-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#ifndef APICast_h
#define APICast_h
-#include "ustring.h"
-#include "ExecState.h"
+#include "JSValue.h"
-namespace KJS {
+namespace JSC {
class ExecState;
- class JSValue;
- class JSObject;
class PropertyNameArray;
+ class JSGlobalData;
+ class JSObject;
+ class JSValuePtr;
}
+typedef const struct OpaqueJSContextGroup* JSContextGroupRef;
typedef const struct OpaqueJSContext* JSContextRef;
typedef struct OpaqueJSContext* JSGlobalContextRef;
-typedef struct OpaqueJSString* JSStringRef;
typedef struct OpaqueJSPropertyNameAccumulator* JSPropertyNameAccumulatorRef;
typedef const struct OpaqueJSValue* JSValueRef;
typedef struct OpaqueJSValue* JSObjectRef;
/* Opaque typing convenience methods */
-inline KJS::ExecState* toJS(JSContextRef c)
-{
- return reinterpret_cast<KJS::ExecState*>(const_cast<OpaqueJSContext*>(c));
-}
-
-inline KJS::ExecState* toJS(JSGlobalContextRef c)
+inline JSC::ExecState* toJS(JSContextRef c)
{
- return reinterpret_cast<KJS::ExecState*>(c);
+ return reinterpret_cast<JSC::ExecState*>(const_cast<OpaqueJSContext*>(c));
}
-inline KJS::JSValue* toJS(JSValueRef v)
+inline JSC::ExecState* toJS(JSGlobalContextRef c)
{
- return reinterpret_cast<KJS::JSValue*>(const_cast<OpaqueJSValue*>(v));
+ return reinterpret_cast<JSC::ExecState*>(c);
}
-inline KJS::UString::Rep* toJS(JSStringRef b)
+inline JSC::JSValuePtr toJS(JSValueRef v)
{
- return reinterpret_cast<KJS::UString::Rep*>(b);
+ return JSC::JSValuePtr::decode(reinterpret_cast<JSC::JSValueEncodedAsPointer*>(const_cast<OpaqueJSValue*>(v)));
}
-inline KJS::JSObject* toJS(JSObjectRef o)
+inline JSC::JSObject* toJS(JSObjectRef o)
{
- return reinterpret_cast<KJS::JSObject*>(o);
+ return reinterpret_cast<JSC::JSObject*>(o);
}
-inline KJS::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a)
+inline JSC::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a)
{
- return reinterpret_cast<KJS::PropertyNameArray*>(a);
+ return reinterpret_cast<JSC::PropertyNameArray*>(a);
}
-inline JSValueRef toRef(KJS::JSValue* v)
+inline JSC::JSGlobalData* toJS(JSContextGroupRef g)
{
- return reinterpret_cast<JSValueRef>(v);
+ return reinterpret_cast<JSC::JSGlobalData*>(const_cast<OpaqueJSContextGroup*>(g));
}
-inline JSValueRef* toRef(KJS::JSValue** v)
+inline JSValueRef toRef(JSC::JSValuePtr v)
{
- return reinterpret_cast<JSValueRef*>(const_cast<const KJS::JSValue**>(v));
+ return reinterpret_cast<JSValueRef>(JSC::JSValuePtr::encode(v));
}
-inline JSStringRef toRef(KJS::UString::Rep* s)
+inline JSValueRef* toRef(JSC::JSValuePtr* v)
{
- return reinterpret_cast<JSStringRef>(s);
+ return reinterpret_cast<JSValueRef*>(v);
}
-inline JSObjectRef toRef(KJS::JSObject* o)
+inline JSObjectRef toRef(JSC::JSObject* o)
{
return reinterpret_cast<JSObjectRef>(o);
}
-inline JSObjectRef toRef(const KJS::JSObject* o)
+inline JSObjectRef toRef(const JSC::JSObject* o)
{
- return reinterpret_cast<JSObjectRef>(const_cast<KJS::JSObject*>(o));
+ return reinterpret_cast<JSObjectRef>(const_cast<JSC::JSObject*>(o));
}
-inline JSContextRef toRef(KJS::ExecState* e)
+inline JSContextRef toRef(JSC::ExecState* e)
{
return reinterpret_cast<JSContextRef>(e);
}
-inline JSGlobalContextRef toGlobalRef(KJS::ExecState* e)
+inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e)
{
- ASSERT(!e->callingExecState());
return reinterpret_cast<JSGlobalContextRef>(e);
}
-inline JSPropertyNameAccumulatorRef toRef(KJS::PropertyNameArray* l)
+inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l)
{
return reinterpret_cast<JSPropertyNameAccumulatorRef>(l);
}
+inline JSContextGroupRef toRef(JSC::JSGlobalData* g)
+{
+ return reinterpret_cast<JSContextGroupRef>(g);
+}
+
#endif // APICast_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSBase.h"
+#include "JSBasePrivate.h"
#include "APICast.h"
+#include "Completion.h"
+#include "OpaqueJSString.h"
#include "SourceCode.h"
-#include <kjs/ExecState.h>
-#include <kjs/JSGlobalObject.h>
-#include <kjs/JSLock.h>
-#include <kjs/interpreter.h>
-#include <kjs/object.h>
+#include <interpreter/CallFrame.h>
+#include <runtime/InitializeThreading.h>
+#include <runtime/Completion.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/JSObject.h>
-using namespace KJS;
+using namespace JSC;
JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsThisObject = toJS(thisObject);
- UString::Rep* scriptRep = toJS(script);
- UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
- SourceCode source = makeSource(UString(scriptRep), UString(sourceURLRep), startingLineNumber);
- // Interpreter::evaluate sets "this" to the global object if it is NULL
- Completion completion = Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), source, jsThisObject);
+
+ // evaluate sets "this" to the global object if it is NULL
+ JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+ SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject);
if (completion.complType() == Throw) {
if (exception)
bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
{
- JSLock lock;
-
ExecState* exec = toJS(ctx);
- UString::Rep* scriptRep = toJS(script);
- UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
- SourceCode source = makeSource(UString(scriptRep), UString(sourceURLRep), startingLineNumber);
- Completion completion = Interpreter::checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
+ Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
if (completion.complType() == Throw) {
if (exception)
*exception = toRef(completion.value());
return true;
}
-void JSGarbageCollect(JSContextRef)
+void JSGarbageCollect(JSContextRef ctx)
{
- JSLock lock;
- if (!Collector::isBusy())
- Collector::collect();
+ // We used to recommend passing NULL as an argument here, which caused the only heap to be collected.
+ // As there is no longer a shared heap, the previously recommended usage became a no-op (but the GC
+ // will happen when the context group is destroyed).
+ // Because the function argument was originally ignored, some clients may pass their released context here,
+ // in which case there is a risk of crashing if another thread performs GC on the same heap in between.
+ if (!ctx)
+ return;
+
+ ExecState* exec = toJS(ctx);
+ JSGlobalData& globalData = exec->globalData();
+
+ JSLock lock(globalData.isSharedInstance);
+
+ if (!globalData.heap.isBusy())
+ globalData.heap.collect();
+
// FIXME: Perhaps we should trigger a second mark and sweep
// once the garbage collector is done if this is called when
// the collector is busy.
}
+
+void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
+{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ exec->globalData().heap.reportExtraMemoryCost(size);
+}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#ifndef JSBase_h
#define JSBase_h
+#ifndef __cplusplus
#include <stdbool.h>
+#endif
/* JavaScript engine interface */
+/*! @typedef JSContextGroupRef A group that associates JavaScript contexts with one another. Contexts in the same group may share and exchange JavaScript objects. */
+typedef const struct OpaqueJSContextGroup* JSContextGroupRef;
+
/*! @typedef JSContextRef A JavaScript execution context. Holds the global object and other execution state. */
typedef const struct OpaqueJSContext* JSContextRef;
#if defined(__GNUC__)
#define JS_EXPORT __attribute__((visibility("default")))
#elif defined(WIN32) || defined(_WIN32)
- // TODO: Export symbols with JS_EXPORT when using MSVC.
- // See http://bugs.webkit.org/show_bug.cgi?id=16227
+ /*
+ * TODO: Export symbols with JS_EXPORT when using MSVC.
+ * See http://bugs.webkit.org/show_bug.cgi?id=16227
+ */
#define JS_EXPORT
#else
#define JS_EXPORT
/* Script Evaluation */
/*!
-@function
+@function JSEvaluateScript
@abstract Evaluates a string of JavaScript.
@param ctx The execution context to use.
@param script A JSString containing the script to evaluate.
JS_EXPORT bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception);
/*!
-@function
+@function JSGarbageCollect
@abstract Performs a JavaScript garbage collection.
-@param ctx This parameter is currently unused. Pass NULL.
+@param ctx The execution context to use.
@discussion JavaScript values that are on the machine stack, in a register,
protected by JSValueProtect, set as the global object of an execution context,
- or reachable from any such value will not be collected.
-
+ or reachable from any such value will not be collected.
+
During JavaScript execution, you are not required to call this function; the
- JavaScript engine will garbage collect as needed. One place you may want to call
- this function, however, is after releasing the last reference to a JSGlobalContextRef.
- At that point, a garbage collection can free the objects still referenced by the
- JSGlobalContextRef's global object, along with the global object itself.
+ JavaScript engine will garbage collect as needed. JavaScript values created
+ within a context group are automatically destroyed when the last reference
+ to the context group is released.
*/
JS_EXPORT void JSGarbageCollect(JSContextRef ctx);
}
#endif
-#endif // JSBase_h
+#endif /* JSBase_h */
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSBasePrivate_h
+#define JSBasePrivate_h
+
+#include <JavaScriptCore/JSBase.h>
+#include <JavaScriptCore/WebKitAvailability.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+@function
+@abstract Reports an object's non-GC memory payload to the garbage collector.
+@param ctx The execution context to use.
+@param size The payload's size, in bytes.
+@discussion Use this function to notify the garbage collector that a GC object
+owns a large non-GC memory region. Calling this function will encourage the
+garbage collector to collect soon, hoping to reclaim that large non-GC memory
+region.
+*/
+JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSBasePrivate_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "JSCallbackConstructor.h"
#include "APICast.h"
-#include <kjs/JSGlobalObject.h>
-#include <kjs/object_object.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/ObjectPrototype.h>
#include <wtf/Vector.h>
-namespace KJS {
+namespace JSC {
-const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0};
+const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 };
-JSCallbackConstructor::JSCallbackConstructor(ExecState* exec, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
- : JSObject(exec->lexicalGlobalObject()->objectPrototype())
+JSCallbackConstructor::JSCallbackConstructor(PassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
+ : JSObject(structure)
, m_class(jsClass)
, m_callback(callback)
{
JSClassRelease(m_class);
}
-bool JSCallbackConstructor::implementsHasInstance() const
-{
- return true;
-}
-
-bool JSCallbackConstructor::implementsConstruct() const
-{
- return true;
-}
-
-JSObject* JSCallbackConstructor::construct(ExecState* exec, const List &args)
+static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, const ArgList& args)
{
JSContextRef ctx = toRef(exec);
- JSObjectRef thisRef = toRef(this);
+ JSObjectRef constructorRef = toRef(constructor);
- if (m_callback) {
+ JSObjectCallAsConstructorCallback callback = static_cast<JSCallbackConstructor*>(constructor)->callback();
+ if (callback) {
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args[i]);
+ arguments[i] = toRef(args.at(exec, i));
- JSLock::DropAllLocks dropAllLocks;
- return toJS(m_callback(ctx, thisRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ JSLock::DropAllLocks dropAllLocks(exec);
+ return toJS(callback(ctx, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
}
- return toJS(JSObjectMake(ctx, m_class, 0));
+ return toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0));
+}
+
+ConstructType JSCallbackConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructJSCallback;
+ return ConstructTypeHost;
}
-} // namespace KJS
+} // namespace JSC
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#define JSCallbackConstructor_h
#include "JSObjectRef.h"
-#include <kjs/object.h>
+#include <runtime/JSObject.h>
-namespace KJS {
+namespace JSC {
-class JSCallbackConstructor : public JSObject
-{
+class JSCallbackConstructor : public JSObject {
public:
- JSCallbackConstructor(ExecState* exec, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback);
+ JSCallbackConstructor(PassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback);
virtual ~JSCallbackConstructor();
-
- virtual bool implementsHasInstance() const;
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List &args);
-
- virtual const ClassInfo *classInfo() const { return &info; }
+ JSClassRef classRef() const { return m_class; }
+ JSObjectCallAsConstructorCallback callback() const { return m_callback; }
static const ClassInfo info;
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ }
+
private:
- JSCallbackConstructor(); // prevent default construction
- JSCallbackConstructor(const JSCallbackConstructor&);
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual const ClassInfo* classInfo() const { return &info; }
JSClassRef m_class;
JSObjectCallAsConstructorCallback m_callback;
};
-} // namespace KJS
+} // namespace JSC
#endif // JSCallbackConstructor_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "JSCallbackFunction.h"
#include "APICast.h"
-#include "function.h"
-#include "function_object.h"
-#include <kjs/JSGlobalObject.h>
+#include "JSFunction.h"
+#include "FunctionPrototype.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
#include <wtf/Vector.h>
-namespace KJS {
+namespace JSC {
-const ClassInfo JSCallbackFunction::info = { "CallbackFunction", &InternalFunctionImp::info, 0};
+ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
+
+const ClassInfo JSCallbackFunction::info = { "CallbackFunction", &InternalFunction::info, 0, 0 };
JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSObjectCallAsFunctionCallback callback, const Identifier& name)
- : InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), name)
+ : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->callbackFunctionStructure(), name)
, m_callback(callback)
{
}
-// InternalFunctionImp mish-mashes constructor and function behavior -- we should
-// refactor the code so this override isn't necessary
-bool JSCallbackFunction::implementsHasInstance() const {
- return false;
-}
-
-JSValue* JSCallbackFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+JSValuePtr JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args)
{
JSContextRef execRef = toRef(exec);
- JSObjectRef thisRef = toRef(this);
- JSObjectRef thisObjRef = toRef(thisObj);
+ JSObjectRef functionRef = toRef(functionObject);
+ JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec));
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args[i]);
+ arguments[i] = toRef(args.at(exec, i));
- JSLock::DropAllLocks dropAllLocks;
- return toJS(m_callback(execRef, thisRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ JSLock::DropAllLocks dropAllLocks(exec);
+ return toJS(static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+}
+
+CallType JSCallbackFunction::getCallData(CallData& callData)
+{
+ callData.native.function = call;
+ return CallTypeHost;
}
-} // namespace KJS
+} // namespace JSC
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#ifndef JSCallbackFunction_h
#define JSCallbackFunction_h
+#include "InternalFunction.h"
#include "JSObjectRef.h"
-#include "function.h"
-#include "object.h"
-namespace KJS {
+namespace JSC {
-class JSCallbackFunction : public InternalFunctionImp
-{
+class JSCallbackFunction : public InternalFunction {
public:
- JSCallbackFunction(ExecState* exec, JSObjectCallAsFunctionCallback callback, const Identifier& name);
+ JSCallbackFunction(ExecState*, JSObjectCallAsFunctionCallback, const Identifier& name);
- virtual bool implementsHasInstance() const;
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List &args);
-
- virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
+ // InternalFunction mish-mashes constructor and function behavior -- we should
+ // refactor the code so this override isn't necessary
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ }
+
private:
- JSCallbackFunction(); // prevent default construction
- JSCallbackFunction(const JSCallbackFunction&);
-
+ virtual CallType getCallData(CallData&);
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ static JSValuePtr call(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
JSObjectCallAsFunctionCallback m_callback;
};
-} // namespace KJS
+} // namespace JSC
#endif // JSCallbackFunction_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
#include "config.h"
#include "JSCallbackObject.h"
-#include "collector.h"
+#include "Collector.h"
-namespace KJS {
+namespace JSC {
-// Define the two types of JSCallbackObjects we support.
-template <> const ClassInfo JSCallbackObject<JSObject>::info = { "CallbackObject", 0, 0 };
-template <> const ClassInfo JSCallbackObject<JSGlobalObject>::info = { "CallbackGlobalObject", 0, 0 };
+ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObject>);
+ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSGlobalObject>);
-COMPILE_ASSERT(sizeof(JSCallbackObject<JSGlobalObject>) <= CELL_SIZE, global_callback_object_fits_in_cell);
+// Define the two types of JSCallbackObjects we support.
+template <> const ClassInfo JSCallbackObject<JSObject>::info = { "CallbackObject", 0, 0, 0 };
+template <> const ClassInfo JSCallbackObject<JSGlobalObject>::info = { "CallbackGlobalObject", 0, 0, 0 };
-} // namespace KJS
+} // namespace JSC
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
#include "JSObjectRef.h"
#include "JSValueRef.h"
-#include "object.h"
+#include "JSObject.h"
-namespace KJS {
+namespace JSC {
template <class Base>
-class JSCallbackObject : public Base
-{
+class JSCallbackObject : public Base {
public:
- JSCallbackObject(ExecState*, JSClassRef, JSValue* prototype, void* data);
+ JSCallbackObject(ExecState*, PassRefPtr<Structure>, JSClassRef, void* data);
JSCallbackObject(JSClassRef);
virtual ~JSCallbackObject();
+ void setPrivate(void* data);
+ void* getPrivate();
+
+ static const ClassInfo info;
+
+ JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
+ bool inherits(JSClassRef) const;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance));
+ }
+
+private:
virtual UString className() const;
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValue*, int attr);
- virtual void put(ExecState*, unsigned, JSValue*, int attr);
+ virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier&);
virtual bool deleteProperty(ExecState*, unsigned);
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List& args);
-
- virtual bool implementsHasInstance() const;
- virtual bool hasInstance(ExecState *exec, JSValue *value);
-
- virtual bool implementsCall() const;
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List &args);
+ virtual bool hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
- void setPrivate(void* data);
- void* getPrivate();
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ virtual const ClassInfo* classInfo() const { return &info; }
- bool inherits(JSClassRef) const;
-
-private:
void init(ExecState*);
+
+ static JSCallbackObject* asCallbackObject(JSValuePtr);
+
+ static JSValuePtr call(ExecState*, JSObject* functionObject, JSValuePtr thisValue, const ArgList&);
+ static JSObject* construct(ExecState*, JSObject* constructor, const ArgList&);
+
+ static JSValuePtr staticValueGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValuePtr staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValuePtr callbackGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ struct JSCallbackObjectData {
+ JSCallbackObjectData(void* privateData, JSClassRef jsClass)
+ : privateData(privateData)
+ , jsClass(jsClass)
+ {
+ JSClassRetain(jsClass);
+ }
+
+ ~JSCallbackObjectData()
+ {
+ JSClassRelease(jsClass);
+ }
+
+ void* privateData;
+ JSClassRef jsClass;
+ };
- static JSValue* cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- static JSValue* staticValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
- static JSValue* staticFunctionGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
- static JSValue* callbackGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
-
- void* m_privateData;
- JSClassRef m_class;
+ OwnPtr<JSCallbackObjectData> m_callbackObjectData;
};
-} // namespace KJS
+} // namespace JSC
// include the actual template class implementation
#include "JSCallbackObjectFunctions.h"
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <wtf/Platform.h>
#include "APICast.h"
+#include "Error.h"
#include "JSCallbackFunction.h"
#include "JSClassRef.h"
-#include "JSObjectRef.h"
#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSObjectRef.h"
+#include "JSString.h"
#include "JSStringRef.h"
+#include "OpaqueJSString.h"
#include "PropertyNameArray.h"
-#include "internal.h"
#include <wtf/Vector.h>
-namespace KJS {
+namespace JSC {
+
+template <class Base>
+inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValuePtr value)
+{
+ ASSERT(asObject(value)->inherits(&info));
+ return static_cast<JSCallbackObject*>(asObject(value));
+}
template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSClassRef jsClass, JSValue* prototype, void* data)
- : Base(prototype)
- , m_privateData(data)
- , m_class(JSClassRetain(jsClass))
+JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
+ : Base(structure)
+ , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
{
init(exec);
}
-// Global object constructor. FIXME: Move this into a JSGlobalCallbackObject subclass.
+// Global object constructor.
+// FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
template <class Base>
JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass)
- : m_privateData(0)
- , m_class(JSClassRetain(jsClass))
+ : Base()
+ , m_callbackObjectData(new JSCallbackObjectData(0, jsClass))
{
ASSERT(Base::isGlobalObject());
init(static_cast<JSGlobalObject*>(this)->globalExec());
ASSERT(exec);
Vector<JSObjectInitializeCallback, 16> initRoutines;
- JSClassRef jsClass = m_class;
+ JSClassRef jsClass = classRef();
do {
if (JSObjectInitializeCallback initialize = jsClass->initialize)
initRoutines.append(initialize);
// initialize from base to derived
for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
- JSLock::DropAllLocks dropAllLocks;
+ JSLock::DropAllLocks dropAllLocks(exec);
JSObjectInitializeCallback initialize = initRoutines[i];
initialize(toRef(exec), toRef(this));
}
{
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
- if (JSObjectFinalizeCallback finalize = jsClass->finalize) {
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
+ if (JSObjectFinalizeCallback finalize = jsClass->finalize)
finalize(thisRef);
- }
-
- JSClassRelease(m_class);
}
template <class Base>
UString JSCallbackObject<Base>::className() const
{
- if (!m_class->className.isNull())
- return m_class->className;
+ UString thisClassName = classRef()->className();
+ if (!thisClassName.isNull())
+ return thisClassName;
return Base::className();
}
{
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
- JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
+ RefPtr<OpaqueJSString> propertyNameRef;
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
// optional optimization to bypass getProperty in cases when we only need to know if the property exists
if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (hasProperty(ctx, thisRef, propertyNameRef)) {
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
slot.setCustom(this, callbackGetter);
return true;
}
} else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
- // cache the value so we don't have to compute it again
- // FIXME: This violates the PropertySlot design a little bit.
- // We should either use this optimization everywhere, or nowhere.
- slot.setCustom(reinterpret_cast<JSObject*>(toJS(value)), cachedValueGetter);
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot()))) {
+ slot.setValue(toJS(value));
return true;
}
}
- if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
+ if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (staticValues->contains(propertyName.ustring().rep())) {
slot.setCustom(this, staticValueGetter);
return true;
}
}
- if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
+ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (staticFunctions->contains(propertyName.ustring().rep())) {
slot.setCustom(this, staticFunctionGetter);
return true;
template <class Base>
bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
- return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
+ return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
template <class Base>
-void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
+void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
{
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
- JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
+ RefPtr<OpaqueJSString> propertyNameRef;
JSValueRef valueRef = toRef(value);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
return;
}
- if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
+ if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
return;
if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
return;
} else
throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
}
}
- if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
+ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
return;
- JSCallbackObject<Base>::putDirect(propertyName, value, attr); // put as override property
+ JSCallbackObject<Base>::putDirect(propertyName, value); // put as override property
return;
}
}
}
- return Base::put(exec, propertyName, value, attr);
-}
-
-template <class Base>
-void JSCallbackObject<Base>::put(ExecState* exec, unsigned propertyName, JSValue* value, int attr)
-{
- return put(exec, Identifier::from(propertyName), value, attr);
+ return Base::put(exec, propertyName, value, slot);
}
template <class Base>
{
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
- JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
+ RefPtr<OpaqueJSString> propertyNameRef;
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (deleteProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (deleteProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
return true;
}
- if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
+ if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
}
}
- if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
+ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
template <class Base>
bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName)
{
- return deleteProperty(exec, Identifier::from(propertyName));
+ return deleteProperty(exec, Identifier::from(exec, propertyName));
}
template <class Base>
-bool JSCallbackObject<Base>::implementsConstruct() const
+ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructData)
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
- if (jsClass->callAsConstructor)
- return true;
-
- return false;
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+ if (jsClass->callAsConstructor) {
+ constructData.native.function = construct;
+ return ConstructTypeHost;
+ }
+ }
+ return ConstructTypeNone;
}
template <class Base>
-JSObject* JSCallbackObject<Base>::construct(ExecState* exec, const List& args)
+JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* constructor, const ArgList& args)
{
JSContextRef execRef = toRef(exec);
- JSObjectRef thisRef = toRef(this);
+ JSObjectRef constructorRef = toRef(constructor);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args[i]);
- JSLock::DropAllLocks dropAllLocks;
- return toJS(callAsConstructor(execRef, thisRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ arguments[i] = toRef(args.at(exec, i));
+ JSLock::DropAllLocks dropAllLocks(exec);
+ return toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
}
}
- ASSERT(0); // implementsConstruct should prevent us from reaching here
+ ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
return 0;
}
template <class Base>
-bool JSCallbackObject<Base>::implementsHasInstance() const
-{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
- if (jsClass->hasInstance)
- return true;
-
- return false;
-}
-
-template <class Base>
-bool JSCallbackObject<Base>::hasInstance(ExecState *exec, JSValue *value)
+bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr)
{
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
- JSLock::DropAllLocks dropAllLocks;
+ JSLock::DropAllLocks dropAllLocks(exec);
return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
}
-
- ASSERT_NOT_REACHED(); // implementsHasInstance should prevent us from reaching here
- return 0;
+ }
+ return false;
}
-
template <class Base>
-bool JSCallbackObject<Base>::implementsCall() const
+CallType JSCallbackObject<Base>::getCallData(CallData& callData)
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
- if (jsClass->callAsFunction)
- return true;
-
- return false;
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+ if (jsClass->callAsFunction) {
+ callData.native.function = call;
+ return CallTypeHost;
+ }
+ }
+ return CallTypeNone;
}
template <class Base>
-JSValue* JSCallbackObject<Base>::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+JSValuePtr JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args)
{
JSContextRef execRef = toRef(exec);
- JSObjectRef thisRef = toRef(this);
- JSObjectRef thisObjRef = toRef(thisObj);
+ JSObjectRef functionRef = toRef(functionObject);
+ JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec));
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(functionObject)->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args[i]);
- JSLock::DropAllLocks dropAllLocks;
- return toJS(callAsFunction(execRef, thisRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ arguments[i] = toRef(args.at(exec, i));
+ JSLock::DropAllLocks dropAllLocks(exec);
+ return toJS(callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
}
}
- ASSERT_NOT_REACHED(); // implementsCall should prevent us from reaching here
- return 0;
+ ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
+ return noValue();
}
template <class Base>
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
- JSLock::DropAllLocks dropAllLocks;
+ JSLock::DropAllLocks dropAllLocks(exec);
getPropertyNames(execRef, thisRef, toRef(&propertyNames));
}
- if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues) {
- typedef OpaqueJSClass::StaticValuesTable::const_iterator iterator;
+ if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
+ typedef OpaqueJSClassStaticValuesTable::const_iterator iterator;
iterator end = staticValues->end();
for (iterator it = staticValues->begin(); it != end; ++it) {
UString::Rep* name = it->first.get();
StaticValueEntry* entry = it->second;
if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
- propertyNames.add(Identifier(name));
+ propertyNames.add(Identifier(exec, name));
}
}
- if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
- typedef OpaqueJSClass::StaticFunctionsTable::const_iterator iterator;
+ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
+ typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator;
iterator end = staticFunctions->end();
for (iterator it = staticFunctions->begin(); it != end; ++it) {
UString::Rep* name = it->first.get();
StaticFunctionEntry* entry = it->second;
if (!(entry->attributes & kJSPropertyAttributeDontEnum))
- propertyNames.add(Identifier(name));
+ propertyNames.add(Identifier(exec, name));
}
}
}
template <class Base>
double JSCallbackObject<Base>::toNumber(ExecState* exec) const
{
+ // We need this check to guard against the case where this object is rhs of
+ // a binary expression where lhs threw an exception in its conversion to
+ // primitive
+ if (exec->hadException())
+ return NaN;
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
- JSLock::DropAllLocks dropAllLocks;
- if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot())))
- return toJS(value)->getNumber();
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot()))) {
+ double dValue;
+ return toJS(value).getNumber(dValue) ? dValue : NaN;
+ }
}
return Base::toNumber(exec);
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
- JSLock::DropAllLocks dropAllLocks;
- if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot())))
- return toJS(value)->getString();
+ JSValueRef value;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot()));
+ }
+ if (value)
+ return toJS(value).getString();
}
return Base::toString(exec);
template <class Base>
void JSCallbackObject<Base>::setPrivate(void* data)
{
- m_privateData = data;
+ m_callbackObjectData->privateData = data;
}
template <class Base>
void* JSCallbackObject<Base>::getPrivate()
{
- return m_privateData;
+ return m_callbackObjectData->privateData;
}
template <class Base>
bool JSCallbackObject<Base>::inherits(JSClassRef c) const
{
- for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
+ for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (jsClass == c)
return true;
}
template <class Base>
-JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- JSValue* v = slot.slotBase();
- ASSERT(v);
- return v;
-}
-
-template <class Base>
-JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+JSValuePtr JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
- ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
- JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
+ JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
JSObjectRef thisRef = toRef(thisObj);
- JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
+ RefPtr<OpaqueJSString> propertyNameRef;
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
- if (OpaqueJSClass::StaticValuesTable* staticValues = jsClass->staticValues)
+ for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
+ if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec))
if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
return toJS(value);
}
}
template <class Base>
-JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+JSValuePtr JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
- ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
- JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
+ JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
// Check for cached or override property.
- PropertySlot slot2;
+ PropertySlot slot2(thisObj);
if (thisObj->Base::getOwnPropertySlot(exec, propertyName, slot2))
- return slot2.getValue(exec, thisObj, propertyName);
+ return slot2.getValue(exec, propertyName);
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
- if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
+ for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
+ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
- JSObject* o = new JSCallbackFunction(exec, callAsFunction, propertyName);
+ JSObject* o = new (exec) JSCallbackFunction(exec, callAsFunction, propertyName);
thisObj->putDirect(propertyName, o, entry->attributes);
return o;
}
}
template <class Base>
-JSValue* JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+JSValuePtr JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
- ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
- JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
+ JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
JSObjectRef thisRef = toRef(thisObj);
- JSStringRef propertyNameRef = toRef(propertyName.ustring().rep());
+ RefPtr<OpaqueJSString> propertyNameRef;
- for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
+ for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
- JSLock::DropAllLocks dropAllLocks;
- if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
+ if (!propertyNameRef)
+ propertyNameRef = OpaqueJSString::create(propertyName.ustring());
+ JSLock::DropAllLocks dropAllLocks(exec);
+ if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
return toJS(value);
}
return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
}
-} // namespace KJS
+} // namespace JSC
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
#include "APICast.h"
#include "JSCallbackObject.h"
#include "JSObjectRef.h"
-#include <kjs/JSGlobalObject.h>
-#include <kjs/identifier.h>
-#include <kjs/object_object.h>
+#include <runtime/InitializeThreading.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/ObjectPrototype.h>
+#include <runtime/Identifier.h>
-using namespace KJS;
+using namespace JSC;
const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
- // FIXME: <rdar://problem/4949018>
- : className(definition->className)
- , parentClass(definition->parentClass)
+ : parentClass(definition->parentClass)
, prototypeClass(0)
- , staticValues(0)
- , staticFunctions(0)
, initialize(definition->initialize)
, finalize(definition->finalize)
, hasProperty(definition->hasProperty)
, callAsConstructor(definition->callAsConstructor)
, hasInstance(definition->hasInstance)
, convertToType(definition->convertToType)
- , cachedPrototype(0)
+ , m_className(UString::Rep::createFromUTF8(definition->className))
+ , m_staticValues(0)
+ , m_staticFunctions(0)
{
+ initializeThreading();
+
if (const JSStaticValue* staticValue = definition->staticValues) {
- staticValues = new StaticValuesTable();
+ m_staticValues = new OpaqueJSClassStaticValuesTable();
while (staticValue->name) {
- // FIXME: <rdar://problem/4949018>
- staticValues->add(Identifier(staticValue->name).ustring().rep(),
+ m_staticValues->add(UString::Rep::createFromUTF8(staticValue->name),
new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes));
++staticValue;
}
}
-
+
if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
- staticFunctions = new StaticFunctionsTable();
+ m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
while (staticFunction->name) {
- // FIXME: <rdar://problem/4949018>
- staticFunctions->add(Identifier(staticFunction->name).ustring().rep(),
+ m_staticFunctions->add(UString::Rep::createFromUTF8(staticFunction->name),
new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes));
++staticFunction;
}
OpaqueJSClass::~OpaqueJSClass()
{
- if (staticValues) {
- deleteAllValues(*staticValues);
- delete staticValues;
+ ASSERT(!m_className.rep()->identifierTable());
+
+ if (m_staticValues) {
+ OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
+ for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
+ ASSERT(!it->first->identifierTable());
+ delete it->second;
+ }
+ delete m_staticValues;
}
- if (staticFunctions) {
- deleteAllValues(*staticFunctions);
- delete staticFunctions;
+ if (m_staticFunctions) {
+ OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
+ for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
+ ASSERT(!it->first->identifierTable());
+ delete it->second;
+ }
+ delete m_staticFunctions;
}
if (prototypeClass)
JSClassRelease(prototypeClass);
}
-JSClassRef OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
+PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition)
{
- return new OpaqueJSClass(definition, 0);
+ return adoptRef(new OpaqueJSClass(definition, 0));
}
-void clearReferenceToPrototype(JSObjectRef prototype)
+static void clearReferenceToPrototype(JSObjectRef prototype)
{
- OpaqueJSClass* jsClass = static_cast<OpaqueJSClass*>(JSObjectGetPrivate(prototype));
- ASSERT(jsClass);
- jsClass->cachedPrototype = 0;
+ OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
+ ASSERT(jsClassData);
+ jsClassData->cachedPrototype = 0;
}
-JSClassRef OpaqueJSClass::create(const JSClassDefinition* definition)
+PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* definition)
{
if (const JSStaticFunction* staticFunctions = definition->staticFunctions) {
// copy functions into a prototype class
JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
protoDefinition.staticFunctions = staticFunctions;
protoDefinition.finalize = clearReferenceToPrototype;
- OpaqueJSClass* protoClass = new OpaqueJSClass(&protoDefinition, 0);
+
+ // We are supposed to use JSClassRetain/Release but since we know that we currently have
+ // the only reference to this class object we cheat and use a RefPtr instead.
+ RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
// remove functions from the original class
JSClassDefinition objectDefinition = *definition;
objectDefinition.staticFunctions = 0;
- return new OpaqueJSClass(&objectDefinition, protoClass);
+
+ return adoptRef(new OpaqueJSClass(&objectDefinition, protoClass.get()));
+ }
+
+ return adoptRef(new OpaqueJSClass(definition, 0));
+}
+
+OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
+ : m_class(jsClass)
+ , cachedPrototype(0)
+{
+ if (jsClass->m_staticValues) {
+ staticValues = new OpaqueJSClassStaticValuesTable;
+ OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
+ for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
+ ASSERT(!it->first->identifierTable());
+ staticValues->add(UString::Rep::createCopying(it->first->data(), it->first->size()),
+ new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes));
+ }
+
+ } else
+ staticValues = 0;
+
+
+ if (jsClass->m_staticFunctions) {
+ staticFunctions = new OpaqueJSClassStaticFunctionsTable;
+ OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
+ for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
+ ASSERT(!it->first->identifierTable());
+ staticFunctions->add(UString::Rep::createCopying(it->first->data(), it->first->size()),
+ new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes));
+ }
+
+ } else
+ staticFunctions = 0;
+}
+
+OpaqueJSClassContextData::~OpaqueJSClassContextData()
+{
+ if (staticValues) {
+ deleteAllValues(*staticValues);
+ delete staticValues;
}
- return new OpaqueJSClass(definition, 0);
+ if (staticFunctions) {
+ deleteAllValues(*staticFunctions);
+ delete staticFunctions;
+ }
+}
+
+OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
+{
+ OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
+ if (!contextData)
+ contextData = new OpaqueJSClassContextData(this);
+ return *contextData;
+}
+
+UString OpaqueJSClass::className()
+{
+ // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable.
+ return UString(m_className.data(), m_className.size());
+}
+
+OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
+{
+ OpaqueJSClassContextData& jsClassData = contextData(exec);
+ return jsClassData.staticValues;
+}
+
+OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
+{
+ OpaqueJSClassContextData& jsClassData = contextData(exec);
+ return jsClassData.staticFunctions;
}
/*!
@param jsClass A JSClass whose prototype you want to get.
@result The JSObject prototype that was automatically generated for jsClass, or NULL if no prototype was automatically generated. This is the prototype that will be used when constructing an object using jsClass.
*/
-JSObject* OpaqueJSClass::prototype(JSContextRef ctx)
+JSObject* OpaqueJSClass::prototype(ExecState* exec)
{
/* Class (C++) and prototype (JS) inheritance are parallel, so:
* (C++) | (JS)
if (!prototypeClass)
return 0;
-
- ExecState* exec = toJS(ctx);
-
- if (!cachedPrototype) {
+
+ OpaqueJSClassContextData& jsClassData = contextData(exec);
+
+ if (!jsClassData.cachedPrototype) {
// Recursive, but should be good enough for our purposes
- JSObject* parentPrototype = 0;
- if (parentClass)
- parentPrototype = parentClass->prototype(ctx); // can be null
- if (!parentPrototype)
- parentPrototype = exec->dynamicGlobalObject()->objectPrototype();
- cachedPrototype = new JSCallbackObject<JSObject>(exec, prototypeClass, parentPrototype, this); // set ourself as the object's private data, so it can clear our reference on destruction
+ jsClassData.cachedPrototype = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
+ if (parentClass) {
+ if (JSObject* prototype = parentClass->prototype(exec))
+ jsClassData.cachedPrototype->setPrototype(prototype);
+ }
}
- return cachedPrototype;
+ return jsClassData.cachedPrototype;
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#include "JSObjectRef.h"
-#include <kjs/object.h>
-#include <kjs/protect.h>
-#include <kjs/ustring.h>
+#include <runtime/JSObject.h>
+#include <runtime/Protect.h>
+#include <runtime/UString.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
JSPropertyAttributes attributes;
};
-struct OpaqueJSClass : public RefCounted<OpaqueJSClass> {
- static OpaqueJSClass* create(const JSClassDefinition*);
- static OpaqueJSClass* createNoAutomaticPrototype(const JSClassDefinition*);
+typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
+typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
+
+class OpaqueJSClass;
+
+// An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups.
+// This structure holds data members that vary across context groups.
+struct OpaqueJSClassContextData : Noncopyable {
+ OpaqueJSClassContextData(OpaqueJSClass*);
+ ~OpaqueJSClassContextData();
+
+ // It is necessary to keep OpaqueJSClass alive because of the following rare scenario:
+ // 1. A class is created and used, so its context data is stored in JSGlobalData hash map.
+ // 2. The class is released, and when all JS objects that use it are collected, OpaqueJSClass
+ // is deleted (that's the part prevented by this RefPtr).
+ // 3. Another class is created at the same address.
+ // 4. When it is used, the old context data is found in JSGlobalData and used.
+ RefPtr<OpaqueJSClass> m_class;
+
+ OpaqueJSClassStaticValuesTable* staticValues;
+ OpaqueJSClassStaticFunctionsTable* staticFunctions;
+ JSC::JSObject* cachedPrototype;
+};
+
+struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> {
+ static PassRefPtr<OpaqueJSClass> create(const JSClassDefinition*);
+ static PassRefPtr<OpaqueJSClass> createNoAutomaticPrototype(const JSClassDefinition*);
~OpaqueJSClass();
- KJS::JSObject* prototype(JSContextRef ctx);
-
- typedef HashMap<RefPtr<KJS::UString::Rep>, StaticValueEntry*> StaticValuesTable;
- typedef HashMap<RefPtr<KJS::UString::Rep>, StaticFunctionEntry*> StaticFunctionsTable;
+ JSC::UString className();
+ OpaqueJSClassStaticValuesTable* staticValues(JSC::ExecState*);
+ OpaqueJSClassStaticFunctionsTable* staticFunctions(JSC::ExecState*);
+ JSC::JSObject* prototype(JSC::ExecState*);
- KJS::UString className;
OpaqueJSClass* parentClass;
OpaqueJSClass* prototypeClass;
-
- StaticValuesTable* staticValues;
- StaticFunctionsTable* staticFunctions;
JSObjectInitializeCallback initialize;
JSObjectFinalizeCallback finalize;
JSObjectConvertToTypeCallback convertToType;
private:
+ friend struct OpaqueJSClassContextData;
+
OpaqueJSClass();
OpaqueJSClass(const OpaqueJSClass&);
OpaqueJSClass(const JSClassDefinition*, OpaqueJSClass* protoClass);
-
- friend void clearReferenceToPrototype(JSObjectRef prototype);
- KJS::JSObject* cachedPrototype;
+
+ OpaqueJSClassContextData& contextData(JSC::ExecState*);
+
+ // UStrings in these data members should not be put into any IdentifierTable.
+ JSC::UString m_className;
+ OpaqueJSClassStaticValuesTable* m_staticValues;
+ OpaqueJSClassStaticFunctionsTable* m_staticFunctions;
};
#endif // JSClassRef_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
#include "JSContextRef.h"
#include "APICast.h"
+#include "InitializeThreading.h"
#include "JSCallbackObject.h"
#include "JSClassRef.h"
#include "JSGlobalObject.h"
-#include "object.h"
+#include "JSObject.h"
#include <wtf/Platform.h>
-using namespace KJS;
+#if PLATFORM(DARWIN)
+#include <mach-o/dyld.h>
+
+static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
+#endif
+
+using namespace JSC;
+
+JSContextGroupRef JSContextGroupCreate()
+{
+ initializeThreading();
+ return toRef(JSGlobalData::create().releaseRef());
+}
+
+JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
+{
+ toJS(group)->ref();
+ return group;
+}
+
+void JSContextGroupRelease(JSContextGroupRef group)
+{
+ toJS(group)->deref();
+}
JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
{
- JSLock lock;
+ initializeThreading();
+#if PLATFORM(DARWIN)
+ // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
+ // to use a unique JSGlobalData, we use a shared one for compatibility.
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
+#else
+ {
+#endif
+ JSLock lock(true);
+ return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
+ }
+#endif // PLATFORM(DARWIN)
+
+ return JSGlobalContextCreateInGroup(0, globalObjectClass);
+}
+
+JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass)
+{
+ initializeThreading();
+
+ JSLock lock(true);
+
+ RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create();
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ globalData->makeUsableFromMultipleThreads();
+#endif
if (!globalObjectClass) {
- JSGlobalObject* globalObject = new JSGlobalObject;
+ JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject;
return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
}
- JSGlobalObject* globalObject = new JSCallbackObject<JSGlobalObject>(globalObjectClass);
- JSGlobalContextRef ctx = toGlobalRef(globalObject->globalExec());
- JSValue* prototype = globalObjectClass->prototype(ctx);
+ JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass);
+ ExecState* exec = globalObject->globalExec();
+ JSValuePtr prototype = globalObjectClass->prototype(exec);
if (!prototype)
prototype = jsNull();
- globalObject->reset(prototype);
- return JSGlobalContextRetain(ctx);
+ globalObject->resetPrototype(prototype);
+ return JSGlobalContextRetain(toGlobalRef(exec));
}
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ JSLock lock(exec);
+
+ JSGlobalData& globalData = exec->globalData();
+
+ globalData.heap.registerThread();
+
gcProtect(exec->dynamicGlobalObject());
+ globalData.ref();
return ctx;
}
void JSGlobalContextRelease(JSGlobalContextRef ctx)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ JSLock lock(exec);
+
gcUnprotect(exec->dynamicGlobalObject());
+
+ JSGlobalData& globalData = exec->globalData();
+ if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
+ // The last reference was released, this is our last chance to collect.
+ ASSERT(!globalData.heap.protectedObjectCount());
+ ASSERT(!globalData.heap.isBusy());
+ globalData.heap.destroy();
+ } else
+ globalData.heap.collect();
+
+ globalData.deref();
}
JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
{
ExecState* exec = toJS(ctx);
- return toRef(exec->dynamicGlobalObject());
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
+ return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
+}
+
+JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
+{
+ ExecState* exec = toJS(ctx);
+ return toRef(&exec->globalData());
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#include <JavaScriptCore/JSObjectRef.h>
#include <JavaScriptCore/JSValueRef.h>
+#include <JavaScriptCore/WebKitAvailability.h>
+#ifndef __cplusplus
#include <stdbool.h>
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+/*!
+@function
+@abstract Creates a JavaScript context group.
+@discussion A JSContextGroup associates JavaScript contexts with one another.
+ Contexts in the same group may share and exchange JavaScript objects. Sharing and/or exchanging
+ JavaScript objects between contexts in different groups will produce undefined behavior.
+ When objects from the same context group are used in multiple threads, explicit
+ synchronization is required.
+@result The created JSContextGroup.
+*/
+JS_EXPORT JSContextGroupRef JSContextGroupCreate() AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
+@abstract Retains a JavaScript context group.
+@param group The JSContextGroup to retain.
+@result A JSContextGroup that is the same as group.
+*/
+JS_EXPORT JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
+@abstract Releases a JavaScript context group.
+@param group The JSContextGroup to release.
+*/
+JS_EXPORT void JSContextGroupRelease(JSContextGroupRef group) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
/*!
@function
@abstract Creates a global JavaScript execution context.
@discussion JSGlobalContextCreate allocates a global object and populates it with all the
built-in JavaScript objects, such as Object, Function, String, and Array.
+
+ In WebKit version 4.0 and later, the context is created in a unique context group.
+ Therefore, scripts may execute in it concurrently with scripts executing in other contexts.
+ However, you may not use values created in the context in other contexts.
@param globalObjectClass The class to use when creating the global object. Pass
NULL to use the default object class.
@result A JSGlobalContext with a global object of class globalObjectClass.
*/
-JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass);
+JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER;
+
+/*!
+@function
+@abstract Creates a global JavaScript execution context in the context group provided.
+@discussion JSGlobalContextCreateInGroup allocates a global object and populates it with
+ all the built-in JavaScript objects, such as Object, Function, String, and Array.
+@param globalObjectClass The class to use when creating the global object. Pass
+ NULL to use the default object class.
+@param group The context group to use. The created global context retains the group.
+ Pass NULL to create a unique group for the context.
+@result A JSGlobalContext with a global object of class globalObjectClass and a context
+ group equal to group.
+*/
+JS_EXPORT JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
/*!
@function
*/
JS_EXPORT JSObjectRef JSContextGetGlobalObject(JSContextRef ctx);
+/*!
+@function
+@abstract Gets the context group to which a JavaScript execution context belongs.
+@param ctx The JSContext whose group you want to get.
+@result ctx's group.
+*/
+JS_EXPORT JSContextGroupRef JSContextGetGroup(JSContextRef ctx) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
#ifdef __cplusplus
}
#endif
-#endif // JSContextRef_h
+#endif /* JSContextRef_h */
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "JSNode.h"
-#include "JSNodeList.h"
-#include "JSObjectRef.h"
-#include "JSStringRef.h"
-#include "JSValueRef.h"
-#include "Node.h"
-#include "NodeList.h"
-#include "UnusedParam.h"
-#include <wtf/Assertions.h>
-
-static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
-
- // Example of throwing a type error for invalid values
- if (!JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
- JSStringRef message = JSStringCreateWithUTF8CString("TypeError: appendChild can only be called on nodes");
- *exception = JSValueMakeString(context, message);
- JSStringRelease(message);
- } else if (argumentCount < 1 || !JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
- JSStringRef message = JSStringCreateWithUTF8CString("TypeError: first argument to appendChild must be a node");
- *exception = JSValueMakeString(context, message);
- JSStringRelease(message);
- } else {
- Node* node = JSObjectGetPrivate(thisObject);
- Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], NULL));
-
- Node_appendChild(node, child);
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef JSNode_removeChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
-
- // Example of ignoring invalid values
- if (argumentCount > 0) {
- if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
- if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
- Node* node = JSObjectGetPrivate(thisObject);
- Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception));
-
- Node_removeChild(node, child);
- }
- }
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef JSNode_replaceChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
-
- if (argumentCount > 1) {
- if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
- if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
- if (JSValueIsObjectOfClass(context, arguments[1], JSNode_class(context))) {
- Node* node = JSObjectGetPrivate(thisObject);
- Node* newChild = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception));
- Node* oldChild = JSObjectGetPrivate(JSValueToObject(context, arguments[1], exception));
-
- Node_replaceChild(node, newChild, oldChild);
- }
- }
- }
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticFunction JSNode_staticFunctions[] = {
- { "appendChild", JSNode_appendChild, kJSPropertyAttributeDontDelete },
- { "removeChild", JSNode_removeChild, kJSPropertyAttributeDontDelete },
- { "replaceChild", JSNode_replaceChild, kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
-};
-
-static JSValueRef JSNode_getNodeType(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- Node* node = JSObjectGetPrivate(object);
- if (node) {
- JSStringRef nodeType = JSStringCreateWithUTF8CString(node->nodeType);
- JSValueRef value = JSValueMakeString(context, nodeType);
- JSStringRelease(nodeType);
- return value;
- }
-
- return NULL;
-}
-
-static JSValueRef JSNode_getChildNodes(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- Node* node = JSObjectGetPrivate(thisObject);
- ASSERT(node);
- return JSNodeList_new(context, NodeList_new(node));
-}
-
-static JSValueRef JSNode_getFirstChild(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticValue JSNode_staticValues[] = {
- { "nodeType", JSNode_getNodeType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
- { "childNodes", JSNode_getChildNodes, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
- { "firstChild", JSNode_getFirstChild, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
- { 0, 0, 0, 0 }
-};
-
-static void JSNode_initialize(JSContextRef context, JSObjectRef object)
-{
- UNUSED_PARAM(context);
-
- Node* node = JSObjectGetPrivate(object);
- ASSERT(node);
-
- Node_ref(node);
-}
-
-static void JSNode_finalize(JSObjectRef object)
-{
- Node* node = JSObjectGetPrivate(object);
- ASSERT(node);
-
- Node_deref(node);
-}
-
-JSClassRef JSNode_class(JSContextRef context)
-{
- UNUSED_PARAM(context);
-
- static JSClassRef jsClass;
- if (!jsClass) {
- JSClassDefinition definition = kJSClassDefinitionEmpty;
- definition.staticValues = JSNode_staticValues;
- definition.staticFunctions = JSNode_staticFunctions;
- definition.initialize = JSNode_initialize;
- definition.finalize = JSNode_finalize;
-
- jsClass = JSClassCreate(&definition);
- }
- return jsClass;
-}
-
-JSObjectRef JSNode_new(JSContextRef context, Node* node)
-{
- return JSObjectMake(context, JSNode_class(context), node);
-}
-
-JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(argumentCount);
- UNUSED_PARAM(arguments);
- UNUSED_PARAM(exception);
-
- return JSNode_new(context, Node_new());
-}
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSNode_h
-#define JSNode_h
-
-#include "JSBase.h"
-#include "Node.h"
-#include <stddef.h>
-
-extern JSObjectRef JSNode_new(JSContextRef context, Node* node);
-extern JSClassRef JSNode_class(JSContextRef context);
-extern JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
-
-#endif // JSNode_h
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "JSNode.h"
-#include "JSNodeList.h"
-#include "JSObjectRef.h"
-#include "JSValueRef.h"
-#include "UnusedParam.h"
-#include <wtf/Assertions.h>
-
-static JSValueRef JSNodeList_item(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(object);
-
- if (argumentCount > 0) {
- NodeList* nodeList = JSObjectGetPrivate(thisObject);
- ASSERT(nodeList);
- Node* node = NodeList_item(nodeList, (unsigned)JSValueToNumber(context, arguments[0], exception));
- if (node)
- return JSNode_new(context, node);
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticFunction JSNodeList_staticFunctions[] = {
- { "item", JSNodeList_item, kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
-};
-
-static JSValueRef JSNodeList_length(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- NodeList* nodeList = JSObjectGetPrivate(thisObject);
- ASSERT(nodeList);
- return JSValueMakeNumber(context, NodeList_length(nodeList));
-}
-
-static JSStaticValue JSNodeList_staticValues[] = {
- { "length", JSNodeList_length, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { 0, 0, 0, 0 }
-};
-
-static JSValueRef JSNodeList_getProperty(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
-{
- NodeList* nodeList = JSObjectGetPrivate(thisObject);
- ASSERT(nodeList);
- double index = JSValueToNumber(context, JSValueMakeString(context, propertyName), exception);
- unsigned uindex = (unsigned)index;
- if (uindex == index) { // false for NaN
- Node* node = NodeList_item(nodeList, uindex);
- if (node)
- return JSNode_new(context, node);
- }
-
- return NULL;
-}
-
-static void JSNodeList_initialize(JSContextRef context, JSObjectRef thisObject)
-{
- UNUSED_PARAM(context);
-
- NodeList* nodeList = JSObjectGetPrivate(thisObject);
- ASSERT(nodeList);
-
- NodeList_ref(nodeList);
-}
-
-static void JSNodeList_finalize(JSObjectRef thisObject)
-{
- NodeList* nodeList = JSObjectGetPrivate(thisObject);
- ASSERT(nodeList);
-
- NodeList_deref(nodeList);
-}
-
-static JSClassRef JSNodeList_class(JSContextRef context)
-{
- UNUSED_PARAM(context);
-
- static JSClassRef jsClass;
- if (!jsClass) {
- JSClassDefinition definition = kJSClassDefinitionEmpty;
- definition.staticValues = JSNodeList_staticValues;
- definition.staticFunctions = JSNodeList_staticFunctions;
- definition.getProperty = JSNodeList_getProperty;
- definition.initialize = JSNodeList_initialize;
- definition.finalize = JSNodeList_finalize;
-
- jsClass = JSClassCreate(&definition);
- }
-
- return jsClass;
-}
-
-JSObjectRef JSNodeList_new(JSContextRef context, NodeList* nodeList)
-{
- return JSObjectMake(context, JSNodeList_class(context), nodeList);
-}
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSNodeList_h
-#define JSNodeList_h
-
-#include "JSBase.h"
-#include "NodeList.h"
-
-extern JSObjectRef JSNodeList_new(JSContextRef, NodeList*);
-
-#endif // JSNodeList_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "config.h"
#include "JSObjectRef.h"
-#include <wtf/Platform.h>
#include "APICast.h"
-#include "JSValueRef.h"
+#include "DateConstructor.h"
+#include "ErrorConstructor.h"
+#include "FunctionConstructor.h"
+#include "Identifier.h"
+#include "InitializeThreading.h"
+#include "JSArray.h"
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
#include "JSCallbackObject.h"
#include "JSClassRef.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
-
+#include "JSObject.h"
+#include "JSRetainPtr.h"
+#include "JSString.h"
+#include "JSValueRef.h"
+#include "ObjectPrototype.h"
#include "PropertyNameArray.h"
-#include "function.h"
-#include "function_object.h"
-#include "identifier.h"
-#include "internal.h"
-#include "object.h"
-#include "object_object.h"
+#include "RegExpConstructor.h"
+#include <wtf/Platform.h>
-using namespace KJS;
+using namespace JSC;
JSClassRef JSClassCreate(const JSClassDefinition* definition)
{
- JSLock lock;
- JSClassRef jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
+ initializeThreading();
+ RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
? OpaqueJSClass::createNoAutomaticPrototype(definition)
: OpaqueJSClass::create(definition);
- return JSClassRetain(jsClass);
+ return jsClass.release().releaseRef();
}
JSClassRef JSClassRetain(JSClassRef jsClass)
{
- JSLock lock;
jsClass->ref();
return jsClass;
}
void JSClassRelease(JSClassRef jsClass)
{
- JSLock lock;
jsClass->deref();
}
JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
if (!jsClass)
- return toRef(new JSObject(exec->lexicalGlobalObject()->objectPrototype())); // slightly more efficient
+ return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
- JSValue* jsPrototype = jsClass->prototype(ctx);
- if (!jsPrototype)
- jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
+ JSCallbackObject<JSObject>* object = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
+ if (JSObject* prototype = jsClass->prototype(exec))
+ object->setPrototype(prototype);
- return toRef(new JSCallbackObject<JSObject>(exec, jsClass, jsPrototype, data));
+ return toRef(object);
}
JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
- Identifier nameID = name ? Identifier(toJS(name)) : Identifier("anonymous");
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
- return toRef(new JSCallbackFunction(exec, callAsFunction, nameID));
+ return toRef(new (exec) JSCallbackFunction(exec, callAsFunction, nameID));
}
JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsPrototype = jsClass
+ ? jsClass->prototype(exec)
+ : exec->lexicalGlobalObject()->objectPrototype();
- JSValue* jsPrototype = jsClass
- ? jsClass->prototype(ctx)
- : exec->dynamicGlobalObject()->objectPrototype();
-
- JSCallbackConstructor* constructor = new JSCallbackConstructor(exec, jsClass, callAsConstructor);
+ JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
return toRef(constructor);
}
JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
{
- JSLock lock;
-
ExecState* exec = toJS(ctx);
- UString::Rep* bodyRep = toJS(body);
- UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
-
- Identifier nameID = name ? Identifier(toJS(name)) : Identifier("anonymous");
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
- List args;
+ ArgList args;
for (unsigned i = 0; i < parameterCount; i++)
- args.append(jsString(UString(toJS(parameterNames[i]))));
- args.append(jsString(UString(bodyRep)));
+ args.append(jsString(exec, parameterNames[i]->ustring()));
+ args.append(jsString(exec, body->ustring()));
+
+ JSObject* result = constructFunction(exec, args, nameID, sourceURL->ustring(), startingLineNumber);
+ if (exec->hadException()) {
+ if (exception)
+ *exception = toRef(exec->exception());
+ exec->clearException();
+ result = 0;
+ }
+ return toRef(result);
+}
+
+JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSObject* result;
+ if (argumentCount) {
+ ArgList argList;
+ for (size_t i = 0; i < argumentCount; ++i)
+ argList.append(toJS(arguments[i]));
+
+ result = constructArray(exec, argList);
+ } else
+ result = constructEmptyArray(exec);
- JSObject* result = exec->dynamicGlobalObject()->functionConstructor()->construct(exec, args, nameID, UString(sourceURLRep), startingLineNumber);
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
exec->clearException();
result = 0;
}
+
+ return toRef(result);
+}
+
+JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ ArgList argList;
+ for (size_t i = 0; i < argumentCount; ++i)
+ argList.append(toJS(arguments[i]));
+
+ JSObject* result = constructDate(exec, argList);
+ if (exec->hadException()) {
+ if (exception)
+ *exception = toRef(exec->exception());
+ exec->clearException();
+ result = 0;
+ }
+
+ return toRef(result);
+}
+
+JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ ArgList argList;
+ for (size_t i = 0; i < argumentCount; ++i)
+ argList.append(toJS(arguments[i]));
+
+ JSObject* result = constructError(exec, argList);
+ if (exec->hadException()) {
+ if (exception)
+ *exception = toRef(exec->exception());
+ exec->clearException();
+ result = 0;
+ }
+
+ return toRef(result);
+}
+
+JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ ArgList argList;
+ for (size_t i = 0; i < argumentCount; ++i)
+ argList.append(toJS(arguments[i]));
+
+ JSObject* result = constructRegExp(exec, argList);
+ if (exec->hadException()) {
+ if (exception)
+ *exception = toRef(exec->exception());
+ exec->clearException();
+ result = 0;
+ }
+
return toRef(result);
}
void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value)
{
JSObject* jsObject = toJS(object);
- JSValue* jsValue = toJS(value);
+ JSValuePtr jsValue = toJS(value);
- jsObject->setPrototype(jsValue);
+ jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull());
}
bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- UString::Rep* nameRep = toJS(propertyName);
- return jsObject->hasProperty(exec, Identifier(nameRep));
+ return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData()));
}
JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- UString::Rep* nameRep = toJS(propertyName);
- JSValue* jsValue = jsObject->get(exec, Identifier(nameRep));
+ JSValuePtr jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- UString::Rep* nameRep = toJS(propertyName);
- JSValue* jsValue = toJS(value);
-
- jsObject->put(exec, Identifier(nameRep), jsValue, attributes);
+ Identifier name(propertyName->identifier(&exec->globalData()));
+ JSValuePtr jsValue = toJS(value);
+
+ if (attributes && !jsObject->hasProperty(exec, name))
+ jsObject->putWithAttributes(exec, name, jsValue, attributes);
+ else {
+ PutPropertySlot slot;
+ jsObject->put(exec, name, jsValue, slot);
+ }
+
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- JSValue* jsValue = jsObject->get(exec, propertyIndex);
+ JSValuePtr jsValue = jsObject->get(exec, propertyIndex);
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- JSValue* jsValue = toJS(value);
+ JSValuePtr jsValue = toJS(value);
jsObject->put(exec, propertyIndex, jsValue);
if (exec->hadException()) {
bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- UString::Rep* nameRep = toJS(propertyName);
- bool result = jsObject->deleteProperty(exec, Identifier(nameRep));
+ bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
{
- JSObject* jsObject = toJS(object);
- return jsObject->implementsCall();
+ CallData callData;
+ return toJS(object)->getCallData(callData) != CallTypeNone;
}
JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
JSObject* jsThisObject = toJS(thisObject);
if (!jsThisObject)
- jsThisObject = exec->dynamicGlobalObject();
-
- List argList;
+ jsThisObject = exec->globalThisValue();
+
+ ArgList argList;
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(arguments[i]));
- JSValueRef result = toRef(jsObject->call(exec, jsThisObject, argList)); // returns NULL if object->implementsCall() is false
+ CallData callData;
+ CallType callType = jsObject->getCallData(callData);
+ if (callType == CallTypeNone)
+ return 0;
+
+ JSValueRef result = toRef(call(exec, jsObject, callType, callData, jsThisObject, argList));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
{
JSObject* jsObject = toJS(object);
- return jsObject->implementsConstruct();
+ ConstructData constructData;
+ return jsObject->getConstructData(constructData) != ConstructTypeNone;
}
JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
-
- List argList;
+
+ ConstructData constructData;
+ ConstructType constructType = jsObject->getConstructData(constructData);
+ if (constructType == ConstructTypeNone)
+ return 0;
+
+ ArgList argList;
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(arguments[i]));
-
- JSObjectRef result = toRef(jsObject->construct(exec, argList)); // returns NULL if object->implementsCall() is false
+ JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
return result;
}
-struct OpaqueJSPropertyNameArray
-{
- OpaqueJSPropertyNameArray() : refCount(0)
+struct OpaqueJSPropertyNameArray {
+ OpaqueJSPropertyNameArray(JSGlobalData* globalData)
+ : refCount(0)
+ , globalData(globalData)
{
}
unsigned refCount;
- PropertyNameArray array;
+ JSGlobalData* globalData;
+ Vector<JSRetainPtr<JSStringRef> > array;
};
JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
{
- JSLock lock;
JSObject* jsObject = toJS(object);
ExecState* exec = toJS(ctx);
-
- JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray();
- jsObject->getPropertyNames(exec, propertyNames->array);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSGlobalData* globalData = &exec->globalData();
+
+ JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
+ PropertyNameArray array(globalData);
+ jsObject->getPropertyNames(exec, array);
+
+ size_t size = array.size();
+ propertyNames->array.reserveInitialCapacity(size);
+ for (size_t i = 0; i < size; ++i)
+ propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).releaseRef()));
return JSPropertyNameArrayRetain(propertyNames);
}
JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
{
- JSLock lock;
++array->refCount;
return array;
}
void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
{
- JSLock lock;
- if (--array->refCount == 0)
+ if (--array->refCount == 0) {
+ JSLock lock(array->globalData->isSharedInstance);
delete array;
+ }
}
size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
{
- return toRef(array->array[static_cast<unsigned>(index)].ustring().rep());
+ return array->array[static_cast<unsigned>(index)].get();
}
void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
{
- JSLock lock;
PropertyNameArray* propertyNames = toJS(array);
- UString::Rep* rep = toJS(propertyName);
-
- propertyNames->add(Identifier(rep));
+
+ propertyNames->globalData()->heap.registerThread();
+ JSLock lock(propertyNames->globalData()->isSharedInstance);
+
+ propertyNames->add(propertyName->identifier(propertyNames->globalData()));
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include <JavaScriptCore/JSBase.h>
#include <JavaScriptCore/JSValueRef.h>
+#include <JavaScriptCore/WebKitAvailability.h>
+#ifndef __cplusplus
#include <stdbool.h>
-#include <stddef.h> // for size_t
+#endif
+#include <stddef.h> /* for size_t */
#ifdef __cplusplus
extern "C" {
A NULL callback specifies that the default object callback should substitute, except in the case of hasProperty, where it specifies that getProperty should substitute.
*/
typedef struct {
- int version; // current (and only) version is 0
+ int version; /* current (and only) version is 0 */
JSClassAttributes attributes;
const char* className;
*/
JS_EXPORT JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor);
+/*!
+ @function
+ @abstract Creates a JavaScript Array object.
+ @param ctx The execution context to use.
+ @param argumentCount An integer count of the number of arguments in arguments.
+ @param arguments A JSValue array of data to populate the Array with. Pass NULL if argumentCount is 0.
+ @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result A JSObject that is an Array.
+ @discussion The behavior of this function does not exactly match the behavior of the built-in Array constructor. Specifically, if one argument
+ is supplied, this function returns an array with one element.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+ @function
+ @abstract Creates a JavaScript Date object, as if by invoking the built-in Date constructor.
+ @param ctx The execution context to use.
+ @param argumentCount An integer count of the number of arguments in arguments.
+ @param arguments A JSValue array of arguments to pass to the Date Constructor. Pass NULL if argumentCount is 0.
+ @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result A JSObject that is a Date.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+ @function
+ @abstract Creates a JavaScript Error object, as if by invoking the built-in Error constructor.
+ @param ctx The execution context to use.
+ @param argumentCount An integer count of the number of arguments in arguments.
+ @param arguments A JSValue array of arguments to pass to the Error Constructor. Pass NULL if argumentCount is 0.
+ @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result A JSObject that is a Error.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+ @function
+ @abstract Creates a JavaScript RegExp object, as if by invoking the built-in RegExp constructor.
+ @param ctx The execution context to use.
+ @param argumentCount An integer count of the number of arguments in arguments.
+ @param arguments A JSValue array of arguments to pass to the RegExp Constructor. Pass NULL if argumentCount is 0.
+ @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result A JSObject that is a RegExp.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
/*!
@function
@abstract Creates a function with a given script as its body.
}
#endif
-#endif // JSObjectRef_h
+#endif /* JSObjectRef_h */
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSProfilerPrivate.h"
+
+#include "APICast.h"
+#include "OpaqueJSString.h"
+#include "Profiler.h"
+
+using namespace JSC;
+
+void JSStartProfiling(JSContextRef ctx, JSStringRef title)
+{
+ Profiler::profiler()->startProfiling(toJS(ctx), title->ustring());
+}
+
+void JSEndProfiling(JSContextRef ctx, JSStringRef title)
+{
+ ExecState* exec = toJS(ctx);
+ Profiler* profiler = Profiler::profiler();
+ profiler->stopProfiling(exec, title->ustring());
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSProfiler_h
+#define JSProfiler_h
+
+#include <JavaScriptCore/JSBase.h>
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+@function JSStartProfiling
+@abstract Enables the profler.
+@param ctx The execution context to use.
+@param title The title of the profile.
+@result The profiler is turned on.
+*/
+JS_EXPORT void JSStartProfiling(JSContextRef ctx, JSStringRef title);
+
+/*!
+@function JSEndProfiling
+@abstract Disables the profler.
+@param ctx The execution context to use.
+@param title The title of the profile.
+@result The profiler is turned off. If there is no name, the most recently started
+ profile is stopped. If the name does not match any profile then no profile
+ is stopped.
+*/
+JS_EXPORT void JSEndProfiling(JSContextRef ctx, JSStringRef title);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSProfiler_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
#include "config.h"
#include "JSStringRef.h"
-#include <wtf/Platform.h>
-
-#include "APICast.h"
-#include <kjs/JSLock.h>
-#include <kjs/JSType.h>
-#include <kjs/internal.h>
-#include <kjs/operations.h>
-#include <kjs/ustring.h>
-#include <kjs/value.h>
+#include "InitializeThreading.h"
+#include "OpaqueJSString.h"
#include <wtf/unicode/UTF8.h>
-using namespace KJS;
+using namespace JSC;
using namespace WTF::Unicode;
JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars)
{
- JSLock lock;
- return toRef(UString(reinterpret_cast<const KJS::UChar*>(chars), static_cast<int>(numChars)).rep()->ref());
+ initializeThreading();
+ return OpaqueJSString::create(chars, numChars).releaseRef();
}
JSStringRef JSStringCreateWithUTF8CString(const char* string)
{
- JSLock lock;
-
- size_t length = strlen(string);
- Vector< ::UChar, 1024> buffer(length);
- ::UChar* p = buffer.data();
- if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
- return 0;
-
- return toRef(UString(reinterpret_cast<KJS::UChar*>(buffer.data()), p - buffer.data()).rep()->ref());
+ initializeThreading();
+ if (string) {
+ size_t length = strlen(string);
+ Vector<UChar, 1024> buffer(length);
+ UChar* p = buffer.data();
+ if (conversionOK == convertUTF8ToUTF16(&string, string + length, &p, p + length))
+ return OpaqueJSString::create(buffer.data(), p - buffer.data()).releaseRef();
+ }
+
+ // Null string.
+ return OpaqueJSString::create().releaseRef();
}
JSStringRef JSStringRetain(JSStringRef string)
{
- JSLock lock;
- UString::Rep* rep = toJS(string);
- return toRef(rep->ref());
+ string->ref();
+ return string;
}
void JSStringRelease(JSStringRef string)
{
- JSLock lock;
- UString::Rep* rep = toJS(string);
- rep->deref();
+ string->deref();
}
size_t JSStringGetLength(JSStringRef string)
{
- UString::Rep* rep = toJS(string);
- return rep->size();
+ return string->length();
}
const JSChar* JSStringGetCharactersPtr(JSStringRef string)
{
- UString::Rep* rep = toJS(string);
- return reinterpret_cast<const JSChar*>(rep->data());
+ return string->characters();
}
size_t JSStringGetMaximumUTF8CStringSize(JSStringRef string)
{
- UString::Rep* rep = toJS(string);
-
// Any UTF8 character > 3 bytes encodes as a UTF16 surrogate pair.
- return rep->size() * 3 + 1; // + 1 for terminating '\0'
+ return string->length() * 3 + 1; // + 1 for terminating '\0'
}
size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize)
{
- JSLock lock;
- UString::Rep* rep = toJS(string);
- CString cString = UString(rep).UTF8String();
+ if (!bufferSize)
+ return 0;
+
+ char* p = buffer;
+ const UChar* d = string->characters();
+ ConversionResult result = convertUTF16ToUTF8(&d, d + string->length(), &p, p + bufferSize - 1, true);
+ *p++ = '\0';
+ if (result != conversionOK && result != targetExhausted)
+ return 0;
- size_t length = std::min(bufferSize, cString.size() + 1); // + 1 for terminating '\0'
- memcpy(buffer, cString.c_str(), length);
- return length;
+ return p - buffer;
}
bool JSStringIsEqual(JSStringRef a, JSStringRef b)
{
- JSLock lock;
-
- UString::Rep* aRep = toJS(a);
- UString::Rep* bRep = toJS(b);
-
- return UString(aRep) == UString(bRep);
+ unsigned len = a->length();
+ return len == b->length() && 0 == memcmp(a->characters(), b->characters(), len * sizeof(UChar));
}
bool JSStringIsEqualToUTF8CString(JSStringRef a, const char* b)
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#include <JavaScriptCore/JSValueRef.h>
+#ifndef __cplusplus
#include <stdbool.h>
-#include <stddef.h> // for size_t
+#endif
+#include <stddef.h> /* for size_t */
#ifdef __cplusplus
extern "C" {
}
#endif
-#endif // JSStringRef_h
+#endif /* JSStringRef_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
extern "C" {
#endif
-// COM convenience methods
+/* COM convenience methods */
/*!
@function
}
#endif
-#endif // JSStringRefBSTR_h
+#endif /* JSStringRefBSTR_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.
*
#include "JSStringRefCF.h"
#include "APICast.h"
+#include "InitializeThreading.h"
#include "JSStringRef.h"
-#include <kjs/JSLock.h>
-#include <kjs/ustring.h>
-#include <kjs/value.h>
-
-using namespace KJS;
+#include "OpaqueJSString.h"
+#include <runtime/UString.h>
+#include <runtime/JSValue.h>
+#include <wtf/OwnArrayPtr.h>
JSStringRef JSStringCreateWithCFString(CFStringRef string)
{
- JSLock lock;
- CFIndex length = CFStringGetLength(string);
- UString::Rep* rep;
- if (!length)
- rep = UString("").rep()->ref();
- else {
- UniChar* buffer = static_cast<UniChar*>(fastMalloc(sizeof(UniChar) * length));
- CFStringGetCharacters(string, CFRangeMake(0, length), buffer);
- rep = UString(reinterpret_cast<UChar*>(buffer), length, false).rep()->ref();
+ JSC::initializeThreading();
+
+ // We cannot use CFIndex here since CFStringGetLength can return values larger than
+ // it can hold. (<rdar://problem/6806478>)
+ size_t length = CFStringGetLength(string);
+ if (length) {
+ OwnArrayPtr<UniChar> buffer(new UniChar[length]);
+ CFStringGetCharacters(string, CFRangeMake(0, length), buffer.get());
+ COMPILE_ASSERT(sizeof(UniChar) == sizeof(UChar), unichar_and_uchar_must_be_same_size);
+ return OpaqueJSString::create(reinterpret_cast<UChar*>(buffer.get()), length).releaseRef();
+ } else {
+ return OpaqueJSString::create(0, 0).releaseRef();
}
- return toRef(rep);
}
CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string)
{
- UString::Rep* rep = toJS(string);
- return CFStringCreateWithCharacters(alloc, reinterpret_cast<const UniChar*>(rep->data()), rep->size());
+ return CFStringCreateWithCharacters(alloc, reinterpret_cast<const UniChar*>(string->characters()), string->length());
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.
*
extern "C" {
#endif
-// CFString convenience methods
+/* CFString convenience methods */
/*!
@function
@result A CFString containing string. Ownership follows the Create Rule.
*/
JS_EXPORT CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string);
-
+
#ifdef __cplusplus
}
#endif
-#endif // JSStringRefCF_h
+#endif /* JSStringRefCF_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
#include "APICast.h"
#include "JSCallbackObject.h"
-#include <kjs/JSType.h>
-#include <kjs/JSGlobalObject.h>
-#include <kjs/internal.h>
-#include <kjs/operations.h>
-#include <kjs/protect.h>
-#include <kjs/ustring.h>
-#include <kjs/value.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSString.h>
+#include <runtime/Operations.h>
+#include <runtime/Protect.h>
+#include <runtime/UString.h>
+#include <runtime/JSValue.h>
#include <wtf/Assertions.h>
JSType JSValueGetType(JSContextRef, JSValueRef value)
{
- KJS::JSValue* jsValue = toJS(value);
- switch (jsValue->type()) {
- case KJS::UndefinedType:
- return kJSTypeUndefined;
- case KJS::NullType:
- return kJSTypeNull;
- case KJS::BooleanType:
- return kJSTypeBoolean;
- case KJS::NumberType:
- return kJSTypeNumber;
- case KJS::StringType:
- return kJSTypeString;
- case KJS::ObjectType:
- return kJSTypeObject;
- default:
- ASSERT(!"JSValueGetType: unknown type code.\n");
- return kJSTypeUndefined;
- }
+ JSC::JSValuePtr jsValue = toJS(value);
+ if (jsValue.isUndefined())
+ return kJSTypeUndefined;
+ if (jsValue.isNull())
+ return kJSTypeNull;
+ if (jsValue.isBoolean())
+ return kJSTypeBoolean;
+ if (jsValue.isNumber())
+ return kJSTypeNumber;
+ if (jsValue.isString())
+ return kJSTypeString;
+ ASSERT(jsValue.isObject());
+ return kJSTypeObject;
}
-using namespace KJS; // placed here to avoid conflict between KJS::JSType and JSType, above.
+using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above.
bool JSValueIsUndefined(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isUndefined();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isUndefined();
}
bool JSValueIsNull(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isNull();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isNull();
}
bool JSValueIsBoolean(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isBoolean();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isBoolean();
}
bool JSValueIsNumber(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isNumber();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isNumber();
}
bool JSValueIsString(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isString();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isString();
}
bool JSValueIsObject(JSContextRef, JSValueRef value)
{
- JSValue* jsValue = toJS(value);
- return jsValue->isObject();
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.isObject();
}
bool JSValueIsObjectOfClass(JSContextRef, JSValueRef value, JSClassRef jsClass)
{
- JSValue* jsValue = toJS(value);
+ JSValuePtr jsValue = toJS(value);
- if (JSObject* o = jsValue->getObject()) {
+ if (JSObject* o = jsValue.getObject()) {
if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
else if (o->inherits(&JSCallbackObject<JSObject>::info))
bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
- JSValue* jsA = toJS(a);
- JSValue* jsB = toJS(b);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsA = toJS(a);
+ JSValuePtr jsB = toJS(b);
- bool result = equal(exec, jsA, jsB); // false if an exception is thrown
+ bool result = JSValuePtr::equal(exec, jsA, jsB); // false if an exception is thrown
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
return result;
}
-bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
+bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b)
{
- JSLock lock;
- ExecState* exec = toJS(ctx);
- JSValue* jsA = toJS(a);
- JSValue* jsB = toJS(b);
+ JSValuePtr jsA = toJS(a);
+ JSValuePtr jsB = toJS(b);
- bool result = strictEqual(exec, jsA, jsB); // can't throw because it doesn't perform value conversion
- ASSERT(!exec->hadException());
+ bool result = JSValuePtr::strictEqual(jsA, jsB);
return result;
}
bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
- JSValue* jsValue = toJS(value);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsValue = toJS(value);
JSObject* jsConstructor = toJS(constructor);
- if (!jsConstructor->implementsHasInstance())
+ if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
return false;
- bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
+ bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
return toRef(jsBoolean(value));
}
-JSValueRef JSValueMakeNumber(JSContextRef, double value)
+JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
{
- JSLock lock;
- return toRef(jsNumber(value));
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ return toRef(jsNumber(exec, value));
}
-JSValueRef JSValueMakeString(JSContextRef, JSStringRef string)
+JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
{
- JSLock lock;
- UString::Rep* rep = toJS(string);
- return toRef(jsString(UString(rep)));
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ return toRef(jsString(exec, string->ustring()));
}
bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
{
ExecState* exec = toJS(ctx);
- JSValue* jsValue = toJS(value);
- return jsValue->toBoolean(exec);
+ JSValuePtr jsValue = toJS(value);
+ return jsValue.toBoolean(exec);
}
double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
{
- JSLock lock;
- JSValue* jsValue = toJS(value);
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
- double number = jsValue->toNumber(exec);
+ JSValuePtr jsValue = toJS(value);
+
+ double number = jsValue.toNumber(exec);
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
{
- JSLock lock;
- JSValue* jsValue = toJS(value);
ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsValue = toJS(value);
- JSStringRef stringRef = toRef(jsValue->toString(exec).rep()->ref());
+ RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
exec->clearException();
- stringRef = 0;
+ stringRef.clear();
}
- return stringRef;
+ return stringRef.release().releaseRef();
}
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
{
- JSLock lock;
ExecState* exec = toJS(ctx);
- JSValue* jsValue = toJS(value);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsValue = toJS(value);
- JSObjectRef objectRef = toRef(jsValue->toObject(exec));
+ JSObjectRef objectRef = toRef(jsValue.toObject(exec));
if (exec->hadException()) {
if (exception)
*exception = toRef(exec->exception());
return objectRef;
}
-void JSValueProtect(JSContextRef, JSValueRef value)
+void JSValueProtect(JSContextRef ctx, JSValueRef value)
{
- JSLock lock;
- JSValue* jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsValue = toJS(value);
gcProtect(jsValue);
}
-void JSValueUnprotect(JSContextRef, JSValueRef value)
+void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
{
- JSLock lock;
- JSValue* jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValuePtr jsValue = toJS(value);
gcUnprotect(jsValue);
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
#include <JavaScriptCore/JSBase.h>
+#ifndef __cplusplus
#include <stdbool.h>
+#endif
/*!
@enum JSType
*/
JS_EXPORT bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass);
-// Comparing values
+/* Comparing values */
/*!
@function
*/
JS_EXPORT bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception);
-// Creating values
+/* Creating values */
/*!
@function
*/
JS_EXPORT JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string);
-// Converting to primitive values
+/* Converting to primitive values */
/*!
@function
*/
JS_EXPORT JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception);
-// Garbage collection
+/* Garbage collection */
/*!
@function
@abstract Protects a JavaScript value from garbage collection.
}
#endif
-#endif // JSValueRef_h
+#endif /* JSValueRef_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
#include <JavaScriptCore/JSObjectRef.h>
#include <JavaScriptCore/JSValueRef.h>
-#endif // JavaScript_h
+#endif /* JavaScript_h */
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
*
#include <JavaScriptCore/JavaScript.h>
#include <JavaScriptCore/JSStringRefCF.h>
-#endif // JavaScriptCore_h
+#endif /* JavaScriptCore_h */
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "Node.h"
-#include <stddef.h>
-#include <stdlib.h>
-
-Node* Node_new(void)
-{
- Node* node = (Node*)malloc(sizeof(Node));
- node->refCount = 0;
- node->nodeType = "Node";
- node->childNodesTail = NULL;
-
- return node;
-}
-
-void Node_appendChild(Node* node, Node* child)
-{
- Node_ref(child);
- NodeLink* nodeLink = (NodeLink*)malloc(sizeof(NodeLink));
- nodeLink->node = child;
- nodeLink->prev = node->childNodesTail;
- node->childNodesTail = nodeLink;
-}
-
-void Node_removeChild(Node* node, Node* child)
-{
- // Linear search from tail -- good enough for our purposes here
- NodeLink* current;
- NodeLink** currentHandle;
- for (currentHandle = &node->childNodesTail, current = *currentHandle; current; currentHandle = ¤t->prev, current = *currentHandle) {
- if (current->node == child) {
- Node_deref(current->node);
- *currentHandle = current->prev;
- free(current);
- break;
- }
- }
-}
-
-void Node_replaceChild(Node* node, Node* newChild, Node* oldChild)
-{
- // Linear search from tail -- good enough for our purposes here
- NodeLink* current;
- for (current = node->childNodesTail; current; current = current->prev) {
- if (current->node == oldChild) {
- Node_deref(current->node);
- current->node = newChild;
- }
- }
-}
-
-void Node_ref(Node* node)
-{
- ++node->refCount;
-}
-
-void Node_deref(Node* node)
-{
- if (--node->refCount == 0)
- free(node);
-}
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Node_h
-#define Node_h
-
-typedef struct __Node Node;
-typedef struct __NodeLink NodeLink;
-
-struct __NodeLink {
- Node* node;
- NodeLink* prev;
-};
-
-struct __Node {
- unsigned refCount;
- const char* nodeType;
- NodeLink* childNodesTail;
-};
-
-extern Node* Node_new(void);
-extern void Node_ref(Node* node);
-extern void Node_deref(Node* node);
-extern void Node_appendChild(Node* node, Node* child);
-extern void Node_removeChild(Node* node, Node* child);
-extern void Node_replaceChild(Node* node, Node* newChild, Node* oldChild);
-
-#endif // Node_h
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "NodeList.h"
-
-#include <stdlib.h>
-
-extern NodeList* NodeList_new(Node* parentNode)
-{
- Node_ref(parentNode);
-
- NodeList* nodeList = (NodeList*)malloc(sizeof(NodeList));
- nodeList->parentNode = parentNode;
- nodeList->refCount = 0;
- return nodeList;
-}
-
-extern unsigned NodeList_length(NodeList* nodeList)
-{
- // Linear count from tail -- good enough for our purposes here
- unsigned i = 0;
- NodeLink* n = nodeList->parentNode->childNodesTail;
- while (n) {
- n = n->prev;
- ++i;
- }
-
- return i;
-}
-
-extern Node* NodeList_item(NodeList* nodeList, unsigned index)
-{
- unsigned length = NodeList_length(nodeList);
- if (index >= length)
- return NULL;
-
- // Linear search from tail -- good enough for our purposes here
- NodeLink* n = nodeList->parentNode->childNodesTail;
- unsigned i = 0;
- unsigned count = length - 1 - index;
- while (i < count) {
- ++i;
- n = n->prev;
- }
- return n->node;
-}
-
-extern void NodeList_ref(NodeList* nodeList)
-{
- ++nodeList->refCount;
-}
-
-extern void NodeList_deref(NodeList* nodeList)
-{
- if (--nodeList->refCount == 0) {
- Node_deref(nodeList->parentNode);
- free(nodeList);
- }
-}
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef NodeList_h
-#define NodeList_h
-
-#include "Node.h"
-
-typedef struct {
- unsigned refCount;
- Node* parentNode;
-} NodeList;
-
-extern NodeList* NodeList_new(Node* parentNode);
-extern unsigned NodeList_length(NodeList*);
-extern Node* NodeList_item(NodeList*, unsigned);
-extern void NodeList_ref(NodeList*);
-extern void NodeList_deref(NodeList*);
-
-#endif // NodeList_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "OpaqueJSString.h"
+
+#include <interpreter/CallFrame.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/Identifier.h>
+
+using namespace JSC;
+
+PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring)
+{
+ if (!ustring.isNull())
+ return adoptRef(new OpaqueJSString(ustring.data(), ustring.size()));
+ return 0;
+}
+
+UString OpaqueJSString::ustring() const
+{
+ if (this && m_characters)
+ return UString(m_characters, m_length, true);
+ return UString::null();
+}
+
+Identifier OpaqueJSString::identifier(JSGlobalData* globalData) const
+{
+ if (!this || !m_characters)
+ return Identifier(globalData, static_cast<const char*>(0));
+
+ return Identifier(globalData, m_characters, m_length);
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpaqueJSString_h
+#define OpaqueJSString_h
+
+#include <runtime/UString.h>
+
+namespace JSC {
+ class Identifier;
+ class JSGlobalData;
+}
+
+struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> {
+
+ static PassRefPtr<OpaqueJSString> create() // null
+ {
+ return adoptRef(new OpaqueJSString);
+ }
+
+ static PassRefPtr<OpaqueJSString> create(const UChar* characters, unsigned length)
+ {
+ return adoptRef(new OpaqueJSString(characters, length));
+ }
+
+ static PassRefPtr<OpaqueJSString> create(const JSC::UString&);
+
+ UChar* characters() { return this ? m_characters : 0; }
+ unsigned length() { return this ? m_length : 0; }
+
+ JSC::UString ustring() const;
+ JSC::Identifier identifier(JSC::JSGlobalData*) const;
+
+private:
+ friend class WTF::ThreadSafeShared<OpaqueJSString>;
+
+ OpaqueJSString()
+ : m_characters(0)
+ , m_length(0)
+ {
+ }
+
+ OpaqueJSString(const UChar* characters, unsigned length)
+ : m_length(length)
+ {
+ m_characters = new UChar[length];
+ memcpy(m_characters, characters, length * sizeof(UChar));
+ }
+
+ ~OpaqueJSString()
+ {
+ delete[] m_characters;
+ }
+
+ UChar* m_characters;
+ unsigned m_length;
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __WebKitAvailability__
+#define __WebKitAvailability__
+
+/* The structure of this header is based on AvailabilityMacros.h. The major difference is that the availability
+ macros are defined in terms of WebKit version numbers rather than Mac OS X system version numbers, as WebKit
+ releases span multiple versions of Mac OS X.
+*/
+
+#define WEBKIT_VERSION_1_0 0x0100
+#define WEBKIT_VERSION_1_1 0x0110
+#define WEBKIT_VERSION_1_2 0x0120
+#define WEBKIT_VERSION_1_3 0x0130
+#define WEBKIT_VERSION_2_0 0x0200
+#define WEBKIT_VERSION_3_0 0x0300
+#define WEBKIT_VERSION_3_1 0x0310
+#define WEBKIT_VERSION_LATEST 0x9999
+
+#ifdef __APPLE__
+#import <AvailabilityMacros.h>
+#else
+/*
+ * For non-Mac platforms, require the newest version.
+ */
+#define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST
+/*
+ * only certain compilers support __attribute__((deprecated))
+ */
+#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+ #define DEPRECATED_ATTRIBUTE __attribute__((deprecated))
+#else
+ #define DEPRECATED_ATTRIBUTE
+#endif
+#endif
+
+/* The versions of GCC that shipped with Xcode prior to 3.0 (GCC build number < 5400) did not support attributes on methods.
+ If we are building with one of these versions, we need to omit the attribute. We achieve this by wrapping the annotation
+ in WEBKIT_OBJC_METHOD_ANNOTATION, which will remove the annotation when an old version of GCC is in use and will otherwise
+ expand to the annotation. The same is needed for protocol methods.
+*/
+#if defined(__APPLE_CC__) && __APPLE_CC__ < 5400
+ #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION)
+#else
+ #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION
+#endif
+
+
+/* If minimum WebKit version is not specified, assume the version that shipped with the target Mac OS X version */
+#ifndef WEBKIT_VERSION_MIN_REQUIRED
+ #if !defined(MAC_OS_X_VERSION_10_2) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_2
+ #error WebKit was not available prior to Mac OS X 10.2
+ #elif !defined(MAC_OS_X_VERSION_10_3) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3
+ /* WebKit 1.0 is the only version available on Mac OS X 10.2. */
+ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_1_0
+ #elif !defined(MAC_OS_X_VERSION_10_4) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
+ /* WebKit 1.1 is the version that shipped on Mac OS X 10.3. */
+ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_1_1
+ #elif !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ /* WebKit 2.0 is the version that shipped on Mac OS X 10.4. */
+ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_2_0
+ #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+ /* WebKit 3.0 is the version that shipped on Mac OS X 10.5. */
+ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_3_0
+ #else
+ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST
+ #endif
+#endif
+
+
+/* If maximum WebKit version is not specified, assume largerof(latest, minimum) */
+#ifndef WEBKIT_VERSION_MAX_ALLOWED
+ #if WEBKIT_VERSION_MIN_REQUIRED > WEBKIT_VERSION_LATEST
+ #define WEBKIT_VERSION_MAX_ALLOWED WEBKIT_VERSION_MIN_REQUIRED
+ #else
+ #define WEBKIT_VERSION_MAX_ALLOWED WEBKIT_VERSION_LATEST
+ #endif
+#endif
+
+
+/* Sanity check the configured values */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_MIN_REQUIRED
+ #error WEBKIT_VERSION_MAX_ALLOWED must be >= WEBKIT_VERSION_MIN_REQUIRED
+#endif
+#if WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_0
+ #error WEBKIT_VERSION_MIN_REQUIRED must be >= WEBKIT_VERSION_1_0
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+ *
+ * Used on functions introduced in WebKit 1.0
+ */
+#define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on functions introduced in WebKit 1.0,
+ * and deprecated in WebKit 1.0
+ */
+#define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_1_0_AND_LATER
+ *
+ * Used on types deprecated in WebKit 1.0
+ */
+#define DEPRECATED_IN_WEBKIT_VERSION_1_0_AND_LATER DEPRECATED_ATTRIBUTE
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 1.1
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_1
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_1
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * and deprecated in WebKit 1.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 1.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER
+ *
+ * Used on types deprecated in WebKit 1.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 1.2
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_2
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_2
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * and deprecated in WebKit 1.2
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 1.2
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated in WebKit 1.2
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER
+ *
+ * Used on types deprecated in WebKit 1.2
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * and deprecated in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * but later deprecated in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER
+ *
+ * Used on types deprecated in WebKit 1.3
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 2.0,
+ * and deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * but later deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * but later deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER
+ *
+ * Used on types deprecated in WebKit 2.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0
+ #define DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 3.0,
+ * and deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * but later deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * but later deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0
+ *
+ * Used on declarations introduced in WebKit 2.0,
+ * but later deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER
+ *
+ * Used on types deprecated in WebKit 3.0
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0
+ #define DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER
+ *
+ * Used on declarations introduced in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED
+ *
+ * Used on declarations introduced in WebKit 3.1,
+ * and deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 2.0,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 3.0,
+ * but later deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER
+ *
+ * Used on types deprecated in WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1
+ #define DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER
+#endif
+
+
+
+
+
+
+/*
+ * AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST
+ #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1 UNAVAILABLE_ATTRIBUTE
+#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST
+ #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1 WEAK_IMPORT_ATTRIBUTE
+#else
+ #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+#endif
+
+/*
+ * AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED
+ *
+ * Used on declarations introduced after WebKit 3.1,
+ * and deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.0,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.1,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.2,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 2.0,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 3.0,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
+#endif
+
+/*
+ * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on declarations introduced in WebKit 3.1,
+ * but later deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER
+#endif
+
+/*
+ * DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ *
+ * Used on types deprecated after WebKit 3.1
+ */
+#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
+ #define DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+#else
+ #define DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+#endif
+
+
+#endif /* __WebKitAvailability__ */
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "JSContextRef.h"
-#include "JSNode.h"
-#include "JSObjectRef.h"
-#include "JSStringRef.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <wtf/Assertions.h>
-#include <wtf/UnusedParam.h>
-
-static char* createStringWithContentsOfFile(const char* fileName);
-static JSValueRef print(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
-
-int main(int argc, char* argv[])
-{
- const char *scriptPath = "minidom.js";
- if (argc > 1) {
- scriptPath = argv[1];
- }
-
- JSGlobalContextRef context = JSGlobalContextCreate(NULL);
- JSObjectRef globalObject = JSContextGetGlobalObject(context);
-
- JSStringRef printIString = JSStringCreateWithUTF8CString("print");
- JSObjectSetProperty(context, globalObject, printIString, JSObjectMakeFunctionWithCallback(context, printIString, print), kJSPropertyAttributeNone, NULL);
- JSStringRelease(printIString);
-
- JSStringRef node = JSStringCreateWithUTF8CString("Node");
- JSObjectSetProperty(context, globalObject, node, JSObjectMakeConstructor(context, JSNode_class(context), JSNode_construct), kJSPropertyAttributeNone, NULL);
- JSStringRelease(node);
-
- char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
- JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
- JSValueRef exception;
- JSValueRef result = JSEvaluateScript(context, script, NULL, NULL, 0, &exception);
- if (result)
- printf("PASS: Test script executed successfully.\n");
- else {
- printf("FAIL: Test script threw exception:\n");
- JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
- size_t exceptionUTF8Size = JSStringGetMaximumUTF8CStringSize(exceptionIString);
- char* exceptionUTF8 = (char*)malloc(exceptionUTF8Size);
- JSStringGetUTF8CString(exceptionIString, exceptionUTF8, exceptionUTF8Size);
- printf("%s\n", exceptionUTF8);
- free(exceptionUTF8);
- JSStringRelease(exceptionIString);
- }
- JSStringRelease(script);
- free(scriptUTF8);
-
- globalObject = 0;
- JSGlobalContextRelease(context);
- JSGarbageCollect(context);
- printf("PASS: Program exited normally.\n");
- return 0;
-}
-
-static JSValueRef print(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(thisObject);
-
- if (argumentCount > 0) {
- JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
- size_t numChars = JSStringGetMaximumUTF8CStringSize(string);
- char stringUTF8[numChars];
- JSStringGetUTF8CString(string, stringUTF8, numChars);
- printf("%s\n", stringUTF8);
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static char* createStringWithContentsOfFile(const char* fileName)
-{
- char* buffer;
-
- size_t buffer_size = 0;
- size_t buffer_capacity = 1024;
- buffer = (char*)malloc(buffer_capacity);
-
- FILE* f = fopen(fileName, "r");
- if (!f) {
- fprintf(stderr, "Could not open file: %s\n", fileName);
- return 0;
- }
-
- while (!feof(f) && !ferror(f)) {
- buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
- if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
- buffer_capacity *= 2;
- buffer = (char*)realloc(buffer, buffer_capacity);
- ASSERT(buffer);
- }
-
- ASSERT(buffer_size < buffer_capacity);
- }
- fclose(f);
- buffer[buffer_size] = '\0';
-
- return buffer;
-}
+++ /dev/null
-<html>
-<head>
-<script src="minidom.js"></script>
-</head>
-
-<body onload="test()">
- <pre id='pre'></pre>
-</body>
-</html>
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-function shouldBe(a, b)
-{
- var evalA;
- try {
- evalA = eval(a);
- } catch(e) {
- evalA = e;
- }
-
- if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
- print("PASS: " + a + " should be " + b + " and is.", "green");
- else
- print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
-}
-
-function test()
-{
- print("Node is " + Node);
- for (var p in Node)
- print(p + ": " + Node[p]);
-
- node = new Node();
- print("node is " + node);
- for (var p in node)
- print(p + ": " + node[p]);
-
- child1 = new Node();
- child2 = new Node();
- child3 = new Node();
-
- node.appendChild(child1);
- node.appendChild(child2);
-
- var childNodes = node.childNodes;
-
- for (var i = 0; i < childNodes.length + 1; i++) {
- print("item " + i + ": " + childNodes.item(i));
- }
-
- for (var i = 0; i < childNodes.length + 1; i++) {
- print(i + ": " + childNodes[i]);
- }
-
- node.removeChild(child1);
- node.replaceChild(child3, child2);
-
- for (var i = 0; i < childNodes.length + 1; i++) {
- print("item " + i + ": " + childNodes.item(i));
- }
-
- for (var i = 0; i < childNodes.length + 1; i++) {
- print(i + ": " + childNodes[i]);
- }
-
- try {
- node.appendChild(null);
- } catch(e) {
- print("caught: " + e);
- }
-
- try {
- var o = new Object();
- o.appendChild = node.appendChild;
- o.appendChild(node);
- } catch(e) {
- print("caught: " + e);
- }
-
- try {
- node.appendChild();
- } catch(e) {
- print("caught: " + e);
- }
-
- oldNodeType = node.nodeType;
- node.nodeType = 1;
- shouldBe("node.nodeType", oldNodeType);
-
- shouldBe("node instanceof Node", true);
- shouldBe("new Object() instanceof Node", false);
-
- print(Node);
-}
-
-test();
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "JavaScriptCore.h"
-#include <math.h>
-#include <wtf/Assertions.h>
-#include <wtf/UnusedParam.h>
-
-static JSGlobalContextRef context = 0;
-
-static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
-{
- if (JSValueToBoolean(context, value) != expectedValue)
- fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
-}
-
-static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
-{
- double number = JSValueToNumber(context, value, NULL);
-
- // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
- // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
- // After that's resolved, we can remove these casts
- if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue)))
- fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
-}
-
-static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
-{
- JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
-
- size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
- char jsBuffer[jsSize];
- JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
-
- unsigned i;
- for (i = 0; jsBuffer[i]; i++)
- if (jsBuffer[i] != expectedValue[i])
- fprintf(stderr, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i, jsBuffer[i], jsBuffer[i], expectedValue[i], expectedValue[i]);
-
- if (jsSize < strlen(jsBuffer) + 1)
- fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
-
- JSStringRelease(valueAsString);
-}
-
-static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
-{
- JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
-
- size_t jsLength = JSStringGetLength(valueAsString);
- const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
-
- CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
- expectedValue,
- kCFStringEncodingUTF8);
- CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
- UniChar cfBuffer[cfLength];
- CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
- CFRelease(expectedValueAsCFString);
-
- if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0)
- fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
-
- if (jsLength != (size_t)cfLength)
- fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, cfLength);
-
- JSStringRelease(valueAsString);
-}
-
-static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
-
-/* MyObject pseudo-class */
-
-static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
-
- if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
- || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
- || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
- || JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
- || JSStringIsEqualToUTF8CString(propertyName, "0")) {
- return true;
- }
-
- return false;
-}
-
-static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
-
- if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
- return JSValueMakeNumber(context, 1);
- }
-
- if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
- return JSValueMakeNumber(context, 1);
- }
-
- if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
- return JSValueMakeUndefined(context);
- }
-
- if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
- *exception = JSValueMakeNumber(context, 1);
- return JSValueMakeNumber(context, 1);
- }
-
- return NULL;
-}
-
-static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
- UNUSED_PARAM(value);
- UNUSED_PARAM(exception);
-
- if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
- return true; // pretend we set the property in order to swallow it
-
- return false;
-}
-
-static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
-
- if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
- return true;
-
- if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
- *exception = JSValueMakeNumber(context, 2);
- return false;
- }
-
- return false;
-}
-
-static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
-
- JSStringRef propertyName;
-
- propertyName = JSStringCreateWithUTF8CString("alwaysOne");
- JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
- JSStringRelease(propertyName);
-
- propertyName = JSStringCreateWithUTF8CString("myPropertyName");
- JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
- JSStringRelease(propertyName);
-}
-
-static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(exception);
-
- if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
- return JSValueMakeNumber(context, 1);
-
- return JSValueMakeUndefined(context);
-}
-
-static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(object);
-
- if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
- return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
-
- return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
-}
-
-static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
-{
- UNUSED_PARAM(context);
- UNUSED_PARAM(constructor);
-
- JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
- JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
- JSStringRelease(numberString);
-
- return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, exception);
-}
-
-static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(exception);
-
- switch (type) {
- case kJSTypeNumber:
- return JSValueMakeNumber(context, 1);
- default:
- break;
- }
-
- // string conversion -- forward to default object class
- return NULL;
-}
-
-static JSStaticValue evilStaticValues[] = {
- { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static JSStaticFunction evilStaticFunctions[] = {
- { "nullCall", 0, kJSPropertyAttributeNone },
- { 0, 0, 0 }
-};
-
-JSClassDefinition MyObject_definition = {
- 0,
- kJSClassAttributeNone,
-
- "MyObject",
- NULL,
-
- evilStaticValues,
- evilStaticFunctions,
-
- NULL,
- NULL,
- MyObject_hasProperty,
- MyObject_getProperty,
- MyObject_setProperty,
- MyObject_deleteProperty,
- MyObject_getPropertyNames,
- MyObject_callAsFunction,
- MyObject_callAsConstructor,
- MyObject_hasInstance,
- MyObject_convertToType,
-};
-
-static JSClassRef MyObject_class(JSContextRef context)
-{
- UNUSED_PARAM(context);
-
- static JSClassRef jsClass;
- if (!jsClass)
- jsClass = JSClassCreate(&MyObject_definition);
-
- return jsClass;
-}
-
-static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 1); // distinguish base get form derived get
-}
-
-static bool Base_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(value);
-
- *exception = JSValueMakeNumber(ctx, 1); // distinguish base set from derived set
- return true;
-}
-
-static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(argumentCount);
- UNUSED_PARAM(arguments);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
-}
-
-static JSStaticFunction Base_staticFunctions[] = {
- { "baseProtoDup", NULL, kJSPropertyAttributeNone },
- { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
- { 0, 0, 0 }
-};
-
-static JSStaticValue Base_staticValues[] = {
- { "baseDup", Base_get, Base_set, kJSPropertyAttributeNone },
- { "baseOnly", Base_get, Base_set, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static bool TestInitializeFinalize;
-static void Base_initialize(JSContextRef context, JSObjectRef object)
-{
- UNUSED_PARAM(context);
-
- if (TestInitializeFinalize) {
- ASSERT((void*)1 == JSObjectGetPrivate(object));
- JSObjectSetPrivate(object, (void*)2);
- }
-}
-
-static unsigned Base_didFinalize;
-static void Base_finalize(JSObjectRef object)
-{
- UNUSED_PARAM(object);
- if (TestInitializeFinalize) {
- ASSERT((void*)4 == JSObjectGetPrivate(object));
- Base_didFinalize = true;
- }
-}
-
-static JSClassRef Base_class(JSContextRef context)
-{
- UNUSED_PARAM(context);
-
- static JSClassRef jsClass;
- if (!jsClass) {
- JSClassDefinition definition = kJSClassDefinitionEmpty;
- definition.staticValues = Base_staticValues;
- definition.staticFunctions = Base_staticFunctions;
- definition.initialize = Base_initialize;
- definition.finalize = Base_finalize;
- jsClass = JSClassCreate(&definition);
- }
- return jsClass;
-}
-
-static JSValueRef Derived_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 2); // distinguish base get form derived get
-}
-
-static bool Derived_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- UNUSED_PARAM(ctx);
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(value);
-
- *exception = JSValueMakeNumber(ctx, 2); // distinguish base set from derived set
- return true;
-}
-
-static JSValueRef Derived_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(argumentCount);
- UNUSED_PARAM(arguments);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
-}
-
-static JSStaticFunction Derived_staticFunctions[] = {
- { "protoOnly", Derived_callAsFunction, kJSPropertyAttributeNone },
- { "protoDup", NULL, kJSPropertyAttributeNone },
- { "baseProtoDup", Derived_callAsFunction, kJSPropertyAttributeNone },
- { 0, 0, 0 }
-};
-
-static JSStaticValue Derived_staticValues[] = {
- { "derivedOnly", Derived_get, Derived_set, kJSPropertyAttributeNone },
- { "protoDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
- { "baseDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static void Derived_initialize(JSContextRef context, JSObjectRef object)
-{
- UNUSED_PARAM(context);
-
- if (TestInitializeFinalize) {
- ASSERT((void*)2 == JSObjectGetPrivate(object));
- JSObjectSetPrivate(object, (void*)3);
- }
-}
-
-static void Derived_finalize(JSObjectRef object)
-{
- if (TestInitializeFinalize) {
- ASSERT((void*)3 == JSObjectGetPrivate(object));
- JSObjectSetPrivate(object, (void*)4);
- }
-}
-
-static JSClassRef Derived_class(JSContextRef context)
-{
- static JSClassRef jsClass;
- if (!jsClass) {
- JSClassDefinition definition = kJSClassDefinitionEmpty;
- definition.parentClass = Base_class(context);
- definition.staticValues = Derived_staticValues;
- definition.staticFunctions = Derived_staticFunctions;
- definition.initialize = Derived_initialize;
- definition.finalize = Derived_finalize;
- jsClass = JSClassCreate(&definition);
- }
- return jsClass;
-}
-
-static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(functionObject);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(exception);
-
- if (argumentCount > 0) {
- JSStringRef string = JSValueToStringCopy(context, arguments[0], NULL);
- size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
- char stringUTF8[sizeUTF8];
- JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
- printf("%s\n", stringUTF8);
- JSStringRelease(string);
- }
-
- return JSValueMakeUndefined(context);
-}
-
-static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(constructorObject);
- UNUSED_PARAM(exception);
-
- JSObjectRef result = JSObjectMake(context, NULL, NULL);
- if (argumentCount > 0) {
- JSStringRef value = JSStringCreateWithUTF8CString("value");
- JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
- JSStringRelease(value);
- }
-
- return result;
-}
-
-
-static void globalObject_initialize(JSContextRef context, JSObjectRef object)
-{
- UNUSED_PARAM(object);
- // Ensure that an execution context is passed in
- ASSERT(context);
-
- // Ensure that the global object is set to the object that we were passed
- JSObjectRef globalObject = JSContextGetGlobalObject(context);
- ASSERT(globalObject);
- ASSERT(object == globalObject);
-
- // Ensure that the standard global properties have been set on the global object
- JSStringRef array = JSStringCreateWithUTF8CString("Array");
- JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
- JSStringRelease(array);
-
- UNUSED_PARAM(arrayConstructor);
- ASSERT(arrayConstructor);
-}
-
-static JSValueRef globalObject_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 3);
-}
-
-static bool globalObject_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- UNUSED_PARAM(object);
- UNUSED_PARAM(propertyName);
- UNUSED_PARAM(value);
-
- *exception = JSValueMakeNumber(ctx, 3);
- return true;
-}
-
-static JSValueRef globalObject_call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- UNUSED_PARAM(function);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(argumentCount);
- UNUSED_PARAM(arguments);
- UNUSED_PARAM(exception);
-
- return JSValueMakeNumber(ctx, 3);
-}
-
-static JSStaticValue globalObject_staticValues[] = {
- { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static JSStaticFunction globalObject_staticFunctions[] = {
- { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
- { 0, 0, 0 }
-};
-
-static char* createStringWithContentsOfFile(const char* fileName);
-
-static void testInitializeFinalize()
-{
- JSObjectRef o = JSObjectMake(context, Derived_class(context), (void*)1);
- UNUSED_PARAM(o);
- ASSERT(JSObjectGetPrivate(o) == (void*)3);
-}
-
-int main(int argc, char* argv[])
-{
- const char *scriptPath = "testapi.js";
- if (argc > 1) {
- scriptPath = argv[1];
- }
-
- // Test garbage collection with a fresh context
- context = JSGlobalContextCreate(NULL);
- TestInitializeFinalize = true;
- testInitializeFinalize();
- JSGlobalContextRelease(context);
- JSGarbageCollect(context);
- TestInitializeFinalize = false;
-
- ASSERT(Base_didFinalize);
-
- JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
- globalObjectClassDefinition.initialize = globalObject_initialize;
- globalObjectClassDefinition.staticValues = globalObject_staticValues;
- globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
- globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
- JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
- context = JSGlobalContextCreate(globalObjectClass);
-
- JSObjectRef globalObject = JSContextGetGlobalObject(context);
- ASSERT(JSValueIsObject(context, globalObject));
-
- JSValueRef jsUndefined = JSValueMakeUndefined(context);
- JSValueRef jsNull = JSValueMakeNull(context);
- JSValueRef jsTrue = JSValueMakeBoolean(context, true);
- JSValueRef jsFalse = JSValueMakeBoolean(context, false);
- JSValueRef jsZero = JSValueMakeNumber(context, 0);
- JSValueRef jsOne = JSValueMakeNumber(context, 1);
- JSValueRef jsOneThird = JSValueMakeNumber(context, 1.0 / 3.0);
- JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, NULL);
- JSObjectSetPrototype(context, jsObjectNoProto, JSValueMakeNull(context));
-
- // FIXME: test funny utf8 characters
- JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
- JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
-
- JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
- JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
-
- UniChar singleUniChar = 65; // Capital A
- CFMutableStringRef cfString =
- CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
- &singleUniChar,
- 1,
- 1,
- kCFAllocatorNull);
-
- JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
- JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
-
- CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
-
- JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
- JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
-
- CFIndex cfStringLength = CFStringGetLength(cfString);
- UniChar buffer[cfStringLength];
- CFStringGetCharacters(cfString,
- CFRangeMake(0, cfStringLength),
- buffer);
- JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters(buffer, cfStringLength);
- JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
-
- JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters(buffer, CFStringGetLength(cfEmptyString));
- JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
-
- ASSERT(JSValueGetType(context, jsUndefined) == kJSTypeUndefined);
- ASSERT(JSValueGetType(context, jsNull) == kJSTypeNull);
- ASSERT(JSValueGetType(context, jsTrue) == kJSTypeBoolean);
- ASSERT(JSValueGetType(context, jsFalse) == kJSTypeBoolean);
- ASSERT(JSValueGetType(context, jsZero) == kJSTypeNumber);
- ASSERT(JSValueGetType(context, jsOne) == kJSTypeNumber);
- ASSERT(JSValueGetType(context, jsOneThird) == kJSTypeNumber);
- ASSERT(JSValueGetType(context, jsEmptyString) == kJSTypeString);
- ASSERT(JSValueGetType(context, jsOneString) == kJSTypeString);
- ASSERT(JSValueGetType(context, jsCFString) == kJSTypeString);
- ASSERT(JSValueGetType(context, jsCFStringWithCharacters) == kJSTypeString);
- ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
- ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
-
- JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
- JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
- JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
- JSStringRelease(myObjectIString);
-
- JSValueRef exception;
-
- // Conversions that throw exceptions
- exception = NULL;
- ASSERT(NULL == JSValueToObject(context, jsNull, &exception));
- ASSERT(exception);
-
- exception = NULL;
- // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
- // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
- // After that's resolved, we can remove these casts
- ASSERT(isnan((float)JSValueToNumber(context, jsObjectNoProto, &exception)));
- ASSERT(exception);
-
- exception = NULL;
- ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
- ASSERT(exception);
-
- ASSERT(JSValueToBoolean(context, myObject));
-
- exception = NULL;
- ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
- ASSERT(exception);
-
- exception = NULL;
- JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
- ASSERT(1 == JSValueToNumber(context, exception, NULL));
-
- assertEqualsAsBoolean(jsUndefined, false);
- assertEqualsAsBoolean(jsNull, false);
- assertEqualsAsBoolean(jsTrue, true);
- assertEqualsAsBoolean(jsFalse, false);
- assertEqualsAsBoolean(jsZero, false);
- assertEqualsAsBoolean(jsOne, true);
- assertEqualsAsBoolean(jsOneThird, true);
- assertEqualsAsBoolean(jsEmptyString, false);
- assertEqualsAsBoolean(jsOneString, true);
- assertEqualsAsBoolean(jsCFString, true);
- assertEqualsAsBoolean(jsCFStringWithCharacters, true);
- assertEqualsAsBoolean(jsCFEmptyString, false);
- assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
-
- assertEqualsAsNumber(jsUndefined, nan(""));
- assertEqualsAsNumber(jsNull, 0);
- assertEqualsAsNumber(jsTrue, 1);
- assertEqualsAsNumber(jsFalse, 0);
- assertEqualsAsNumber(jsZero, 0);
- assertEqualsAsNumber(jsOne, 1);
- assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
- assertEqualsAsNumber(jsEmptyString, 0);
- assertEqualsAsNumber(jsOneString, 1);
- assertEqualsAsNumber(jsCFString, nan(""));
- assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
- assertEqualsAsNumber(jsCFEmptyString, 0);
- assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
- ASSERT(sizeof(JSChar) == sizeof(UniChar));
-
- assertEqualsAsCharactersPtr(jsUndefined, "undefined");
- assertEqualsAsCharactersPtr(jsNull, "null");
- assertEqualsAsCharactersPtr(jsTrue, "true");
- assertEqualsAsCharactersPtr(jsFalse, "false");
- assertEqualsAsCharactersPtr(jsZero, "0");
- assertEqualsAsCharactersPtr(jsOne, "1");
- assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
- assertEqualsAsCharactersPtr(jsEmptyString, "");
- assertEqualsAsCharactersPtr(jsOneString, "1");
- assertEqualsAsCharactersPtr(jsCFString, "A");
- assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
- assertEqualsAsCharactersPtr(jsCFEmptyString, "");
- assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
-
- assertEqualsAsUTF8String(jsUndefined, "undefined");
- assertEqualsAsUTF8String(jsNull, "null");
- assertEqualsAsUTF8String(jsTrue, "true");
- assertEqualsAsUTF8String(jsFalse, "false");
- assertEqualsAsUTF8String(jsZero, "0");
- assertEqualsAsUTF8String(jsOne, "1");
- assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
- assertEqualsAsUTF8String(jsEmptyString, "");
- assertEqualsAsUTF8String(jsOneString, "1");
- assertEqualsAsUTF8String(jsCFString, "A");
- assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
- assertEqualsAsUTF8String(jsCFEmptyString, "");
- assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
-
- ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
- ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
-
- ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
- ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
-
- CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
- CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
- ASSERT(CFEqual(cfJSString, cfString));
- ASSERT(CFEqual(cfJSEmptyString, cfEmptyString));
- CFRelease(cfJSString);
- CFRelease(cfJSEmptyString);
-
- CFRelease(cfString);
- CFRelease(cfEmptyString);
-
- jsGlobalValue = JSObjectMake(context, NULL, NULL);
- JSValueProtect(context, jsGlobalValue);
- JSGarbageCollect(context);
- ASSERT(JSValueIsObject(context, jsGlobalValue));
- JSValueUnprotect(context, jsGlobalValue);
-
- JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
- JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
- ASSERT(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
- ASSERT(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
-
- JSValueRef result;
- JSValueRef v;
- JSObjectRef o;
- JSStringRef string;
-
- result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
- ASSERT(result);
- ASSERT(JSValueIsEqual(context, result, jsOne, NULL));
-
- exception = NULL;
- result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
- ASSERT(!result);
- ASSERT(JSValueIsObject(context, exception));
-
- JSStringRef array = JSStringCreateWithUTF8CString("Array");
- JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
- JSStringRelease(array);
- result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
- ASSERT(result);
- ASSERT(JSValueIsObject(context, result));
- ASSERT(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
- ASSERT(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(context), arrayConstructor, NULL));
-
- o = JSValueToObject(context, result, NULL);
- exception = NULL;
- ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
- ASSERT(!exception);
-
- JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
- ASSERT(!exception);
-
- exception = NULL;
- ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
- ASSERT(!exception);
-
- JSStringRef functionBody;
- JSObjectRef function;
-
- exception = NULL;
- functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
- JSStringRef line = JSStringCreateWithUTF8CString("line");
- ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
- ASSERT(JSValueIsObject(context, exception));
- v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
- assertEqualsAsNumber(v, 2); // FIXME: Lexer::setCode bumps startingLineNumber by 1 -- we need to change internal callers so that it doesn't have to (saying '0' to mean '1' in the API would be really confusing -- it's really confusing internally, in fact)
- JSStringRelease(functionBody);
- JSStringRelease(line);
-
- exception = NULL;
- functionBody = JSStringCreateWithUTF8CString("return Array;");
- function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception);
- JSStringRelease(functionBody);
- ASSERT(!exception);
- ASSERT(JSObjectIsFunction(context, function));
- v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
- ASSERT(v);
- ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
-
- exception = NULL;
- function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
- ASSERT(!exception);
- v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
- ASSERT(v && !exception);
- ASSERT(JSValueIsUndefined(context, v));
-
- exception = NULL;
- v = NULL;
- JSStringRef foo = JSStringCreateWithUTF8CString("foo");
- JSStringRef argumentNames[] = { foo };
- functionBody = JSStringCreateWithUTF8CString("return foo;");
- function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
- ASSERT(function && !exception);
- JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
- v = JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
- JSStringRelease(foo);
- JSStringRelease(functionBody);
-
- string = JSValueToStringCopy(context, function, NULL);
- assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) \n{\n return foo;\n}");
- JSStringRelease(string);
-
- JSStringRef print = JSStringCreateWithUTF8CString("print");
- JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
- JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
- JSStringRelease(print);
-
- ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
- ASSERT(!JSObjectGetPrivate(printFunction));
-
- JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
- JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
- JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
- JSStringRelease(myConstructorIString);
-
- ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
- ASSERT(!JSObjectGetPrivate(myConstructor));
-
- string = JSStringCreateWithUTF8CString("Derived");
- JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
- JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
- JSStringRelease(string);
-
- o = JSObjectMake(context, NULL, NULL);
- JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
- JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
- JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
- size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
- size_t count;
- for (count = 0; count < expectedCount; ++count)
- JSPropertyNameArrayGetNameAtIndex(nameArray, count);
- JSPropertyNameArrayRelease(nameArray);
- ASSERT(count == 1); // jsCFString should not be enumerated
-
- JSClassDefinition nullDefinition = kJSClassDefinitionEmpty;
- nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
- JSClassRef nullClass = JSClassCreate(&nullDefinition);
- JSClassRelease(nullClass);
-
- nullDefinition = kJSClassDefinitionEmpty;
- nullClass = JSClassCreate(&nullDefinition);
- JSClassRelease(nullClass);
-
- functionBody = JSStringCreateWithUTF8CString("return this;");
- function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
- JSStringRelease(functionBody);
- v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
- ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
- v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
- ASSERT(JSValueIsEqual(context, v, o, NULL));
-
- char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
- if (!scriptUTF8)
- printf("FAIL: Test script could not be loaded.\n");
- else {
- JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
- result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- if (JSValueIsUndefined(context, result))
- printf("PASS: Test script executed successfully.\n");
- else {
- printf("FAIL: Test script returned unexpected value:\n");
- JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
- CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
- CFShow(exceptionCF);
- CFRelease(exceptionCF);
- JSStringRelease(exceptionIString);
- }
- JSStringRelease(script);
- free(scriptUTF8);
- }
-
- // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
- function = NULL;
- v = NULL;
- o = NULL;
- globalObject = NULL;
-
- JSStringRelease(jsEmptyIString);
- JSStringRelease(jsOneIString);
- JSStringRelease(jsCFIString);
- JSStringRelease(jsCFEmptyIString);
- JSStringRelease(jsCFIStringWithCharacters);
- JSStringRelease(jsCFEmptyIStringWithCharacters);
- JSStringRelease(goodSyntax);
- JSStringRelease(badSyntax);
-
- JSGlobalContextRelease(context);
- JSGarbageCollect(context);
- JSClassRelease(globalObjectClass);
-
- printf("PASS: Program exited normally.\n");
- return 0;
-}
-
-static char* createStringWithContentsOfFile(const char* fileName)
-{
- char* buffer;
-
- size_t buffer_size = 0;
- size_t buffer_capacity = 1024;
- buffer = (char*)malloc(buffer_capacity);
-
- FILE* f = fopen(fileName, "r");
- if (!f) {
- fprintf(stderr, "Could not open file: %s\n", fileName);
- return 0;
- }
-
- while (!feof(f) && !ferror(f)) {
- buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
- if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
- buffer_capacity *= 2;
- buffer = (char*)realloc(buffer, buffer_capacity);
- ASSERT(buffer);
- }
-
- ASSERT(buffer_size < buffer_capacity);
- }
- fclose(f);
- buffer[buffer_size] = '\0';
-
- return buffer;
-}
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-function shouldBe(a, b)
-{
- var evalA;
- try {
- evalA = eval(a);
- } catch(e) {
- evalA = e;
- }
-
- if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
- print("PASS: " + a + " should be " + b + " and is.", "green");
- else
- print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
-}
-
-function shouldThrow(a)
-{
- var result = "__FAIL__: " + a + " did not throw an exception.";
-
- var evalA;
- try {
- eval(a);
- } catch(e) {
- result = "PASS: " + a + " threw: " + e;
- }
-
- print(result);
-}
-
-function globalStaticFunction()
-{
- return 4;
-}
-
-shouldBe("globalStaticValue", 3);
-shouldBe("globalStaticFunction()", 4);
-
-shouldBe("typeof MyObject", "function"); // our object implements 'call'
-MyObject.cantFind = 1;
-shouldBe("MyObject.cantFind", undefined);
-MyObject.regularType = 1;
-shouldBe("MyObject.regularType", 1);
-MyObject.alwaysOne = 2;
-shouldBe("MyObject.alwaysOne", 1);
-MyObject.cantDelete = 1;
-delete MyObject.cantDelete;
-shouldBe("MyObject.cantDelete", 1);
-shouldBe("delete MyObject.throwOnDelete", 2); // deleteProperty -- should throw 2
-MyObject.cantSet = 1;
-shouldBe("MyObject.cantSet", undefined);
-
-var foundMyPropertyName = false;
-var foundRegularType = false;
-for (var p in MyObject) {
- if (p == "myPropertyName")
- foundMyPropertyName = true;
- if (p == "regularType")
- foundRegularType = true;
-}
-print(foundMyPropertyName
- ? "PASS: MyObject.myPropertyName was enumerated"
- : "__FAIL__: MyObject.myPropertyName was not enumerated");
-print(foundRegularType
- ? "PASS: MyObject.regularType was enumerated"
- : "__FAIL__: MyObject.regularType was not enumerated");
-
-myObject = new MyObject();
-
-shouldBe("delete MyObject.regularType", true);
-shouldBe("MyObject.regularType", undefined);
-shouldBe("MyObject(0)", 1);
-shouldBe("MyObject()", undefined);
-shouldBe("typeof myObject", "object");
-shouldBe("MyObject ? 1 : 0", true); // toBoolean
-shouldBe("+MyObject", 1); // toNumber
-shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
-shouldBe("MyObject - 0", NaN); // toPrimitive
-
-shouldBe("typeof MyConstructor", "object");
-constructedObject = new MyConstructor(1);
-shouldBe("typeof constructedObject", "object");
-shouldBe("constructedObject.value", 1);
-shouldBe("myObject instanceof MyObject", true);
-shouldBe("(new Object()) instanceof MyObject", false);
-
-shouldThrow("MyObject.nullGetSet = 1");
-shouldThrow("MyObject.nullGetSet");
-shouldThrow("MyObject.nullCall()");
-shouldThrow("MyObject.hasPropertyLie");
-
-derived = new Derived();
-
-// base properties and functions return 1 when called/gotten; derived, 2
-shouldBe("derived.baseProtoDup()", 2);
-shouldBe("derived.baseProto()", 1);
-shouldBe("derived.baseDup", 2);
-shouldBe("derived.baseOnly", 1);
-shouldBe("derived.protoOnly()", 2);
-shouldBe("derived.protoDup", 2);
-shouldBe("derived.derivedOnly", 2)
-
-// base properties throw 1 when set; derived, 2
-shouldBe("derived.baseDup = 0", 2);
-shouldBe("derived.baseOnly = 0", 1);
-shouldBe("derived.derivedOnly = 0", 2)
-shouldBe("derived.protoDup = 0", 2);
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "JSNode.h"
+#include "JSNodeList.h"
+#include "JSObjectRef.h"
+#include "JSStringRef.h"
+#include "JSValueRef.h"
+#include "Node.h"
+#include "NodeList.h"
+#include "UnusedParam.h"
+#include <wtf/Assertions.h>
+
+static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+
+ /* Example of throwing a type error for invalid values */
+ if (!JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
+ JSStringRef message = JSStringCreateWithUTF8CString("TypeError: appendChild can only be called on nodes");
+ *exception = JSValueMakeString(context, message);
+ JSStringRelease(message);
+ } else if (argumentCount < 1 || !JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
+ JSStringRef message = JSStringCreateWithUTF8CString("TypeError: first argument to appendChild must be a node");
+ *exception = JSValueMakeString(context, message);
+ JSStringRelease(message);
+ } else {
+ Node* node = JSObjectGetPrivate(thisObject);
+ Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], NULL));
+
+ Node_appendChild(node, child);
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef JSNode_removeChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+
+ /* Example of ignoring invalid values */
+ if (argumentCount > 0) {
+ if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
+ if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
+ Node* node = JSObjectGetPrivate(thisObject);
+ Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception));
+
+ Node_removeChild(node, child);
+ }
+ }
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef JSNode_replaceChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+
+ if (argumentCount > 1) {
+ if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
+ if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
+ if (JSValueIsObjectOfClass(context, arguments[1], JSNode_class(context))) {
+ Node* node = JSObjectGetPrivate(thisObject);
+ Node* newChild = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception));
+ Node* oldChild = JSObjectGetPrivate(JSValueToObject(context, arguments[1], exception));
+
+ Node_replaceChild(node, newChild, oldChild);
+ }
+ }
+ }
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticFunction JSNode_staticFunctions[] = {
+ { "appendChild", JSNode_appendChild, kJSPropertyAttributeDontDelete },
+ { "removeChild", JSNode_removeChild, kJSPropertyAttributeDontDelete },
+ { "replaceChild", JSNode_replaceChild, kJSPropertyAttributeDontDelete },
+ { 0, 0, 0 }
+};
+
+static JSValueRef JSNode_getNodeType(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ Node* node = JSObjectGetPrivate(object);
+ if (node) {
+ JSStringRef nodeType = JSStringCreateWithUTF8CString(node->nodeType);
+ JSValueRef value = JSValueMakeString(context, nodeType);
+ JSStringRelease(nodeType);
+ return value;
+ }
+
+ return NULL;
+}
+
+static JSValueRef JSNode_getChildNodes(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ Node* node = JSObjectGetPrivate(thisObject);
+ ASSERT(node);
+ return JSNodeList_new(context, NodeList_new(node));
+}
+
+static JSValueRef JSNode_getFirstChild(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticValue JSNode_staticValues[] = {
+ { "nodeType", JSNode_getNodeType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { "childNodes", JSNode_getChildNodes, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { "firstChild", JSNode_getFirstChild, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { 0, 0, 0, 0 }
+};
+
+static void JSNode_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(context);
+
+ Node* node = JSObjectGetPrivate(object);
+ ASSERT(node);
+
+ Node_ref(node);
+}
+
+static void JSNode_finalize(JSObjectRef object)
+{
+ Node* node = JSObjectGetPrivate(object);
+ ASSERT(node);
+
+ Node_deref(node);
+}
+
+JSClassRef JSNode_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.staticValues = JSNode_staticValues;
+ definition.staticFunctions = JSNode_staticFunctions;
+ definition.initialize = JSNode_initialize;
+ definition.finalize = JSNode_finalize;
+
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+JSObjectRef JSNode_new(JSContextRef context, Node* node)
+{
+ return JSObjectMake(context, JSNode_class(context), node);
+}
+
+JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSNode_new(context, Node_new());
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSNode_h
+#define JSNode_h
+
+#include "JSBase.h"
+#include "Node.h"
+#include <stddef.h>
+
+extern JSObjectRef JSNode_new(JSContextRef context, Node* node);
+extern JSClassRef JSNode_class(JSContextRef context);
+extern JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+#endif /* JSNode_h */
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "JSNode.h"
+#include "JSNodeList.h"
+#include "JSObjectRef.h"
+#include "JSValueRef.h"
+#include "UnusedParam.h"
+#include <wtf/Assertions.h>
+
+static JSValueRef JSNodeList_item(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+
+ if (argumentCount > 0) {
+ NodeList* nodeList = JSObjectGetPrivate(thisObject);
+ ASSERT(nodeList);
+ Node* node = NodeList_item(nodeList, (unsigned)JSValueToNumber(context, arguments[0], exception));
+ if (node)
+ return JSNode_new(context, node);
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticFunction JSNodeList_staticFunctions[] = {
+ { "item", JSNodeList_item, kJSPropertyAttributeDontDelete },
+ { 0, 0, 0 }
+};
+
+static JSValueRef JSNodeList_length(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ NodeList* nodeList = JSObjectGetPrivate(thisObject);
+ ASSERT(nodeList);
+ return JSValueMakeNumber(context, NodeList_length(nodeList));
+}
+
+static JSStaticValue JSNodeList_staticValues[] = {
+ { "length", JSNodeList_length, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { 0, 0, 0, 0 }
+};
+
+static JSValueRef JSNodeList_getProperty(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ NodeList* nodeList = JSObjectGetPrivate(thisObject);
+ ASSERT(nodeList);
+ double index = JSValueToNumber(context, JSValueMakeString(context, propertyName), exception);
+ unsigned uindex = (unsigned)index;
+ if (uindex == index) { /* false for NaN */
+ Node* node = NodeList_item(nodeList, uindex);
+ if (node)
+ return JSNode_new(context, node);
+ }
+
+ return NULL;
+}
+
+static void JSNodeList_initialize(JSContextRef context, JSObjectRef thisObject)
+{
+ UNUSED_PARAM(context);
+
+ NodeList* nodeList = JSObjectGetPrivate(thisObject);
+ ASSERT(nodeList);
+
+ NodeList_ref(nodeList);
+}
+
+static void JSNodeList_finalize(JSObjectRef thisObject)
+{
+ NodeList* nodeList = JSObjectGetPrivate(thisObject);
+ ASSERT(nodeList);
+
+ NodeList_deref(nodeList);
+}
+
+static JSClassRef JSNodeList_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.staticValues = JSNodeList_staticValues;
+ definition.staticFunctions = JSNodeList_staticFunctions;
+ definition.getProperty = JSNodeList_getProperty;
+ definition.initialize = JSNodeList_initialize;
+ definition.finalize = JSNodeList_finalize;
+
+ jsClass = JSClassCreate(&definition);
+ }
+
+ return jsClass;
+}
+
+JSObjectRef JSNodeList_new(JSContextRef context, NodeList* nodeList)
+{
+ return JSObjectMake(context, JSNodeList_class(context), nodeList);
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSNodeList_h
+#define JSNodeList_h
+
+#include "JSBase.h"
+#include "NodeList.h"
+
+extern JSObjectRef JSNodeList_new(JSContextRef, NodeList*);
+
+#endif /* JSNodeList_h */
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Node.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+Node* Node_new(void)
+{
+ Node* node = (Node*)malloc(sizeof(Node));
+ node->refCount = 0;
+ node->nodeType = "Node";
+ node->childNodesTail = NULL;
+
+ return node;
+}
+
+void Node_appendChild(Node* node, Node* child)
+{
+ Node_ref(child);
+ NodeLink* nodeLink = (NodeLink*)malloc(sizeof(NodeLink));
+ nodeLink->node = child;
+ nodeLink->prev = node->childNodesTail;
+ node->childNodesTail = nodeLink;
+}
+
+void Node_removeChild(Node* node, Node* child)
+{
+ /* Linear search from tail -- good enough for our purposes here */
+ NodeLink* current;
+ NodeLink** currentHandle;
+ for (currentHandle = &node->childNodesTail, current = *currentHandle; current; currentHandle = ¤t->prev, current = *currentHandle) {
+ if (current->node == child) {
+ Node_deref(current->node);
+ *currentHandle = current->prev;
+ free(current);
+ break;
+ }
+ }
+}
+
+void Node_replaceChild(Node* node, Node* newChild, Node* oldChild)
+{
+ /* Linear search from tail -- good enough for our purposes here */
+ NodeLink* current;
+ for (current = node->childNodesTail; current; current = current->prev) {
+ if (current->node == oldChild) {
+ Node_deref(current->node);
+ current->node = newChild;
+ }
+ }
+}
+
+void Node_ref(Node* node)
+{
+ ++node->refCount;
+}
+
+void Node_deref(Node* node)
+{
+ if (--node->refCount == 0)
+ free(node);
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Node_h
+#define Node_h
+
+typedef struct __Node Node;
+typedef struct __NodeLink NodeLink;
+
+struct __NodeLink {
+ Node* node;
+ NodeLink* prev;
+};
+
+struct __Node {
+ unsigned refCount;
+ const char* nodeType;
+ NodeLink* childNodesTail;
+};
+
+extern Node* Node_new(void);
+extern void Node_ref(Node* node);
+extern void Node_deref(Node* node);
+extern void Node_appendChild(Node* node, Node* child);
+extern void Node_removeChild(Node* node, Node* child);
+extern void Node_replaceChild(Node* node, Node* newChild, Node* oldChild);
+
+#endif /* Node_h */
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "NodeList.h"
+
+#include <stdlib.h>
+
+extern NodeList* NodeList_new(Node* parentNode)
+{
+ Node_ref(parentNode);
+
+ NodeList* nodeList = (NodeList*)malloc(sizeof(NodeList));
+ nodeList->parentNode = parentNode;
+ nodeList->refCount = 0;
+ return nodeList;
+}
+
+extern unsigned NodeList_length(NodeList* nodeList)
+{
+ /* Linear count from tail -- good enough for our purposes here */
+ unsigned i = 0;
+ NodeLink* n = nodeList->parentNode->childNodesTail;
+ while (n) {
+ n = n->prev;
+ ++i;
+ }
+
+ return i;
+}
+
+extern Node* NodeList_item(NodeList* nodeList, unsigned index)
+{
+ unsigned length = NodeList_length(nodeList);
+ if (index >= length)
+ return NULL;
+
+ /* Linear search from tail -- good enough for our purposes here */
+ NodeLink* n = nodeList->parentNode->childNodesTail;
+ unsigned i = 0;
+ unsigned count = length - 1 - index;
+ while (i < count) {
+ ++i;
+ n = n->prev;
+ }
+ return n->node;
+}
+
+extern void NodeList_ref(NodeList* nodeList)
+{
+ ++nodeList->refCount;
+}
+
+extern void NodeList_deref(NodeList* nodeList)
+{
+ if (--nodeList->refCount == 0) {
+ Node_deref(nodeList->parentNode);
+ free(nodeList);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NodeList_h
+#define NodeList_h
+
+#include "Node.h"
+
+typedef struct {
+ unsigned refCount;
+ Node* parentNode;
+} NodeList;
+
+extern NodeList* NodeList_new(Node* parentNode);
+extern unsigned NodeList_length(NodeList*);
+extern Node* NodeList_item(NodeList*, unsigned);
+extern void NodeList_ref(NodeList*);
+extern void NodeList_deref(NodeList*);
+
+#endif /* NodeList_h */
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "JSContextRef.h"
+#include "JSNode.h"
+#include "JSObjectRef.h"
+#include "JSStringRef.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <wtf/Assertions.h>
+#include <wtf/UnusedParam.h>
+
+static char* createStringWithContentsOfFile(const char* fileName);
+static JSValueRef print(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+int main(int argc, char* argv[])
+{
+ const char *scriptPath = "minidom.js";
+ if (argc > 1) {
+ scriptPath = argv[1];
+ }
+
+ JSGlobalContextRef context = JSGlobalContextCreateInGroup(NULL, NULL);
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+
+ JSStringRef printIString = JSStringCreateWithUTF8CString("print");
+ JSObjectSetProperty(context, globalObject, printIString, JSObjectMakeFunctionWithCallback(context, printIString, print), kJSPropertyAttributeNone, NULL);
+ JSStringRelease(printIString);
+
+ JSStringRef node = JSStringCreateWithUTF8CString("Node");
+ JSObjectSetProperty(context, globalObject, node, JSObjectMakeConstructor(context, JSNode_class(context), JSNode_construct), kJSPropertyAttributeNone, NULL);
+ JSStringRelease(node);
+
+ char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
+ JSValueRef exception;
+ JSValueRef result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
+ if (result)
+ printf("PASS: Test script executed successfully.\n");
+ else {
+ printf("FAIL: Test script threw exception:\n");
+ JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
+ size_t exceptionUTF8Size = JSStringGetMaximumUTF8CStringSize(exceptionIString);
+ char* exceptionUTF8 = (char*)malloc(exceptionUTF8Size);
+ JSStringGetUTF8CString(exceptionIString, exceptionUTF8, exceptionUTF8Size);
+ printf("%s\n", exceptionUTF8);
+ free(exceptionUTF8);
+ JSStringRelease(exceptionIString);
+ }
+ JSStringRelease(script);
+ free(scriptUTF8);
+
+ globalObject = 0;
+ JSGlobalContextRelease(context);
+ printf("PASS: Program exited normally.\n");
+ return 0;
+}
+
+static JSValueRef print(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(thisObject);
+
+ if (argumentCount > 0) {
+ JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
+ size_t numChars = JSStringGetMaximumUTF8CStringSize(string);
+ char stringUTF8[numChars];
+ JSStringGetUTF8CString(string, stringUTF8, numChars);
+ printf("%s\n", stringUTF8);
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static char* createStringWithContentsOfFile(const char* fileName)
+{
+ char* buffer;
+
+ size_t buffer_size = 0;
+ size_t buffer_capacity = 1024;
+ buffer = (char*)malloc(buffer_capacity);
+
+ FILE* f = fopen(fileName, "r");
+ if (!f) {
+ fprintf(stderr, "Could not open file: %s\n", fileName);
+ return 0;
+ }
+
+ while (!feof(f) && !ferror(f)) {
+ buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
+ if (buffer_size == buffer_capacity) { /* guarantees space for trailing '\0' */
+ buffer_capacity *= 2;
+ buffer = (char*)realloc(buffer, buffer_capacity);
+ ASSERT(buffer);
+ }
+
+ ASSERT(buffer_size < buffer_capacity);
+ }
+ fclose(f);
+ buffer[buffer_size] = '\0';
+
+ return buffer;
+}
--- /dev/null
+<html>
+<head>
+<script src="minidom.js"></script>
+</head>
+
+<body onload="test()">
+ <pre id='pre'></pre>
+</body>
+</html>
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function shouldBe(a, b)
+{
+ var evalA;
+ try {
+ evalA = eval(a);
+ } catch(e) {
+ evalA = e;
+ }
+
+ if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
+ print("PASS: " + a + " should be " + b + " and is.", "green");
+ else
+ print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
+}
+
+function test()
+{
+ print("Node is " + Node);
+ for (var p in Node)
+ print(p + ": " + Node[p]);
+
+ node = new Node();
+ print("node is " + node);
+ for (var p in node)
+ print(p + ": " + node[p]);
+
+ child1 = new Node();
+ child2 = new Node();
+ child3 = new Node();
+
+ node.appendChild(child1);
+ node.appendChild(child2);
+
+ var childNodes = node.childNodes;
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print("item " + i + ": " + childNodes.item(i));
+ }
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print(i + ": " + childNodes[i]);
+ }
+
+ node.removeChild(child1);
+ node.replaceChild(child3, child2);
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print("item " + i + ": " + childNodes.item(i));
+ }
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print(i + ": " + childNodes[i]);
+ }
+
+ try {
+ node.appendChild(null);
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ try {
+ var o = new Object();
+ o.appendChild = node.appendChild;
+ o.appendChild(node);
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ try {
+ node.appendChild();
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ oldNodeType = node.nodeType;
+ node.nodeType = 1;
+ shouldBe("node.nodeType", oldNodeType);
+
+ shouldBe("node instanceof Node", true);
+ shouldBe("new Object() instanceof Node", false);
+
+ print(Node);
+}
+
+test();
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "JavaScriptCore.h"
+#include "JSBasePrivate.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/UnusedParam.h>
+
+#if COMPILER(MSVC)
+
+#include <wtf/MathExtras.h>
+
+static double nan(const char*)
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+#endif
+
+static JSGlobalContextRef context = 0;
+
+static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
+{
+ if (JSValueToBoolean(context, value) != expectedValue)
+ fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
+}
+
+static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
+{
+ double number = JSValueToNumber(context, value, NULL);
+
+ // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
+ // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
+ // After that's resolved, we can remove these casts
+ if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue)))
+ fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
+}
+
+static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
+{
+ JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
+
+ size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
+ char* jsBuffer = (char*)malloc(jsSize);
+ JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
+
+ unsigned i;
+ for (i = 0; jsBuffer[i]; i++)
+ if (jsBuffer[i] != expectedValue[i])
+ fprintf(stderr, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i, jsBuffer[i], jsBuffer[i], expectedValue[i], expectedValue[i]);
+
+ if (jsSize < strlen(jsBuffer) + 1)
+ fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
+
+ free(jsBuffer);
+ JSStringRelease(valueAsString);
+}
+
+static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
+{
+ JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
+
+ size_t jsLength = JSStringGetLength(valueAsString);
+ const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
+
+ CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
+ expectedValue,
+ kCFStringEncodingUTF8);
+ CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
+ UniChar* cfBuffer = (UniChar*)malloc(cfLength * sizeof(UniChar));
+ CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
+ CFRelease(expectedValueAsCFString);
+
+ if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0)
+ fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
+
+ if (jsLength != (size_t)cfLength)
+ fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, cfLength);
+
+ free(cfBuffer);
+ JSStringRelease(valueAsString);
+}
+
+static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
+
+/* MyObject pseudo-class */
+
+static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
+ || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
+ || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
+ || JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
+ || JSStringIsEqualToUTF8CString(propertyName, "0")) {
+ return true;
+ }
+
+ return false;
+}
+
+static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
+ return JSValueMakeNumber(context, 1);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
+ return JSValueMakeNumber(context, 1);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
+ return JSValueMakeUndefined(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
+ *exception = JSValueMakeNumber(context, 1);
+ return JSValueMakeNumber(context, 1);
+ }
+
+ return NULL;
+}
+
+static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
+ return true; // pretend we set the property in order to swallow it
+
+ return false;
+}
+
+static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
+ return true;
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
+ *exception = JSValueMakeNumber(context, 2);
+ return false;
+ }
+
+ return false;
+}
+
+static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ JSStringRef propertyName;
+
+ propertyName = JSStringCreateWithUTF8CString("alwaysOne");
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+
+ propertyName = JSStringCreateWithUTF8CString("myPropertyName");
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+}
+
+static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(exception);
+
+ if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
+ return JSValueMakeNumber(context, 1);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
+ return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
+
+ return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
+}
+
+static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructor);
+
+ JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
+ JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
+ JSStringRelease(numberString);
+
+ return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, exception);
+}
+
+static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(exception);
+
+ switch (type) {
+ case kJSTypeNumber:
+ return JSValueMakeNumber(context, 1);
+ case kJSTypeString:
+ {
+ JSStringRef string = JSStringCreateWithUTF8CString("MyObjectAsString");
+ JSValueRef result = JSValueMakeString(context, string);
+ JSStringRelease(string);
+ return result;
+ }
+ default:
+ break;
+ }
+
+ // string conversion -- forward to default object class
+ return NULL;
+}
+
+static JSStaticValue evilStaticValues[] = {
+ { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static JSStaticFunction evilStaticFunctions[] = {
+ { "nullCall", 0, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+JSClassDefinition MyObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "MyObject",
+ NULL,
+
+ evilStaticValues,
+ evilStaticFunctions,
+
+ NULL,
+ NULL,
+ MyObject_hasProperty,
+ MyObject_getProperty,
+ MyObject_setProperty,
+ MyObject_deleteProperty,
+ MyObject_getPropertyNames,
+ MyObject_callAsFunction,
+ MyObject_callAsConstructor,
+ MyObject_hasInstance,
+ MyObject_convertToType,
+};
+
+static JSClassRef MyObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&MyObject_definition);
+
+ return jsClass;
+}
+
+static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 1); // distinguish base get form derived get
+}
+
+static bool Base_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 1); // distinguish base set from derived set
+ return true;
+}
+
+static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
+}
+
+static JSStaticFunction Base_staticFunctions[] = {
+ { "baseProtoDup", NULL, kJSPropertyAttributeNone },
+ { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue Base_staticValues[] = {
+ { "baseDup", Base_get, Base_set, kJSPropertyAttributeNone },
+ { "baseOnly", Base_get, Base_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static bool TestInitializeFinalize;
+static void Base_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(context);
+
+ if (TestInitializeFinalize) {
+ ASSERT((void*)1 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)2);
+ }
+}
+
+static unsigned Base_didFinalize;
+static void Base_finalize(JSObjectRef object)
+{
+ UNUSED_PARAM(object);
+ if (TestInitializeFinalize) {
+ ASSERT((void*)4 == JSObjectGetPrivate(object));
+ Base_didFinalize = true;
+ }
+}
+
+static JSClassRef Base_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.staticValues = Base_staticValues;
+ definition.staticFunctions = Base_staticFunctions;
+ definition.initialize = Base_initialize;
+ definition.finalize = Base_finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+static JSValueRef Derived_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 2); // distinguish base get form derived get
+}
+
+static bool Derived_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(ctx);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 2); // distinguish base set from derived set
+ return true;
+}
+
+static JSValueRef Derived_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
+}
+
+static JSStaticFunction Derived_staticFunctions[] = {
+ { "protoOnly", Derived_callAsFunction, kJSPropertyAttributeNone },
+ { "protoDup", NULL, kJSPropertyAttributeNone },
+ { "baseProtoDup", Derived_callAsFunction, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue Derived_staticValues[] = {
+ { "derivedOnly", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { "protoDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { "baseDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static void Derived_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(context);
+
+ if (TestInitializeFinalize) {
+ ASSERT((void*)2 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)3);
+ }
+}
+
+static void Derived_finalize(JSObjectRef object)
+{
+ if (TestInitializeFinalize) {
+ ASSERT((void*)3 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)4);
+ }
+}
+
+static JSClassRef Derived_class(JSContextRef context)
+{
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.parentClass = Base_class(context);
+ definition.staticValues = Derived_staticValues;
+ definition.staticFunctions = Derived_staticFunctions;
+ definition.initialize = Derived_initialize;
+ definition.finalize = Derived_finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(functionObject);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(exception);
+
+ if (argumentCount > 0) {
+ JSStringRef string = JSValueToStringCopy(context, arguments[0], NULL);
+ size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
+ char* stringUTF8 = (char*)malloc(sizeUTF8);
+ JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
+ printf("%s\n", stringUTF8);
+ free(stringUTF8);
+ JSStringRelease(string);
+ }
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(constructorObject);
+ UNUSED_PARAM(exception);
+
+ JSObjectRef result = JSObjectMake(context, NULL, NULL);
+ if (argumentCount > 0) {
+ JSStringRef value = JSStringCreateWithUTF8CString("value");
+ JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
+ JSStringRelease(value);
+ }
+
+ return result;
+}
+
+
+static void globalObject_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(object);
+ // Ensure that an execution context is passed in
+ ASSERT(context);
+
+ // Ensure that the global object is set to the object that we were passed
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(globalObject);
+ ASSERT(object == globalObject);
+
+ // Ensure that the standard global properties have been set on the global object
+ JSStringRef array = JSStringCreateWithUTF8CString("Array");
+ JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
+ JSStringRelease(array);
+
+ UNUSED_PARAM(arrayConstructor);
+ ASSERT(arrayConstructor);
+}
+
+static JSValueRef globalObject_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 3);
+}
+
+static bool globalObject_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 3);
+ return true;
+}
+
+static JSValueRef globalObject_call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 3);
+}
+
+static JSStaticValue globalObject_staticValues[] = {
+ { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static JSStaticFunction globalObject_staticFunctions[] = {
+ { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static char* createStringWithContentsOfFile(const char* fileName);
+
+static void testInitializeFinalize()
+{
+ JSObjectRef o = JSObjectMake(context, Derived_class(context), (void*)1);
+ UNUSED_PARAM(o);
+ ASSERT(JSObjectGetPrivate(o) == (void*)3);
+}
+
+int main(int argc, char* argv[])
+{
+ const char *scriptPath = "testapi.js";
+ if (argc > 1) {
+ scriptPath = argv[1];
+ }
+
+ // Test garbage collection with a fresh context
+ context = JSGlobalContextCreateInGroup(NULL, NULL);
+ TestInitializeFinalize = true;
+ testInitializeFinalize();
+ JSGlobalContextRelease(context);
+ TestInitializeFinalize = false;
+
+ ASSERT(Base_didFinalize);
+
+ JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
+ globalObjectClassDefinition.initialize = globalObject_initialize;
+ globalObjectClassDefinition.staticValues = globalObject_staticValues;
+ globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
+ globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
+ context = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
+
+ JSGlobalContextRetain(context);
+ JSGlobalContextRelease(context);
+
+ JSReportExtraMemoryCost(context, 0);
+ JSReportExtraMemoryCost(context, 1);
+ JSReportExtraMemoryCost(context, 1024);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(JSValueIsObject(context, globalObject));
+
+ JSValueRef jsUndefined = JSValueMakeUndefined(context);
+ JSValueRef jsNull = JSValueMakeNull(context);
+ JSValueRef jsTrue = JSValueMakeBoolean(context, true);
+ JSValueRef jsFalse = JSValueMakeBoolean(context, false);
+ JSValueRef jsZero = JSValueMakeNumber(context, 0);
+ JSValueRef jsOne = JSValueMakeNumber(context, 1);
+ JSValueRef jsOneThird = JSValueMakeNumber(context, 1.0 / 3.0);
+ JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, NULL);
+ JSObjectSetPrototype(context, jsObjectNoProto, JSValueMakeNull(context));
+
+ // FIXME: test funny utf8 characters
+ JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
+ JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
+
+ JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
+ JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
+
+ UniChar singleUniChar = 65; // Capital A
+ CFMutableStringRef cfString =
+ CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
+ &singleUniChar,
+ 1,
+ 1,
+ kCFAllocatorNull);
+
+ JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
+ JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
+
+ CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
+
+ JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
+ JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
+
+ CFIndex cfStringLength = CFStringGetLength(cfString);
+ UniChar* buffer = (UniChar*)malloc(cfStringLength * sizeof(UniChar));
+ CFStringGetCharacters(cfString,
+ CFRangeMake(0, cfStringLength),
+ buffer);
+ JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, cfStringLength);
+ JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
+
+ JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, CFStringGetLength(cfEmptyString));
+ free(buffer);
+ JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
+
+ ASSERT(JSValueGetType(context, jsUndefined) == kJSTypeUndefined);
+ ASSERT(JSValueGetType(context, jsNull) == kJSTypeNull);
+ ASSERT(JSValueGetType(context, jsTrue) == kJSTypeBoolean);
+ ASSERT(JSValueGetType(context, jsFalse) == kJSTypeBoolean);
+ ASSERT(JSValueGetType(context, jsZero) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsOne) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsOneThird) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsEmptyString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsOneString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFStringWithCharacters) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
+
+ JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
+ JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
+ JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(myObjectIString);
+
+ JSValueRef exception;
+
+ // Conversions that throw exceptions
+ exception = NULL;
+ ASSERT(NULL == JSValueToObject(context, jsNull, &exception));
+ ASSERT(exception);
+
+ exception = NULL;
+ // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
+ // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
+ // After that's resolved, we can remove these casts
+ ASSERT(isnan((float)JSValueToNumber(context, jsObjectNoProto, &exception)));
+ ASSERT(exception);
+
+ exception = NULL;
+ ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
+ ASSERT(exception);
+
+ ASSERT(JSValueToBoolean(context, myObject));
+
+ exception = NULL;
+ ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
+ ASSERT(exception);
+
+ exception = NULL;
+ JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
+ ASSERT(1 == JSValueToNumber(context, exception, NULL));
+
+ assertEqualsAsBoolean(jsUndefined, false);
+ assertEqualsAsBoolean(jsNull, false);
+ assertEqualsAsBoolean(jsTrue, true);
+ assertEqualsAsBoolean(jsFalse, false);
+ assertEqualsAsBoolean(jsZero, false);
+ assertEqualsAsBoolean(jsOne, true);
+ assertEqualsAsBoolean(jsOneThird, true);
+ assertEqualsAsBoolean(jsEmptyString, false);
+ assertEqualsAsBoolean(jsOneString, true);
+ assertEqualsAsBoolean(jsCFString, true);
+ assertEqualsAsBoolean(jsCFStringWithCharacters, true);
+ assertEqualsAsBoolean(jsCFEmptyString, false);
+ assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
+
+ assertEqualsAsNumber(jsUndefined, nan(""));
+ assertEqualsAsNumber(jsNull, 0);
+ assertEqualsAsNumber(jsTrue, 1);
+ assertEqualsAsNumber(jsFalse, 0);
+ assertEqualsAsNumber(jsZero, 0);
+ assertEqualsAsNumber(jsOne, 1);
+ assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
+ assertEqualsAsNumber(jsEmptyString, 0);
+ assertEqualsAsNumber(jsOneString, 1);
+ assertEqualsAsNumber(jsCFString, nan(""));
+ assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
+ assertEqualsAsNumber(jsCFEmptyString, 0);
+ assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
+ ASSERT(sizeof(JSChar) == sizeof(UniChar));
+
+ assertEqualsAsCharactersPtr(jsUndefined, "undefined");
+ assertEqualsAsCharactersPtr(jsNull, "null");
+ assertEqualsAsCharactersPtr(jsTrue, "true");
+ assertEqualsAsCharactersPtr(jsFalse, "false");
+ assertEqualsAsCharactersPtr(jsZero, "0");
+ assertEqualsAsCharactersPtr(jsOne, "1");
+ assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
+ assertEqualsAsCharactersPtr(jsEmptyString, "");
+ assertEqualsAsCharactersPtr(jsOneString, "1");
+ assertEqualsAsCharactersPtr(jsCFString, "A");
+ assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
+ assertEqualsAsCharactersPtr(jsCFEmptyString, "");
+ assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
+
+ assertEqualsAsUTF8String(jsUndefined, "undefined");
+ assertEqualsAsUTF8String(jsNull, "null");
+ assertEqualsAsUTF8String(jsTrue, "true");
+ assertEqualsAsUTF8String(jsFalse, "false");
+ assertEqualsAsUTF8String(jsZero, "0");
+ assertEqualsAsUTF8String(jsOne, "1");
+ assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
+ assertEqualsAsUTF8String(jsEmptyString, "");
+ assertEqualsAsUTF8String(jsOneString, "1");
+ assertEqualsAsUTF8String(jsCFString, "A");
+ assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
+ assertEqualsAsUTF8String(jsCFEmptyString, "");
+ assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
+
+ ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
+ ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
+
+ ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
+ ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
+
+ CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
+ CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
+ ASSERT(CFEqual(cfJSString, cfString));
+ ASSERT(CFEqual(cfJSEmptyString, cfEmptyString));
+ CFRelease(cfJSString);
+ CFRelease(cfJSEmptyString);
+
+ CFRelease(cfString);
+ CFRelease(cfEmptyString);
+
+ jsGlobalValue = JSObjectMake(context, NULL, NULL);
+ JSValueProtect(context, jsGlobalValue);
+ JSGarbageCollect(context);
+ ASSERT(JSValueIsObject(context, jsGlobalValue));
+ JSValueUnprotect(context, jsGlobalValue);
+
+ JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
+ JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
+ ASSERT(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
+ ASSERT(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
+
+ JSValueRef result;
+ JSValueRef v;
+ JSObjectRef o;
+ JSStringRef string;
+
+ result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
+ ASSERT(result);
+ ASSERT(JSValueIsEqual(context, result, jsOne, NULL));
+
+ exception = NULL;
+ result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
+ ASSERT(!result);
+ ASSERT(JSValueIsObject(context, exception));
+
+ JSStringRef array = JSStringCreateWithUTF8CString("Array");
+ JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
+ JSStringRelease(array);
+ result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
+ ASSERT(result);
+ ASSERT(JSValueIsObject(context, result));
+ ASSERT(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
+ ASSERT(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(context), arrayConstructor, NULL));
+
+ o = JSValueToObject(context, result, NULL);
+ exception = NULL;
+ ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
+ ASSERT(!exception);
+
+ JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
+ ASSERT(!exception);
+
+ exception = NULL;
+ ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
+ ASSERT(!exception);
+
+ JSStringRef functionBody;
+ JSObjectRef function;
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
+ JSStringRef line = JSStringCreateWithUTF8CString("line");
+ ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
+ ASSERT(JSValueIsObject(context, exception));
+ v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
+ assertEqualsAsNumber(v, 1);
+ JSStringRelease(functionBody);
+ JSStringRelease(line);
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("return Array;");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception);
+ JSStringRelease(functionBody);
+ ASSERT(!exception);
+ ASSERT(JSObjectIsFunction(context, function));
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(v);
+ ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
+
+ exception = NULL;
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
+ ASSERT(!exception);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
+ ASSERT(v && !exception);
+ ASSERT(JSValueIsUndefined(context, v));
+
+ exception = NULL;
+ v = NULL;
+ JSStringRef foo = JSStringCreateWithUTF8CString("foo");
+ JSStringRef argumentNames[] = { foo };
+ functionBody = JSStringCreateWithUTF8CString("return foo;");
+ function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
+ ASSERT(function && !exception);
+ JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
+ v = JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
+ JSStringRelease(foo);
+ JSStringRelease(functionBody);
+
+ string = JSValueToStringCopy(context, function, NULL);
+ assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {return foo;}");
+ JSStringRelease(string);
+
+ JSStringRef print = JSStringCreateWithUTF8CString("print");
+ JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
+ JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(print);
+
+ ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
+ ASSERT(!JSObjectGetPrivate(printFunction));
+
+ JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
+ JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
+ JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(myConstructorIString);
+
+ ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
+ ASSERT(!JSObjectGetPrivate(myConstructor));
+
+ string = JSStringCreateWithUTF8CString("Derived");
+ JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
+ JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(string);
+
+ o = JSObjectMake(context, NULL, NULL);
+ JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
+ JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
+ size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
+ size_t count;
+ for (count = 0; count < expectedCount; ++count)
+ JSPropertyNameArrayGetNameAtIndex(nameArray, count);
+ JSPropertyNameArrayRelease(nameArray);
+ ASSERT(count == 1); // jsCFString should not be enumerated
+
+ JSValueRef argumentsArrayValues[] = { JSValueMakeNumber(context, 10), JSValueMakeNumber(context, 20) };
+ o = JSObjectMakeArray(context, sizeof(argumentsArrayValues) / sizeof(JSValueRef), argumentsArrayValues, NULL);
+ string = JSStringCreateWithUTF8CString("length");
+ v = JSObjectGetProperty(context, o, string, NULL);
+ assertEqualsAsNumber(v, 2);
+ v = JSObjectGetPropertyAtIndex(context, o, 0, NULL);
+ assertEqualsAsNumber(v, 10);
+ v = JSObjectGetPropertyAtIndex(context, o, 1, NULL);
+ assertEqualsAsNumber(v, 20);
+
+ o = JSObjectMakeArray(context, 0, NULL, NULL);
+ v = JSObjectGetProperty(context, o, string, NULL);
+ assertEqualsAsNumber(v, 0);
+ JSStringRelease(string);
+
+ JSValueRef argumentsDateValues[] = { JSValueMakeNumber(context, 0) };
+ o = JSObjectMakeDate(context, 1, argumentsDateValues, NULL);
+ assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
+
+ string = JSStringCreateWithUTF8CString("an error message");
+ JSValueRef argumentsErrorValues[] = { JSValueMakeString(context, string) };
+ o = JSObjectMakeError(context, 1, argumentsErrorValues, NULL);
+ assertEqualsAsUTF8String(o, "Error: an error message");
+ JSStringRelease(string);
+
+ string = JSStringCreateWithUTF8CString("foo");
+ JSStringRef string2 = JSStringCreateWithUTF8CString("gi");
+ JSValueRef argumentsRegExpValues[] = { JSValueMakeString(context, string), JSValueMakeString(context, string2) };
+ o = JSObjectMakeRegExp(context, 2, argumentsRegExpValues, NULL);
+ assertEqualsAsUTF8String(o, "/foo/gi");
+ JSStringRelease(string);
+ JSStringRelease(string2);
+
+ JSClassDefinition nullDefinition = kJSClassDefinitionEmpty;
+ nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef nullClass = JSClassCreate(&nullDefinition);
+ JSClassRelease(nullClass);
+
+ nullDefinition = kJSClassDefinitionEmpty;
+ nullClass = JSClassCreate(&nullDefinition);
+ JSClassRelease(nullClass);
+
+ functionBody = JSStringCreateWithUTF8CString("return this;");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
+ JSStringRelease(functionBody);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+
+ functionBody = JSStringCreateWithUTF8CString("return eval(\"this\");");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
+ JSStringRelease(functionBody);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+
+ JSStringRef script = JSStringCreateWithUTF8CString("this;");
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+ JSStringRelease(script);
+
+ script = JSStringCreateWithUTF8CString("eval(this);");
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+ JSStringRelease(script);
+
+ char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
+ if (!scriptUTF8)
+ printf("FAIL: Test script could not be loaded.\n");
+ else {
+ script = JSStringCreateWithUTF8CString(scriptUTF8);
+ result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
+ if (JSValueIsUndefined(context, result))
+ printf("PASS: Test script executed successfully.\n");
+ else {
+ printf("FAIL: Test script returned unexpected value:\n");
+ JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
+ CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
+ CFShow(exceptionCF);
+ CFRelease(exceptionCF);
+ JSStringRelease(exceptionIString);
+ }
+ JSStringRelease(script);
+ free(scriptUTF8);
+ }
+
+ // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
+ function = NULL;
+ v = NULL;
+ o = NULL;
+ globalObject = NULL;
+
+ JSStringRelease(jsEmptyIString);
+ JSStringRelease(jsOneIString);
+ JSStringRelease(jsCFIString);
+ JSStringRelease(jsCFEmptyIString);
+ JSStringRelease(jsCFIStringWithCharacters);
+ JSStringRelease(jsCFEmptyIStringWithCharacters);
+ JSStringRelease(goodSyntax);
+ JSStringRelease(badSyntax);
+
+ JSGlobalContextRelease(context);
+ JSClassRelease(globalObjectClass);
+
+ printf("PASS: Program exited normally.\n");
+ return 0;
+}
+
+static char* createStringWithContentsOfFile(const char* fileName)
+{
+ char* buffer;
+
+ size_t buffer_size = 0;
+ size_t buffer_capacity = 1024;
+ buffer = (char*)malloc(buffer_capacity);
+
+ FILE* f = fopen(fileName, "r");
+ if (!f) {
+ fprintf(stderr, "Could not open file: %s\n", fileName);
+ return 0;
+ }
+
+ while (!feof(f) && !ferror(f)) {
+ buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
+ if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
+ buffer_capacity *= 2;
+ buffer = (char*)realloc(buffer, buffer_capacity);
+ ASSERT(buffer);
+ }
+
+ ASSERT(buffer_size < buffer_capacity);
+ }
+ fclose(f);
+ buffer[buffer_size] = '\0';
+
+ return buffer;
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function shouldBe(a, b)
+{
+ var evalA;
+ try {
+ evalA = eval(a);
+ } catch(e) {
+ evalA = e;
+ }
+
+ if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
+ print("PASS: " + a + " should be " + b + " and is.", "green");
+ else
+ print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
+}
+
+function shouldThrow(a)
+{
+ var result = "__FAIL__: " + a + " did not throw an exception.";
+
+ var evalA;
+ try {
+ eval(a);
+ } catch(e) {
+ result = "PASS: " + a + " threw: " + e;
+ }
+
+ print(result);
+}
+
+function globalStaticFunction()
+{
+ return 4;
+}
+
+shouldBe("globalStaticValue", 3);
+shouldBe("globalStaticFunction()", 4);
+
+shouldBe("typeof MyObject", "function"); // our object implements 'call'
+MyObject.cantFind = 1;
+shouldBe("MyObject.cantFind", undefined);
+MyObject.regularType = 1;
+shouldBe("MyObject.regularType", 1);
+MyObject.alwaysOne = 2;
+shouldBe("MyObject.alwaysOne", 1);
+MyObject.cantDelete = 1;
+delete MyObject.cantDelete;
+shouldBe("MyObject.cantDelete", 1);
+shouldBe("delete MyObject.throwOnDelete", 2); // deleteProperty -- should throw 2
+MyObject.cantSet = 1;
+shouldBe("MyObject.cantSet", undefined);
+
+var foundMyPropertyName = false;
+var foundRegularType = false;
+for (var p in MyObject) {
+ if (p == "myPropertyName")
+ foundMyPropertyName = true;
+ if (p == "regularType")
+ foundRegularType = true;
+}
+print(foundMyPropertyName
+ ? "PASS: MyObject.myPropertyName was enumerated"
+ : "__FAIL__: MyObject.myPropertyName was not enumerated");
+print(foundRegularType
+ ? "PASS: MyObject.regularType was enumerated"
+ : "__FAIL__: MyObject.regularType was not enumerated");
+
+myObject = new MyObject();
+
+shouldBe("delete MyObject.regularType", true);
+shouldBe("MyObject.regularType", undefined);
+shouldBe("MyObject(0)", 1);
+shouldBe("MyObject()", undefined);
+shouldBe("typeof myObject", "object");
+shouldBe("MyObject ? 1 : 0", true); // toBoolean
+shouldBe("+MyObject", 1); // toNumber
+shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
+shouldBe("String(MyObject)", "MyObjectAsString"); // type conversion to string
+shouldBe("MyObject - 0", NaN); // toPrimitive
+
+shouldBe("typeof MyConstructor", "object");
+constructedObject = new MyConstructor(1);
+shouldBe("typeof constructedObject", "object");
+shouldBe("constructedObject.value", 1);
+shouldBe("myObject instanceof MyObject", true);
+shouldBe("(new Object()) instanceof MyObject", false);
+
+shouldThrow("MyObject.nullGetSet = 1");
+shouldThrow("MyObject.nullGetSet");
+shouldThrow("MyObject.nullCall()");
+shouldThrow("MyObject.hasPropertyLie");
+
+derived = new Derived();
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived.baseProtoDup()", 2);
+shouldBe("derived.baseProto()", 1);
+shouldBe("derived.baseDup", 2);
+shouldBe("derived.baseOnly", 1);
+shouldBe("derived.protoOnly()", 2);
+shouldBe("derived.protoDup", 2);
+shouldBe("derived.derivedOnly", 2)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived.baseDup = 0", 2);
+shouldBe("derived.baseOnly = 0", 1);
+shouldBe("derived.derivedOnly = 0", 2)
+shouldBe("derived.protoDup = 0", 2);
--- /dev/null
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// This file exists to help compile the essential code of
+// JavaScriptCore all as one file, for compilers and build systems
+// that see a significant speed gain from this.
+
+#define KDE_USE_FINAL 1
+#define JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE 1
+#include "config.h"
+
+// these headers are included here to avoid confusion between ::JSType and JSC::JSType
+#include "JSCallbackConstructor.h"
+#include "JSCallbackFunction.h"
+#include "JSCallbackObject.h"
+
+#include "runtime/JSStaticScopeObject.cpp"
+#include "runtime/JSFunction.cpp"
+#include "runtime/Arguments.cpp"
+#include "runtime/JSGlobalObjectFunctions.cpp"
+#include "runtime/PrototypeFunction.cpp"
+#include "runtime/GlobalEvalFunction.cpp"
+#include "debugger/Debugger.cpp"
+#include "runtime/JSArray.cpp"
+#include "runtime/ArrayConstructor.cpp"
+#include "runtime/ArrayPrototype.cpp"
+#include "runtime/BooleanConstructor.cpp"
+#include "runtime/BooleanObject.cpp"
+#include "runtime/BooleanPrototype.cpp"
+#include "runtime/Collector.cpp"
+#include "runtime/CommonIdentifiers.cpp"
+#include "runtime/DateConstructor.cpp"
+#include "runtime/DateMath.cpp"
+#include "runtime/DatePrototype.cpp"
+#include "runtime/DateInstance.cpp"
+#include "wtf/dtoa.cpp"
+#include "runtime/ErrorInstance.cpp"
+#include "runtime/ErrorPrototype.cpp"
+#include "runtime/ErrorConstructor.cpp"
+#include "runtime/FunctionConstructor.cpp"
+#include "runtime/FunctionPrototype.cpp"
+#include "Grammar.cpp"
+#include "runtime/Identifier.cpp"
+#include "runtime/JSString.cpp"
+#include "runtime/JSNumberCell.cpp"
+#include "runtime/GetterSetter.cpp"
+#include "runtime/InternalFunction.cpp"
+#include "runtime/Completion.cpp"
+#include "runtime/JSImmediate.cpp"
+#include "runtime/JSLock.cpp"
+#include "runtime/JSWrapperObject.cpp"
+#include "parser/Lexer.cpp"
+#include "runtime/ArgList.cpp"
+#include "runtime/Lookup.cpp"
+#include "runtime/MathObject.cpp"
+#include "runtime/NativeErrorConstructor.cpp"
+#include "runtime/NativeErrorPrototype.cpp"
+#include "runtime/NumberConstructor.cpp"
+#include "runtime/NumberObject.cpp"
+#include "runtime/NumberPrototype.cpp"
+#include "parser/Nodes.cpp"
+#include "runtime/JSObject.cpp"
+#include "runtime/Error.cpp"
+#include "runtime/JSGlobalObject.cpp"
+#include "runtime/ObjectConstructor.cpp"
+#include "runtime/ObjectPrototype.cpp"
+#include "runtime/Operations.cpp"
+#include "parser/Parser.cpp"
+#include "runtime/PropertySlot.cpp"
+#include "runtime/PropertyNameArray.cpp"
+#include "runtime/RegExp.cpp"
+#include "runtime/RegExpConstructor.cpp"
+#include "runtime/RegExpObject.cpp"
+#include "runtime/RegExpPrototype.cpp"
+#include "runtime/ScopeChain.cpp"
+#include "runtime/StringConstructor.cpp"
+#include "runtime/StringObject.cpp"
+#include "runtime/StringPrototype.cpp"
+#include "runtime/UString.cpp"
+#include "runtime/JSValue.cpp"
+#include "runtime/CallData.cpp"
+#include "runtime/ConstructData.cpp"
+#include "runtime/JSCell.cpp"
+#include "runtime/JSVariableObject.cpp"
+#include "wtf/FastMalloc.cpp"
+#include "wtf/TCSystemAlloc.cpp"
+#include "bytecompiler/BytecodeGenerator.cpp"
+#include "interpreter/RegisterFile.cpp"
--- /dev/null
+2008-08-10 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Reviewed (and updated) by Alp Toker.
+
+ https://bugs.webkit.org/show_bug.cgi?id=16620
+ [GTK] Autotools make dist and make check support
+
+ Get make dist working.
+
+ Note that not all possible configurations have been tested yet.
+
+ * GNUmakefile.am:
+
+2008-08-09 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Sam Weinig.
+
+ Added same heap debug checks to more code paths.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::put):
+ (KJS::JSActivation::putWithAttributes):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::putWithAttributes):
+ * kjs/JSObject.h:
+ (KJS::JSObject::putDirect):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTablePut):
+ (KJS::JSVariableObject::symbolTablePutWithAttributes):
+
+2008-08-09 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Fix some style issues in the sampling tool.
+
+ * VM/SamplingTool.cpp:
+ (KJS::sleepForMicroseconds):
+ (KJS::SamplingTool::dump):
+
+2008-08-09 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Revision 35651, despite being a rather trivial change, introduced a
+ large regression on the regexp-dna SunSpider test. This regression
+ stemmed from an increase in the size of CodeBlock::dump(). There is
+ no reason for this method (and several related methods) to be compiled
+ in non-debug builds with the sampling tool disabled. This patch
+ conditionally compiles them, reversing the regression on SunSpider.
+
+ * JavaScriptCore.exp:
+ * VM/CodeBlock.cpp:
+ * VM/CodeBlock.h:
+ * VM/Machine.cpp:
+
+2008-08-08 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 20330: JSCore crash loading any filehurricane media page
+ <https://bugs.webkit.org/show_bug.cgi?id=20330>
+
+ Fix a typo in the constant loading patch. Also, add a case for
+ op_unexpected_load to CodeBlock::dump().
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addUnexpectedConstant):
+
+2008-08-08 Matt Lilek <webkit@mattlilek.com>
+
+ Not reviewed, build fix.
+
+ * JavaScriptCore.exp:
+
+2008-08-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Improve performance of arithmetic operators
+
+ Added a fast (non-virtual) mechanism to determine if a non-immediate JSValue*
+ is a JSNumberCell. We then use this to allow improved specialisation in many
+ arithmetic operators. SunSpider reports a 2.5% progression overall, with greater
+ than 10% progressions on a number of arithmetic heavy tests.
+
+ * VM/Machine.cpp:
+ (KJS::fastIsNumber):
+ (KJS::fastToInt32):
+ (KJS::fastToUInt32):
+ (KJS::jsLess):
+ (KJS::jsLessEq):
+ (KJS::jsAdd):
+ (KJS::Machine::privateExecute):
+ * kjs/JSNumberCell.h:
+ (KJS::JSNumberCell::fastToInt32):
+ (KJS::JSNumberCell::fastToUInt32):
+ * kjs/collector.cpp:
+ (KJS::allocateBlock):
+ (KJS::Heap::heapAllocate):
+ * kjs/collector.h:
+ (KJS::Heap::fastIsNumber):
+
+2008-08-06 Adam Roben <aroben@apple.com>
+
+ Try to fix the Windows build bots
+
+ * API/JSBase.cpp: Touch this to force JSC to rebuild and re-copy the
+ WTF headers.
+
+2008-08-06 Tor Arne Vestbø <tavestbo@trolltech.com>
+
+ Revert change 35595.
+
+ * wtf/RetainPtr.h:
+
+2008-08-06 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Fix non-Mac build.
+
+ * wtf/RetainPtr.h: CoreFoundation only for PLATFORM(MAC)
+
+2008-08-06 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Fix non-Mac build.
+
+ * wtf/RetainPtr.h: CoreFoundation only for PLATFORM(MAC)
+
+2008-08-06 Csaba Osztrogonac <oszi@inf.u-szeged.hu>
+
+ Reviewed by Darin. Landed by Cameron.
+
+ Bug 20272: typo in JavaScriptCore
+ <https://bugs.webkit.org/show_bug.cgi?id=20272>
+
+ Correct the documentation for op_not. (typo)
+ Fix #undef. (typo)
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-08-06 Cameron Zwarich <cwzwarich@webkit.org>
+
+ Reviewed by Maciej.
+
+ Bug 20286: Load constants all at once instead of using op_load
+ <https://bugs.webkit.org/show_bug.cgi?id=20286>
+
+ Load constants all at once into temporary registers instead of using
+ individual instances of op_load.
+
+ This is a 2.6% speedup on SunSpider.
+
+ * JavaScriptCore.exp:
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ (KJS::CodeBlock::mark):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::newTemporary):
+ (KJS::CodeGenerator::addConstant):
+ (KJS::CodeGenerator::addUnexpectedConstant):
+ (KJS::CodeGenerator::emitLoad):
+ (KJS::CodeGenerator::emitUnexpectedLoad):
+ (KJS::CodeGenerator::emitNewError):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::throwException):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * VM/Opcode.h:
+ * VM/RegisterID.h:
+ (KJS::RegisterID::RegisterID):
+ (KJS::RegisterID::makeConstant):
+ (KJS::RegisterID::isTemporary):
+ * kjs/NodeInfo.h:
+ * kjs/Parser.cpp:
+ (KJS::Parser::didFinishParsing):
+ * kjs/Parser.h:
+ (KJS::Parser::parse):
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::NullNode::emitCode):
+ (KJS::BooleanNode::emitCode):
+ (KJS::NumberNode::emitCode):
+ (KJS::StringNode::emitCode):
+ (KJS::ArrayNode::emitCode):
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::DeleteValueNode::emitCode):
+ (KJS::VoidNode::emitCode):
+ (KJS::ConstDeclNode::emitCodeSingle):
+ (KJS::ReturnNode::emitCode):
+ (KJS::ScopeNode::ScopeNode):
+ (KJS::ProgramNode::ProgramNode):
+ (KJS::ProgramNode::create):
+ (KJS::EvalNode::EvalNode):
+ (KJS::EvalNode::create):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::FunctionBodyNode::create):
+ (KJS::FunctionBodyNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::ScopeNode::neededConstants):
+
+2008-08-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Cameron.
+
+ - add fast path for immediates to % operator, as we have for many other math ops
+
+ This fixes handling for a 0 divisor relative to the last patch. Only an 0.2% speedup on SunSpider but
+ still a 1.4x win on Oliver's prime test.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-08-05 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 20293: Crash in JavaScript codegen for eval("const a;")
+ <https://bugs.webkit.org/show_bug.cgi?id=20293>
+
+ Correctly handle constant declarations in eval code with no initializer.
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::emitCodeSingle):
+
+2008-08-05 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Roll out r35555 because of correctness issues.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-08-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - add fast path for immediates to % operator, as we have for many other math ops
+
+ 0.6% speedup on SunSpider. 1.4x speedup on a prime testing torture test that Oliver whipped up.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-07-31 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Bug 19359: JavaScriptCore behaves differently from FF2/3 and IE when handling context in catch statement
+ <https://bugs.webkit.org/show_bug.cgi?id=19359>
+
+ Make our catch behave like Firefox and IE, we do this by using a StaticScopeObject
+ instead of a generic JSObject for the scope node. We still don't make use of the
+ fact that we have a static scope inside the catch block, so the internal performance
+ of the catch block is not improved, even though technically it would be possible to
+ do so.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPushNewScope):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::createExceptionScope):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * VM/Opcode.h:
+ * kjs/JSStaticScopeObject.cpp:
+ (KJS::JSStaticScopeObject::toThisObject):
+ (KJS::JSStaticScopeObject::put):
+ * kjs/JSStaticScopeObject.h:
+ * kjs/nodes.cpp:
+ (KJS::TryNode::emitCode):
+
+2008-08-02 Rob Gowin <robg@gowin.net>
+
+ Reviewed by Eric Seidel.
+
+ Added JavaScriptCore/API/WebKitAvailability to list of files in
+ javascriptcore_h_api.
+
+ * GNUmakefile.am:
+
+2008-08-01 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Maciej.
+
+ Remove JSGlobalData::DataInstance. It was only needed when we had per-thread JSGlobalData
+ instances.
+
+ * kjs/JSGlobalData.h:
+
+2008-07-31 Kevin Ollivier <kevino@theolliviers.com>
+
+ Second attempt at Windows/wx build fix. Instead of avoiding inclusion of windows.h,
+ use defines, etc. to avoid conflicts in each affected file. Also, change PLATFORM(WIN)
+ to PLATFORM(WIN_OS) so that other ports using Windows headers get the right impls.
+
+ * VM/SamplingTool.cpp:
+ * wtf/Threading.h:
+
+2008-07-31 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Adam.
+
+ Fix Windows build.
+
+ * kjs/collector.h:
+ * wtf/FastMalloc.cpp:
+
+2008-07-31 Csaba Osztrogonac <oszi@inf.u-szeged.hu>
+
+ Reviewed by Simon.
+
+ Bug 20170: [Qt] missing namespace defines in JavaScriptCore.pro
+ <https://bugs.webkit.org/show_bug.cgi?id=20170>
+
+ * JavaScriptCore.pro: Added missing define.
+
+2008-07-31 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Maciej.
+
+ Eliminate JSLock (it was already disabled, removing the stub implementaion and all
+ call sites now).
+
+ * API/JSBase.cpp:
+ (JSEvaluateScript):
+ (JSCheckScriptSyntax):
+ (JSGarbageCollect):
+ * API/JSCallbackConstructor.cpp:
+ (KJS::constructJSCallback):
+ * API/JSCallbackFunction.cpp:
+ (KJS::JSCallbackFunction::call):
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::init):
+ (KJS::::getOwnPropertySlot):
+ (KJS::::put):
+ (KJS::::deleteProperty):
+ (KJS::::construct):
+ (KJS::::hasInstance):
+ (KJS::::call):
+ (KJS::::getPropertyNames):
+ (KJS::::toNumber):
+ (KJS::::toString):
+ (KJS::::staticValueGetter):
+ (KJS::::callbackGetter):
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreateInGroup):
+ (JSGlobalContextRetain):
+ (JSGlobalContextRelease):
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeConstructor):
+ (JSObjectMakeFunction):
+ (JSObjectHasProperty):
+ (JSObjectGetProperty):
+ (JSObjectSetProperty):
+ (JSObjectGetPropertyAtIndex):
+ (JSObjectSetPropertyAtIndex):
+ (JSObjectDeleteProperty):
+ (JSObjectCallAsFunction):
+ (JSObjectCallAsConstructor):
+ (JSObjectCopyPropertyNames):
+ (JSPropertyNameArrayRelease):
+ (JSPropertyNameAccumulatorAddName):
+ * API/JSStringRef.cpp:
+ (JSStringRelease):
+ * API/JSValueRef.cpp:
+ (JSValueIsEqual):
+ (JSValueIsInstanceOfConstructor):
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ (JSValueToNumber):
+ (JSValueToStringCopy):
+ (JSValueToObject):
+ (JSValueProtect):
+ (JSValueUnprotect):
+ * ForwardingHeaders/JavaScriptCore/JSLock.h: Removed.
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.order:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ * kjs/JSGlobalData.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject):
+ (KJS::JSGlobalObject::init):
+ * kjs/JSLock.cpp: Removed.
+ * kjs/JSLock.h: Removed.
+ * kjs/Shell.cpp:
+ (functionGC):
+ (jscmain):
+ * kjs/collector.cpp:
+ (KJS::Heap::~Heap):
+ (KJS::Heap::heapAllocate):
+ (KJS::Heap::setGCProtectNeedsLocking):
+ (KJS::Heap::protect):
+ (KJS::Heap::unprotect):
+ (KJS::Heap::collect):
+ * kjs/identifier.cpp:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::checkSyntax):
+ (KJS::Interpreter::evaluate):
+
+2008-07-31 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Oliver Hunt.
+
+ Fix the Mac project to not display "test/" as part of file name for tests.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-31 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Rename USE(MULTIPLE_THREADS) to ENABLE(JSC_MULTIPLE_THREADS)
+ to better match the use/enable pattern (and better describe
+ the usage of the feature in question.)
+
+ I also fixed a couple other ENABLE_ macros to be pre-processor
+ definition override-able to match the rest of the ENABLE_ macros
+ since it seems to be our convention that build systems can set
+ ENABLE_ macros in Makefiles.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreadingOnce):
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::~JSGlobalData):
+ * kjs/MathObject.cpp:
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap):
+ (KJS::Heap::~Heap):
+ (KJS::allocateBlock):
+ (KJS::Heap::markStackObjectsConservatively):
+ * kjs/collector.h:
+ * kjs/dtoa.cpp:
+ (KJS::pow5mult):
+ (KJS::rv_alloc):
+ (KJS::freedtoa):
+ (KJS::dtoa):
+ * wtf/FastMalloc.cpp:
+ * wtf/Platform.h:
+ * wtf/RefCountedLeakCounter.cpp:
+
+2008-07-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Try to clean up our usage of USE(MULTIPLE_THREADS) vs. USE(PTHREADS) a little.
+ It looks like JSC assumes that if MULTIPLE_THREADS is defined, then pthreads will always be available
+ I'm not sure that's always the case for gtk, certainly not for Windows. We should eventually go back
+ and fix wtf/Threading.h to cover all these cases some day.
+
+ * kjs/JSLock.cpp:
+ * kjs/collector.h:
+ * wtf/Platform.h:
+
+2008-07-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ MSVC warns when structs are called classes or vice versa.
+ Make all the source refer to JSGlobalData as a class.
+
+ * kjs/CommonIdentifiers.h:
+ * kjs/JSGlobalData.h:
+ * kjs/Parser.h:
+ * kjs/lexer.h:
+
+2008-07-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Add consistency checks to UString to document and enforce its design.
+
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::create):
+ (KJS::UString::Rep::destroy):
+ (KJS::UString::Rep::checkConsistency):
+ (KJS::UString::expandCapacity):
+ (KJS::UString::expandPreCapacity):
+ (KJS::UString::UString):
+ (KJS::UString::spliceSubstringsWithSeparators):
+ (KJS::UString::append):
+ * kjs/ustring.h:
+ (KJS::UString::Rep::checkConsistency):
+
+2008-07-30 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Fixes for Windows and non-AllInOne file build with SamplingTool, plus review fixes.
+
+ * GNUmakefile.am: Adding SamplingTool.cpp to build.
+ * JavaScriptCore.exp: Export hooks to init & control SamplingTool.
+ * JavaScriptCore.pri: Adding SamplingTool.cpp to build.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Adding SamplingTool.cpp to build.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Adding SamplingTool.cpp to build.
+ * JavaScriptCoreSources.bkl: Adding SamplingTool.cpp to build.
+ * VM/Machine.cpp: MACHINE_SAMPLING_callingNativeFunction renamed MACHINE_SAMPLING_callingHostFunction
+ * VM/Machine.h:
+ * VM/Opcode.cpp: SamplingTool moved to SamplingTool.cpp/.h, opcodeNames generated from FOR_EACH_OPCODE_ID.
+ * VM/Opcode.h:
+ * VM/SamplingTool.cpp: Added .cpp/.h for SamplingTool.
+ * VM/SamplingTool.h:
+ * kjs/Shell.cpp: Switched SAMPLING_TOOL_ENABLED to ENABLE_SAMPLING_TOOL.
+ * wtf/Platform.h: Added ENABLE_SAMPLING_TOOL config option.
+ * kjs/nodes.cpp: Header include to fix non-AllInOne builds.
+
+2008-07-30 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Fix compilation without multi-threading support.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap):
+
+2008-07-30 Anders Carlsson <andersca@apple.com>
+
+ Add WebKitAvailability.h forwarding header.
+
+ * ForwardingHeaders/JavaScriptCore/WebKitAvailability.h: Added.
+
+2008-07-30 Anders Carlsson <andersca@apple.com>
+
+ Fix the else.
+
+ * API/WebKitAvailability.h:
+
+2008-07-30 Anders Carlsson <andersca@apple.com>
+
+ * API/WebKitAvailability.h:
+ Fix Windows (and other non-Mac builds).
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ Add WebKitAvailability.h to the project.
+
+2008-07-30 Anders Carlsson <andersca@apple.com>
+
+ One step closer towards fixing the Windows build.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ Make sure to copy WebKitAvailability.h
+
+2008-07-29 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Bug 20209: Atomize constant strings
+ <https://bugs.webkit.org/show_bug.cgi?id=20209>
+
+ Prevents significant performance degradation seen when a script contains multiple
+ identical strings that are used as keys to identify properties on objects.
+
+ No performance change on SunSpider.
+
+ * kjs/nodes.cpp: Atomize constant strings.
+
+2008-07-30 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ <rdar://problem/6111648> JavaScript exceptions fail if the scope chain includes the global object
+
+ In an attempt to remove the branch I just added to KJS::depth I
+ used the existence of a Variable Object at a point in the scope
+ chain as an indicator of function or global scope activation.
+ However this assumption results in incorrect behaviour if the
+ global object is injected into the scope chain with 'with'.
+
+ * VM/Machine.cpp:
+ (KJS::depth):
+
+2008-07-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Don't call JSGarbageCollect() on a released context.
+
+ * API/testapi.c: (main):
+
+2008-07-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Implement JSContextGroup APIs to make concurrent execution possible for
+ JavaScriptCore clients.
+
+ This changes the behavior of JSGlobalContextCreate(), so that it now uses a private context
+ group for each context, making JSlock implicit locking unnecessary.
+
+ * API/JSContextRef.h:
+ * API/JSContextRef.cpp:
+ (JSContextGroupCreate):
+ (JSContextGroupRetain):
+ (JSContextGroupRelease):
+ (JSGlobalContextCreate):
+ (JSGlobalContextCreateInGroup):
+ (JSGlobalContextRelease):
+ (JSContextGetGroup):
+ Added new methods. JSGlobalContextCreate() calls JSGlobalContextCreateInGroup() now.
+
+ * API/APICast.h: (toJS): (toRef): Added converters for JSContextGroupRef.
+ * API/JSBase.cpp: (JSGarbageCollect): JSGarbageCollect(0) is now a no-op, and the passed in
+ context is actually used.
+
+ * API/JSBase.h: Aded a typedef for JSContextGroupRef. Updated documentation for
+ JSGarbageCollect().
+
+ * JavaScriptCore.exp: Removed JSGlobalData::sharedInstance().
+
+ * kjs/JSGlobalData.cpp:
+ * kjs/JSGlobalData.h:
+ Removed support for JSGlobalData shared instance. JSGlobalData::isSharedInstance member
+ variable still remains, to be deleted in a followup patch.
+
+ * kjs/JSLock.cpp: (KJS::JSLock::JSLock): Disabled JSLock, to be deleted in a follow-up patch.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::markOtherThreadConservatively): Removed an assertion that referenced
+ JSGlobalData::sharedInstance.
+
+ * kjs/collector.h: Made Heap destructor public, so that JSContextRelease can use it.
+
+2008-07-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Fix a leak of ThreadRegistrar objects.
+
+ As the heap is usually deleted when registered threads still exist, ThreadSpecific doesn't
+ have a chance to clean up per-thread object. Switched to native pthread calls, storing a
+ plain pointer that doesn't require cleanup.
+
+ * kjs/collector.cpp:
+ (KJS::PlatformThread::PlatformThread):
+ (KJS::Heap::Thread::Thread):
+ (KJS::Heap::Heap):
+ (KJS::Heap::~Heap):
+ (KJS::Heap::registerThread):
+ (KJS::Heap::unregisterThread):
+ * kjs/collector.h:
+
+2008-07-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Sam Weinig.
+
+ https://bugs.webkit.org/show_bug.cgi?id=20169
+ Memory allocated with fastMalloc is freed with delete
+
+ * VM/JSPropertyNameIterator.cpp:
+ (KJS::JSPropertyNameIterator::invalidate): Free the array properly.
+ (KJS::JSPropertyNameIterator::~JSPropertyNameIterator): Delete the array by calling
+ invalidate().
+
+2008-07-29 Mark Rowe <mrowe@apple.com>
+
+ Attempt to fix the Qt build.
+
+ * wtf/ThreadingQt.cpp: Add the extra argument to createThread.
+
+2008-07-29 Adam Roben <aroben@apple.com>
+
+ Change Vector::find to return an index instead of an iterator
+
+ Indices are more natural than iterators when working with Vector.
+
+ Reviewed by John Sullivan.
+
+ * wtf/Vector.h:
+ (WTF::Vector::find): Changed to iterate the Vector manually and return
+ the index of the found item, rather than an iterator. When the item
+ could not be found, we return WTF::notFound.
+
+2008-07-29 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::setThreadName): Move a misplaced assertion to here...
+ (WTF::createThread): ...from here.
+
+2008-07-29 Adam Roben <aroben@apple.com>
+
+ Add support for setting thread names on Windows
+
+ These thread names make it much easier to identify particular threads
+ in Visual Studio's Threads panel.
+
+ WTF::createThread now takes a const char* representing the thread's
+ name. On Windows, we throw a special exception to set this string as
+ the thread's name. Other platforms do nothing with this name for now.
+
+ Reviewed by Anders Carlsson.
+
+ * JavaScriptCore.exp: Export the new version of createThread that
+ takes 3 arguments (the old one continues to be exported for backward
+ compatibility).
+ * wtf/Threading.h: Add a threadName argument to createThread.
+
+ * wtf/ThreadingGtk.cpp:
+ (WTF::createThread):
+ * wtf/ThreadingNone.cpp:
+ (WTF::createThread):
+ Updated for function signature change.
+
+ * wtf/ThreadingPthreads.cpp:
+ (WTF::createThread): Updated for function signature change. We keep
+ around the old 2-argument version of createThread for backward
+ compatibility.
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::setThreadName): Added. This function's implementation came from
+ MSDN.
+ (WTF::initializeThreading): Set the name of the main thread.
+ (WTF::createThread): Call setThreadName. We keep around the old
+ 2-argument version of createThread for backward compatibility.
+
+2008-07-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Store UString::Rep::isStatic bit in identifierTable pointer instead of reportedCost for
+ slightly nicer code and a 0.5% SunSpider improvement.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::~OpaqueJSClass):
+ (OpaqueJSClassContextData::OpaqueJSClassContextData):
+ * API/JSStringRef.cpp:
+ (JSStringRelease):
+ * kjs/PropertyNameArray.cpp:
+ (KJS::PropertyNameArray::add):
+ * kjs/identifier.cpp:
+ (KJS::IdentifierTable::~IdentifierTable):
+ (KJS::IdentifierTable::add):
+ (KJS::Identifier::addSlowCase):
+ (KJS::Identifier::remove):
+ * kjs/identifier.h:
+ (KJS::Identifier::add):
+ * kjs/ustring.cpp:
+ (KJS::):
+ (KJS::UString::Rep::create):
+ (KJS::UString::Rep::destroy):
+ * kjs/ustring.h:
+ (KJS::UString::Rep::identifierTable):
+ (KJS::UString::Rep::setIdentifierTable):
+ (KJS::UString::Rep::isStatic):
+ (KJS::UString::Rep::setStatic):
+ (KJS::UString::cost):
+
+2008-07-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Renamed "ConstructTypeNative" => "ConstructTypeHost".
+
+2008-07-26 Mark Rowe <mrowe@apple.com>
+
+ Speculative fix for the wx build.
+
+ * JavaScriptCoreSources.bkl: Add JSStaticScopeObject.cpp to the list of source files.
+
+2008-07-25 Oliver Hunt <oliver@apple.com>
+
+ RS=Cameron Zwarich.
+
+ Whoops, forgot to save style correction.
+
+ * kjs/JSStaticScopeObject.h:
+
+2008-07-25 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Bug 19718: Named anonymous functions are slow accessing global variables
+ <https://bugs.webkit.org/show_bug.cgi?id=19718>
+
+ To fix this we switch over to an activation-like scope object for
+ on which we attach the function name property, and add logic to
+ prevent cross scope assignment to read only properties.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::findScopedProperty):
+ (KJS::CodeGenerator::emitResolve):
+ * VM/CodeGenerator.h:
+ * kjs/AllInOneFile.cpp:
+ * kjs/JSStaticScopeObject.cpp: Added.
+ (KJS::JSStaticScopeObject::putWithAttributes):
+ (KJS::JSStaticScopeObject::isDynamicScope):
+ (KJS::JSStaticScopeObject::~JSStaticScopeObject):
+ (KJS::JSStaticScopeObject::getOwnPropertySlot):
+ * kjs/JSStaticScopeObject.h: Added.
+ (KJS::JSStaticScopeObject::JSStaticScopeObjectData::JSStaticScopeObjectData):
+ (KJS::JSStaticScopeObject::JSStaticScopeObject):
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::emitCode):
+ (KJS::PostfixResolveNode::emitCode):
+ (KJS::PrefixResolveNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::FuncExprNode::makeFunction):
+
+2008-07-25 kevino <kevino@theolliviers.com>
+
+ wx build fix for Win.
+
+ On wx/Win, including windows.h in Threading.h causes multiply-defined symbol errors
+ for libjpeg and wx, and also wx needs to include windows.h itself first for wx
+ includes to work right. So until we can find a better solution to this problem,
+ on wx, we work around the need to include windows.h here.
+
+ * wtf/Threading.h:
+
+2008-07-25 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/testapi/testapi.vcproj: Add API/ to the
+ include path.
+
+2008-07-25 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the build of jsc on Qt/Windows, make sure os-win32 is in the
+ include search path (added by WebKit.pri).
+
+ * kjs/jsc.pro:
+
+2008-07-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Simon Hausmann.
+
+ Move JavaScriptCore API tests into a subdirectory of their own to avoid header name
+ conflicts and developer confusion.
+
+ * API/JSNode.c: Removed.
+ * API/JSNode.h: Removed.
+ * API/JSNodeList.c: Removed.
+ * API/JSNodeList.h: Removed.
+ * API/Node.c: Removed.
+ * API/Node.h: Removed.
+ * API/NodeList.c: Removed.
+ * API/NodeList.h: Removed.
+ * API/minidom.c: Removed.
+ * API/minidom.html: Removed.
+ * API/minidom.js: Removed.
+ * API/testapi.c: Removed.
+ * API/testapi.js: Removed.
+ * API/tests: Added.
+ * API/tests/JSNode.c: Copied from JavaScriptCore/API/JSNode.c.
+ * API/tests/JSNode.h: Copied from JavaScriptCore/API/JSNode.h.
+ * API/tests/JSNodeList.c: Copied from JavaScriptCore/API/JSNodeList.c.
+ * API/tests/JSNodeList.h: Copied from JavaScriptCore/API/JSNodeList.h.
+ * API/tests/Node.c: Copied from JavaScriptCore/API/Node.c.
+ * API/tests/Node.h: Copied from JavaScriptCore/API/Node.h.
+ * API/tests/NodeList.c: Copied from JavaScriptCore/API/NodeList.c.
+ * API/tests/NodeList.h: Copied from JavaScriptCore/API/NodeList.h.
+ * API/tests/minidom.c: Copied from JavaScriptCore/API/minidom.c.
+ * API/tests/minidom.html: Copied from JavaScriptCore/API/minidom.html.
+ * API/tests/minidom.js: Copied from JavaScriptCore/API/minidom.js.
+ * API/tests/testapi.c: Copied from JavaScriptCore/API/testapi.c.
+ * API/tests/testapi.js: Copied from JavaScriptCore/API/testapi.js.
+ * GNUmakefile.am:
+ * JavaScriptCore.vcproj/testapi/testapi.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-25 Simon Hausmann <hausmann@webkit.org>
+
+ Prospective WX build fix, add JavaScriptCore/API to the include search
+ path.
+
+ * jscore.bkl:
+
+2008-07-25 Simon Hausmann <hausmann@webkit.org>
+
+ Rubber-stamped by Lars.
+
+ Fix the build on Windows. operator new for ArgList is implemented using fastMalloc()
+ but operator delete was not implemented. Unfortunately MSVC decides to call/reference
+ the function, so a simple implementation using fastFree() fixes the build.
+
+ * kjs/ArgList.h:
+ (KJS::ArgList::operator delete):
+
+2008-07-25 Simon Hausmann <hausmann@webkit.org>
+
+ Discussed with and rubber-stamped by Lars.
+
+ Fix the build system for the Qt port.
+
+ Recent JavaScriptCore changes require the addition of JavaScriptCore/API to the
+ include search path. With a build process that combines JavaScriptCore and
+ WebCore in one build process/Makefile the existance of
+ JavaScriptCore/API/Node.h and WebCore/dom/Node.h causes include conflicts.
+
+ This commit solves this by introducing a separate build of JavaScriptCore into
+ a static library.
+
+ As a result of the split-up a race-condition due to broken dependencies of
+ regular source files to header files of generated sources showed up very
+ frequently when doing parallel builds (which the buildbot does). This commit at
+ the same time tries to address the dependency problem by making the
+ addExtraCompiler() function also generate a pseudo extra compiler that
+ represents the header file output, so that qmake is aware of the creation of
+ the header file for dependency calculation.
+
+ At the same time I removed a lot of cruft from the pro files to ease maintenance.
+
+ * JavaScriptCore.pri:
+ * JavaScriptCore.pro: Added.
+ * kjs/jsc.pro:
+
+2008-07-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed a strict aliasing violation, which caused hash tables with floating
+ point keys not to find items that were indeed in the tables
+ (intermittently, and only in release builds, of course).
+
+ SunSpider reports no change.
+
+ This bug doesn't seem to affect any existing code, but it causes obvious
+ crashes in some new code I'm working on.
+
+ * wtf/HashFunctions.h:
+ (WTF::FloatHash::hash): Use a union when punning between a float / double
+ and an unsigned (bucket of bits). With strict aliasing enabled, unions
+ are the only safe way to do this kind of type punning.
+
+ * wtf/HashTable.h: When rehashing, ASSERT that the item we just added to
+ the table is indeed in the table. In the buggy case described above, this
+ ASSERT fires.
+
+2008-07-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Bug 20142: REGRESSION(r35245): /=/ weirdness
+ <https://bugs.webkit.org/show_bug.cgi?id=20142>
+
+ When adding all the meta data needed for exception error messages
+ I accidentally clobbered the handling of regex beginning with /=.
+
+ * kjs/grammar.y:
+
+2008-07-23 Alp Toker <alp@nuanti.com>
+
+ Build fix after r35293: Add API/ to the include path.
+
+ * GNUmakefile.am:
+
+2008-07-23 Adam Roben <aroben@apple.com>
+
+ Windows build fixes
+
+ Build fix after r35293:
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add API/
+ to the include path.
+
+ Build fix after r35305:
+
+ * VM/Machine.cpp:
+ * VM/Machine.h:
+ * VM/Opcode.cpp:
+ * VM/Opcode.h:
+ Completely compile out all sampler-related code when
+ SAMPLING_TOOL_ENABLED is 0. The sampler code can't be compiled 1) on
+ non-AllInOne configurations due to circular header dependencies, and
+ 2) on platforms that don't have a usleep() function, such as Windows.
+
+2008-07-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff Garen and Sam Weinig.
+
+ Improve switch performance.
+
+ Improve switch performance by converting to a hashmap based jump
+ table to avoid the sequence of dispatches that would otherwise be
+ needed. This results in a 9-19x performance win for string switches
+ based on ad hoc testing, and a 6x improvement for integer switch
+ statements. SunSpider reports a 1.2% progression.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ (KJS::SimpleJumpTable::offsetForValue):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::beginSwitch):
+ (KJS::prepareJumpTableForImmediateSwitch):
+ (KJS::prepareJumpTableForCharacterSwitch):
+ (KJS::prepareJumpTableForStringSwitch):
+ (KJS::CodeGenerator::endSwitch):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::offsetForStringSwitch):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.cpp:
+ (KJS::):
+ * VM/Opcode.h:
+ * kjs/JSImmediate.h:
+ * kjs/nodes.cpp:
+ (KJS::):
+ (KJS::processClauseList):
+ (KJS::CaseBlockNode::tryOptimisedSwitch):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+ * kjs/nodes.h:
+ (KJS::SwitchInfo::):
+
+2008-07-23 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Sampling tool to analyze cost of instruction execution and identify hot regions of JS code.
+ Enable Switches by setting SAMPLING_TOOL_ENABLED in Opcode.h.
+
+ * JavaScriptCore.exp: Export symbols for Shell.cpp.
+ * VM/Machine.cpp: Added sampling hooks.
+ * VM/Machine.h: Machine contains a pointer to a sampler, when sampling.
+ * VM/Opcode.cpp: Tool implementation.
+ * VM/Opcode.h: Tool declaration.
+ * kjs/Shell.cpp: Initialize the sampler, if enabled.
+ * kjs/nodes.cpp: Added sampling hooks.
+
+2008-07-23 Gabor Loki <loki@inf.u-szeged.hu>
+
+ Bug 20097: [Qt] 20% Sunspider slow-down
+
+ <https://bugs.webkit.org/show_bug.cgi?id=20097>
+
+ Reviewed by Simon Hausmann.
+
+ * kjs/jsc.pro: Added missing NDEBUG define for release builds.
+
+2008-07-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ JSClassRef is created context-free, but gets infatuated with the first context it sees.
+
+ The implicit API contract is that JSClassRef can be used with any context on any thread.
+ This no longer worked, because UStrings in the class were turned into per-context
+ identifiers, and the cached JSObject prototype was tied to JSGlobalData, too.
+
+ * API/JSClassRef.h: Made a separate struct for context-dependent parts of OpaqueJSClass.
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::OpaqueJSClass): Updated for renames and changed member variable order.
+ (OpaqueJSClass::~OpaqueJSClass): Assert that string members are not identifiers.
+ (clearReferenceToPrototype): Update for the new reference location.
+ (OpaqueJSClassContextData::OpaqueJSClassContextData): Make a deep copy of all strings.
+ (OpaqueJSClass::contextData): Added a function that finds the per-context part of
+ OpaqueJSClass in JSGlobalData, or creates it if not found.
+ (OpaqueJSClass::className): Always make a deep copy. Callers of this function do not have
+ a way to access JSGlobalData, so a per-context copy could not be made.
+ (OpaqueJSClass::staticValues): Updated for new data location.
+ (OpaqueJSClass::staticFunctions): Ditto.
+ (OpaqueJSClass::prototype): Changed to take an internal type for consistency.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::~JSGlobalData):
+ * kjs/JSGlobalData.h:
+ Keep a HashMap to access per-context JSClass data given a pointr to the shared part.
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::className):
+ (KJS::::getOwnPropertySlot):
+ (KJS::::put):
+ (KJS::::deleteProperty):
+ (KJS::::getPropertyNames):
+ (KJS::::staticValueGetter):
+ (KJS::::staticFunctionGetter):j
+ Use function accessors instead of accessing OpaqueJSClass members directly.
+
+ * API/JSContextRef.cpp: (JSGlobalContextCreate): Updated for the change in
+ OpaqueJSClass::prototype() argument type.
+
+ * API/JSObjectRef.cpp:
+ (JSObjectMake): Updated for the change in OpaqueJSClass::prototype() argument type.
+ (JSObjectMakeConstructor): Ditto.
+
+2008-07-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Build fix.
+
+ * kjs/ArgList.h: (KJS::ArgList::operator new): removed an extraneous "ArgList::" inside the
+ class definition.
+
+2008-07-22 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt and Sam Weinig.
+
+ Next step toward putting doubles in registers: Prepare the Register class
+ and its clients for registers that don't contain JSValue*s.
+
+ This means a few things:
+
+ 1. Register::jsValue() clients, including ArgList clients, must now supply
+ an ExecState* when accessing an entry in an ArgList, in case the entry
+ will need to create a JSValue* on the fly.
+
+ 2. Register clients that definitely don't want to create a JSValue* on
+ the fly now use different APIs: getJSValue() for clients that know
+ the register contains a JSValue*, and v() for clients who just want a
+ void*.
+
+ 3. I had to change some headers around in order to resolve dependency
+ problems created by using a Register in the ArgList header.
+
+ SunSpider reports no change.
+
+2008-07-22 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Prevent integer overflow when reallocating storage vector for arrays.
+
+ Sunspider reports 1.005x as fast (no change expected).
+
+ * kjs/JSArray.cpp:
+
+2008-07-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ <rdar://problem/6091287> Revamp the handling of CFBundleShortVersionString to be fixed at the major component of the version number.
+
+ * Configurations/Version.xcconfig:
+ * Info.plist:
+
+2008-07-21 Adam Roben <aroben@apple.com>
+
+ Add Vector::find
+
+ This is a convenience wrapper around std::find.
+
+ Reviewed by Anders Carlsson.
+
+ * wtf/Vector.h:
+
+2008-07-19 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Bug 20104: Exception in tables/mozilla_expected_failures/bugs/bug92868_1.html includes the equals operator in the quoted expression
+ <https://bugs.webkit.org/show_bug.cgi?id=20104>
+
+ To make this correct we make the dot and bracket assign nodes emit the information to indicate
+ the failure range is the dot/bracket accessor.
+
+ * kjs/grammar.y:
+
+2008-07-18 Steve Falkenburg <sfalken@apple.com>
+
+ Windows build fix.
+
+ * kjs/JSGlobalObjectFunctions.cpp:
+ (KJS::isStrWhiteSpace):
+
+2008-07-18 Steve Falkenburg <sfalken@apple.com>
+
+ Windows build fix.
+
+ * kjs/nodes.h:
+ (KJS::ThrowableExpressionData::ThrowableExpressionData):
+
+2008-07-18 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Bug 18774: SQUIRRELFISH: print meaningful error messages <https://bugs.webkit.org/show_bug.cgi?id=18774>
+ <rdar://problem/5769353> SQUIRRELFISH: JavaScript error messages are missing informative text
+
+ Add support for decent error messages in JavaScript. This patch achieves this by providing
+ ensuring the common errors and exceptions have messages that provide the text of expression
+ that trigger the exception. In addition it attaches a number of properties to the exception
+ object detailing where in the source the expression came from.
+
+ * JavaScriptCore.exp:
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::lineNumberForVPC):
+ (KJS::CodeBlock::expressionRangeForVPC):
+ Function to recover the expression range for an instruction
+ that triggered an exception.
+ * VM/CodeBlock.h:
+ (KJS::ExpressionRangeInfo::):
+ (KJS::CodeBlock::CodeBlock):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall):
+ (KJS::CodeGenerator::emitCallEval):
+ Emit call needed to be modified so to place the expression range info internally,
+ as the CodeGenerator emits the arguments nodes itself, rather than the various call
+ nodes.
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::emitExpressionInfo):
+ Record the expression range info.
+ * VM/ExceptionHelpers.cpp:
+ (KJS::createErrorMessage):
+ (KJS::createInvalidParamError):
+ (KJS::createUndefinedVariableError):
+ (KJS::createNotAConstructorError):
+ (KJS::createNotAFunctionError):
+ (KJS::createNotAnObjectErrorStub):
+ (KJS::createNotAnObjectError):
+ Rewrite all the code for the error messages so that they make use of the newly available
+ information.
+ * VM/ExceptionHelpers.h:
+ * VM/Machine.cpp:
+ (KJS::isNotObject): Now needs vPC and codeBlock
+ (KJS::Machine::throwException):
+ New logic to handle the NotAnObjectErrorStub and to handle the absurd "no default value" edge case
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::evaluate):
+ * kjs/Error.cpp:
+ (KJS::Error::create):
+ * kjs/Error.h:
+ * kjs/JSGlobalObjectFunctions.cpp:
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toObject):
+ (KJS::JSImmediate::prototype):
+ My changes to the JSNotAnObject constructor needed to be handled here.
+ * kjs/JSNotAnObject.h:
+ (KJS::JSNotAnObjectErrorStub::JSNotAnObjectErrorStub):
+ (KJS::JSNotAnObjectErrorStub::isNull):
+ (KJS::JSNotAnObjectErrorStub::isNotAnObjectErrorStub):
+ Added a JSNotAnObjectErrorStub class to ease the handling of toObject failure exceptions,
+ and potentially allow even more detailed error messages in future.
+ * kjs/JSObject.h:
+ * kjs/Parser.h:
+ (KJS::Parser::parse):
+ * kjs/SourceRange.h:
+ * kjs/grammar.y:
+ Large amounts of position propagation.
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::shift):
+ (KJS::Lexer::lex):
+ The lexer needed a few changes to be able to correctly track token character positions.
+ * kjs/lexer.h:
+ * kjs/nodes.cpp:
+ (KJS::ThrowableExpressionData::emitThrowError):
+ (KJS::StatementNode::StatementNode):
+ (KJS::ResolveNode::emitCode):
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::NewExprNode::emitCode):
+ (KJS::EvalFunctionCallNode::emitCode):
+ (KJS::FunctionCallValueNode::emitCode):
+ (KJS::FunctionCallResolveNode::emitCode):
+ (KJS::FunctionCallBracketNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+ (KJS::PostfixResolveNode::emitCode):
+ (KJS::PostfixBracketNode::emitCode):
+ (KJS::PostfixDotNode::emitCode):
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::DeleteBracketNode::emitCode):
+ (KJS::DeleteDotNode::emitCode):
+ (KJS::PrefixResolveNode::emitCode):
+ (KJS::PrefixBracketNode::emitCode):
+ (KJS::PrefixDotNode::emitCode):
+ (KJS::ThrowableBinaryOpNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ (KJS::ForInNode::ForInNode):
+ (KJS::ForInNode::emitCode):
+ (KJS::WithNode::emitCode):
+ (KJS::LabelNode::emitCode):
+ (KJS::ThrowNode::emitCode):
+ (KJS::ProgramNode::ProgramNode):
+ (KJS::ProgramNode::create):
+ (KJS::EvalNode::generateCode):
+ (KJS::FunctionBodyNode::create):
+ (KJS::FunctionBodyNode::generateCode):
+ (KJS::ProgramNode::generateCode):
+ All of these methods were handling the position information.
+ Constructors and create methods were modified to store the information.
+ All the emitCall implementations listed needed to be updated to actually
+ record the position information we have so carefully collected.
+ * kjs/nodes.h:
+ (KJS::ThrowableExpressionData::ThrowableExpressionData):
+ (KJS::ThrowableExpressionData::setExceptionSourceRange):
+ (KJS::ThrowableExpressionData::divot):
+ (KJS::ThrowableExpressionData::startOffset):
+ (KJS::ThrowableExpressionData::endOffset):
+ (KJS::ThrowableSubExpressionData::ThrowableSubExpressionData):
+ (KJS::ThrowableSubExpressionData::setSubexpressionInfo):
+ (KJS::ThrowablePrefixedSubExpressionData::ThrowablePrefixedSubExpressionData):
+ (KJS::ThrowablePrefixedSubExpressionData::setSubexpressionInfo):
+ ThrowableExpressionData is just a uniform mechanism for storing the position
+ information.
+ (KJS::ResolveNode::):
+ (KJS::PrePostResolveNode::):
+ (KJS::ThrowableBinaryOpNode::):
+ (KJS::WithNode::):
+
+2008-07-18 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Three renames:
+
+ "CallTypeNative" => "CallTypeHost"
+ "code" => "byteCode"
+ "generatedCode" => "generatedByteCode"
+
+2008-07-18 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Optimized <= for immediate number cases.
+
+ SunSpider reports no overall change, but a 10% speedup on access-nsieve.
+
+2008-07-18 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Sam Weinig.
+
+ Fix some casts added in a previous build fix to match the style used
+ throughout WebKit.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::initializeCallFrame):
+ * VM/Register.h:
+ (KJS::Register::Register):
+
+2008-07-18 Landry Breuil <landry@openbsd.org>
+
+ Bug 19975: [OpenBSD] Patches to enable build of WebKit
+
+ <https://bugs.webkit.org/show_bug.cgi?id=19975>
+
+ Reviewed by David Kilzer.
+
+ Support for OpenBSD, mostly threading and libm tweaks.
+
+ * kjs/collector.cpp: #include <pthread.h>
+ (KJS::currentThreadStackBase): use pthread_stackseg_np() to get stack base
+ * kjs/config.h: OpenBSD also provides <pthread_np.h>
+ * wtf/MathExtras.h: #include <sys/types.h> and <machine/ieee.h>
+ (isfinite), (signbit): as long as we don't have those functions provide fallback implementations
+ * wtf/Platform.h: Add support for PLATFORM(OPENBSD) and PLATFORM(SPARC64) macro
+
+2008-07-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Next step toward putting doubles in registers: Store constant pool
+ entries as registers, not JSValue*s.
+
+ SunSpider reports no change.
+
+2008-07-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by John Sullivan and Oliver Hunt.
+
+ A tiny bit of tidying in function call register allocation.
+
+ This patch saves one register when invoking a function expression and/or
+ a new expression that is stored in a temporary.
+
+ Since it's just one register, I can't make a testcase for it.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall): No need to ref the function we're calling
+ or its base. We'd like the call frame to overlap with them, if possible.
+ op_call will read the function and its base before writing the call frame,
+ so this is safe.
+
+ * kjs/nodes.cpp:
+ (KJS::NewExprNode::emitCode): No need to ref the function we're new-ing,
+ for the same reasons stated above.
+
+ (KJS::FunctionCallValueNode::emitCode): ditto
+
+2008-07-17 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * kjs/InternalFunction.cpp:
+
+2008-07-17 Sam Weinig <sam@webkit.org>
+
+ Roll out r35199 as it is causing failures on the PPC build.
+
+2008-07-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by David Kilzer.
+
+ Fixed https://bugs.webkit.org/show_bug.cgi?id=20067
+ Support function.name (Firefox extension)
+
+ Pretty straight-forward.
+
+2008-07-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed <rdar://problem/6081636> Functions calls use more temporary
+ registers than necessary
+
+ Holding a reference to the last statement result register caused each
+ successive statement to output its result to an even higher register.
+
+ Happily, statements don't actually need to return a result register
+ at all. I hope to make this clearer in a future cleanup patch,
+ but this change will fix the major bug for now.
+
+ * kjs/nodes.cpp:
+ (KJS::statementListEmitCode):
+
+2008-07-17 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Merge pre&post dot nodes to simplify the parse tree.
+ Sunspider results show 0.6% progression (no performance change expected).
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-07-17 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Merge pre&post resolve nodes to simplify the parse tree.
+ Sunspider results show no performance change.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-07-17 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Merge logical nodes to simplify the parse tree.
+ Sunspider results show 0.6% progression (no performance change expected).
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-07-17 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fix MinGW build (broken in r35198) and simplify getLocalTime().
+
+ * kjs/DateMath.cpp:
+ (KJS::getLocalTime):
+
+2008-07-17 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Merge pre&post bracket nodes to simplify the parse tree.
+ Sunspider results show no performance change.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-07-17 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fix the 32-bit gcc builds, conversion from "long int" to Register is
+ ambiguous. Explicitly choose the intptr_t constructor.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::initializeCallFrame):
+ * VM/Register.h:
+ (KJS::Register::Register):
+
+2008-07-16 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Geoff Garen.
+
+ Fix JavaScript in 64-bit by using a pointer-sized integer
+ type in the Register union. Also includes a rename of
+ the intType constant to IntType.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::initializeCallFrame):
+ * VM/Register.h:
+ (KJS::Register::):
+ (KJS::Register::Register):
+
+2008-07-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ First step toward putting doubles in registers: Turned Register into a
+ proper abstraction layer. It is no longer possible to cast a Register
+ to a JSValue*, or a Register& to a JSValue*&, or to access the union
+ inside a Register directly.
+
+ SunSpider reports no change.
+
+ In support of this change, I had to make the following mechanical changes
+ in a lot of places:
+
+ 1. Clients now use explicit accessors to read data out of Registers, and
+ implicit copy constructors to write data into registers.
+
+ So, assignment that used to look like
+
+ x.u.jsValue = y;
+
+ now looks like
+
+ x = y;
+
+ And access that used to look like
+
+ x = y.u.jsValue;
+
+ now looks like
+
+ x = y.jsValue();
+
+ 2. I made generic flow control specific in opcodes that made their flow
+ control generic by treating a Register& as a JSValue*&. This had the
+ added benefit of removing some exception checking branches from immediate
+ number code.
+
+ 3. I beefed up PropertySlot to support storing a Register* in a property
+ slot. For now, only JSVariableObject's symbolTableGet and symbolTablePut
+ use this functionality, but I expect more clients to use it in the future.
+
+ 4. I changed ArgList to be a buffer of Registers, not JSValue*'s, and I
+ changed ArgList iterator clients to iterate Registers, not JSValue*'s.
+
+2008-07-16 Ada Chan <adachan@apple.com>
+
+ Fixed build.
+
+ * kjs/JSGlobalObject.cpp:
+
+2008-07-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam and Geoff.
+
+ <rdar://problem/5958840> Navigating to another page while profiler is
+ attached results in slow JavaScript for all time.
+
+ - The UNLIKELY keeps this from being a sunspider performance regression.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject): Stop the profiler associated
+ with this exec state.
+
+2008-07-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Steve Falkenburg.
+
+ Replace adopting UString constructor in favor of explicit
+ static adopt method.
+
+ * API/JSStringRefCF.cpp:
+ (JSStringCreateWithCFString):
+ * kjs/StringConstructor.cpp:
+ (KJS::stringFromCharCode):
+ * kjs/StringPrototype.cpp:
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ * kjs/ustring.cpp:
+ (KJS::UString::adopt):
+ * kjs/ustring.h:
+ (KJS::UString::UString):
+ (KJS::UString::~UString):
+
+2008-07-16 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ http://trolltech.com/developer/task-tracker/index_html?method=entry&id=216179
+ Fix potential crash (on Qt for Windows port) when performing JavaScript date
+ conversion.
+
+ * kjs/DateMath.cpp:
+ (KJS::getLocalTime): For the Qt port, prefer to use Windows code, i.e.
+ localtime_s() instead of localtime() since the latter might crash (on Windows)
+ given a non-sensible, e.g. NaN, argument.
+
+2008-07-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Anders and Geoff.
+
+ https://bugs.webkit.org/show_bug.cgi?id=20023
+ Failed assertion in PropertyNameArray.cpp
+
+ This is already tested by testapi.
+
+ * API/JSObjectRef.cpp: (JSPropertyNameAccumulatorAddName): Add the string to identifier
+ table to appease PropertyNameArray.
+
+2008-07-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Dereference identifiers when deleting a hash table (fixes leaks with private JSGlobalData
+ objects).
+
+ * kjs/JSGlobalData.cpp: (KJS::JSGlobalData::~JSGlobalData):
+ * kjs/lookup.cpp: (KJS::HashTable::deleteTable):
+ * kjs/lookup.h:
+ * kjs/lexer.cpp: (KJS::Lexer::~Lexer)
+ HashTable cannot have a destructor, because check-for-global-initializers complains about
+ having a global constructor then.
+
+2008-07-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Check pthread_key_create return value.
+
+ This check was helpful when debugging a crash in run-webkit-tests --threaded that happened
+ because JSGlobalData objects were not deleted, and we were running out of pthread keys soon.
+ It also looks useful for production builds.
+
+ * wtf/ThreadSpecific.h: (WTF::::ThreadSpecific):
+
+2008-07-15 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ Rename pageGroupIdentifier to profileGroup to keep mention of a
+ pageGroup out of JavaScriptCore.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::setProfileGroup):
+ (KJS::JSGlobalObject::profileGroup):
+ * profiler/ProfileGenerator.cpp:
+ (KJS::ProfileGenerator::create):
+ (KJS::ProfileGenerator::ProfileGenerator):
+ * profiler/ProfileGenerator.h:
+ (KJS::ProfileGenerator::profileGroup):
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::startProfiling):
+ (KJS::dispatchFunctionToProfiles):
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+
+2008-07-14 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fix https://bugs.webkit.org/show_bug.cgi?id=20037
+ Bug 20037: GCC 4.2 build broken due to strict aliasing violation.
+
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::computeHash): Add a version of computeHash that takes a char* and explicit length.
+ * kjs/ustring.h:
+ * profiler/CallIdentifier.h:
+ (WTF::): Use new version of computeHash that takes a char* and explicit length to avoid unsafe aliasing.
+
+2008-07-14 David Hyatt <hyatt@apple.com>
+
+ Fix a crashing bug in ListHashSet's -- operator. Make sure that end() can be -- by special-casing the null
+ position.
+
+ Reviewed by Maciej
+
+ * wtf/ListHashSet.h:
+ (WTF::ListHashSetConstIterator::operator--):
+
+2008-07-14 David Hyatt <hyatt@apple.com>
+
+ Buidl fix. Make sure the second insertBefore method returns a value.
+
+ * wtf/ListHashSet.h:
+ (WTF::::insertBefore):
+
+2008-07-14 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/jsc/jsc.vcproj: Added include/pthreads to the
+ include path.
+
+2008-07-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Kevin McCullough.
+
+ Make JSGlobalData refcounted in preparation to adding a way to create contexts that share
+ global data.
+
+ * JavaScriptCore.exp:
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::create):
+ * kjs/JSGlobalData.h:
+ Made contructor private, and added a static create() method. Made the class inherit from
+ RefCounted.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::globalData):
+ JSGlobalData is now owned by JSGlobalObject (except for the shared one, and the common
+ WebCore one, which are never deleted).
+
+ * kjs/Shell.cpp: (main): Create JSGlobalData with create() method.
+
+2008-07-14 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the single-threaded build.
+
+ * kjs/JSLock.cpp: Removed undeclared registerThread() function.
+ * kjs/collector.cpp:
+ (KJS::Heap::registerThread): Added dummy implementation.
+
+2008-07-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Eliminate per-thread JavaScript global data instance support and make arbitrary
+ global data/global object combinations possible.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap): Store a JSGlobalData pointer instead of multiple pointers to its members.
+ This allows for going from any JS object to its associated global data, currently used in
+ JSGlobalObject constructor to initialize its JSGlobalData pointer.
+ (KJS::Heap::registerThread): Changed thread registration data to be per-heap. Previously,
+ only the shared heap could be used from multiple threads, so it was the only one that needed
+ thread registration, but now this can happen to any heap.
+ (KJS::Heap::unregisterThread): Ditto.
+ (KJS::Heap::markStackObjectsConservatively): Adapt for the above changes.
+ (KJS::Heap::setGCProtectNeedsLocking): Ditto.
+ (KJS::Heap::protect): Ditto.
+ (KJS::Heap::unprotect): Ditto.
+ (KJS::Heap::collect): Ditto.
+ (KJS::Heap::globalObjectCount): Use global object list associated with the current heap,
+ not the late per-thread one.
+ (KJS::Heap::protectedGlobalObjectCount): Ditto.
+
+ * kjs/collector.h:
+ (KJS::Heap::ThreadRegistrar): Added a helper object that unregisters a thread when it is
+ destroyed.
+
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::JSLock):
+ * kjs/JSLock.h:
+ (KJS::JSLock::JSLock):
+ Don't use JSLock to implicitly register threads. I've added registerThread() calls to most
+ places that use JSLock - we cannot guarantee absolute safety unless we always mark all
+ threads in the process, but these implicit registration calls should cover reasonable usage
+ scenarios, I hope.
+
+ * API/JSBase.cpp:
+ (JSEvaluateScript): Explicitly register the current thread.
+ (JSCheckScriptSyntax): Explicitly register the current thread.
+ (JSGarbageCollect): Changed to use the passed in context. Unfortunately, this creates a race
+ condition for clients that pass an already released context to JSGarbageCollect - but it is
+ unlikely to create real life problems.
+ To maintain compatibility, the shared heap is collected if NULL is passed.
+
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreate): Use a new syntax for JSGlobalObject allocation.
+ (JSGlobalContextRetain): Register the thread.
+ (JSContextGetGlobalObject): Register the thread.
+
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeConstructor):
+ (JSObjectMakeFunction):
+ (JSObjectHasProperty):
+ (JSObjectGetProperty):
+ (JSObjectSetProperty):
+ (JSObjectGetPropertyAtIndex):
+ (JSObjectSetPropertyAtIndex):
+ (JSObjectDeleteProperty):
+ (JSObjectCallAsFunction):
+ (JSObjectCallAsConstructor):
+ (JSObjectCopyPropertyNames):
+ (JSPropertyNameAccumulatorAddName):
+ * API/JSValueRef.cpp:
+ (JSValueIsEqual):
+ (JSValueIsInstanceOfConstructor):
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ (JSValueToNumber):
+ (JSValueToStringCopy):
+ (JSValueToObject):
+ (JSValueProtect):
+ (JSValueUnprotect):
+ Register the thread.
+
+ * API/JSStringRef.cpp: (JSStringRelease): Changed a comment to not mention per-thread contexts.
+
+ * API/JSStringRefCF.cpp: Removed an unnecessary include of JSLock.h.
+
+ * JavaScriptCore.exp: Export JSGlobalData constructor/destructor, now that anyone can have
+ their own instances. Adapt to other changes, too.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Made ThreadSpecific.h private, as it is now
+ included by collector.h and is thus needed in other projects.
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreadingOnce): Don't initialize per-thread
+ global data, as it no longer exists.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::~JSGlobalData):
+ * kjs/JSGlobalData.h:
+ Removed support for per-thread instance. Made constructor and destructor public.
+
+ * kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::init): Get to now arbitrary JSGlobalData
+ via the heap.
+ (KJS::JSGlobalObject::operator new): Changed ot take JSGlobalDatra pointer.
+ * kjs/JSGlobalObject.h:
+
+ * kjs/Shell.cpp:
+ (main):
+ (jscmain):
+ Changed to maintain a custom JSGlobalData pointer instead of a per-thread one.
+
+2008-07-13 Ada Chan <adachan@apple.com>
+
+ Windows build fix: Add wtf/RefCountedLeakCounter to the project.
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+
+2008-07-12 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Gtk, Qt and Wx build fix: Add wtf/RefCountedLeakCounter in the
+ build scripts
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCoreSources.bkl:
+
+2008-07-11 Stephanie Lewis <slewis@apple.com>
+
+ Reviewed by Darin Adler and Oliver Hunt.
+
+ Refactor RefCounting Leak counting code into a common class.
+
+ In order to export the symbols I needed to put the debug defines inside the function names
+
+ Before we had a separate channel for each Logging each Leak type. Since the leak channels were only used in one location, and only at quit for simplicity I combined them all into one leak channel.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj: add new class
+ * kjs/nodes.cpp: remove old leak counting code
+ * wtf/RefCountedLeakCounter.cpp: Added. create a common leak counting class
+ * wtf/RefCountedLeakCounter.h: Added.
+
+2008-07-11 David Hyatt <hyatt@apple.com>
+
+ Add an insertBefore method to ListHashSet to allow for insertions in the middle of the list (rather than just
+ at the end).
+
+ Reviewed by Anders
+
+ * wtf/ListHashSet.h:
+ (WTF::::insertBefore):
+ (WTF::::insertNodeBefore):
+
+2008-07-11 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ Move call function to CallData.cpp and construct to ConstructData.cpp.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/CallData.cpp: Copied from kjs/JSValue.cpp.
+ * kjs/ConstructData.cpp: Copied from kjs/JSValue.cpp.
+ * kjs/JSValue.cpp:
+
+2008-07-10 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Define WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST when building WebKit to ensure that no symbols end up with the weak_import attribute.
+
+ * Configurations/Base.xcconfig:
+
+2008-07-10 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fix the Tiger build by omitting annotations from methods declared in categories when using old versions of GCC.
+
+ * API/WebKitAvailability.h:
+
+2008-07-10 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ -Minor cleanup. Renamed callTree() to head() and no longer use m_head
+ directly but instead keep it private and access via a method().
+
+ * profiler/HeavyProfile.cpp:
+ (KJS::HeavyProfile::HeavyProfile):
+ (KJS::HeavyProfile::generateHeavyStructure):
+ (KJS::HeavyProfile::addNode):
+ * profiler/Profile.h:
+ (KJS::Profile::head):
+ * profiler/ProfileGenerator.cpp:
+ (KJS::ProfileGenerator::ProfileGenerator):
+
+2008-07-10 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Eliminate CollectorHeapIntrospector.
+
+ CollectorHeapIntrospector was added primarily in the hopes to improve leaks tool output,
+ a result that it didn't deliver. Also, it helped by labeling JSC heap regions as reported by
+ vmmap tool, but at the same time, it made them mislabeled as malloc'd ones - the correct
+ way to label mapped regions is to use a VM tag.
+
+ So, it makes more sense to remove it completely than to make it work with multiple heaps.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/AllInOneFile.cpp:
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading):
+ * kjs/collector.cpp:
+ * kjs/collector.h:
+ * kjs/CollectorHeapIntrospector.cpp: Removed.
+ * kjs/CollectorHeapIntrospector.h: Removed.
+
+2008-07-09 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5951532> JSProfiler: Implement heavy (or bottom-up)
+ view (19228)
+ - Implemented the time and call count portionof heavy. Now all that we
+ need is some UI.
+
+ * profiler/CallIdentifier.h: Removed an unused constructor.
+ * profiler/HeavyProfile.cpp:
+ (KJS::HeavyProfile::HeavyProfile): Set the initial time of the head
+ node so that percentages work correctly.
+ (KJS::HeavyProfile::mergeProfiles): Sum the times and call count of
+ nodes being merged.
+ * profiler/ProfileNode.cpp: Set the intital values of time and call
+ count when copying ProfileNodes.
+ (KJS::ProfileNode::ProfileNode):
+
+2008-07-10 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Gtk build fix.
+
+ * GNUmakefile.am: Add HeavyProfile.cpp
+
+2008-07-09 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Don't warn about deprecated functions in production builds.
+
+ * Configurations/Base.xcconfig:
+ * Configurations/DebugRelease.xcconfig:
+
+2008-07-09 Darin Adler <darin@apple.com>
+
+ * JavaScriptCore.pri: Fix Qt build by adding HeavyProfile.cpp.
+
+2008-07-09 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx biuld fix. Add HeavyProfile.cpp to build files.
+
+ * JavaScriptCoreSources.bkl:
+
+2008-07-09 Kevin McCullough <kmccullough@apple.com>
+
+ - Windows build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-07-09 Kevin McCullough <kmccullough@apple.com>
+
+ - Build fix.
+
+ * profiler/HeavyProfile.cpp:
+ (KJS::HeavyProfile::mergeProfiles):
+
+2008-07-09 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff and Adam.
+
+ <rdar://problem/5951532> JSProfiler: Implement Bottom-Up view (19228)
+ - This is the plumbing for bottom-up, but does not include calculating
+ time, mostly because I'm still undclear about what the end result should
+ look like.
+ - This, obviously, does not include the UI to expose this in the
+ inspector yet.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * profiler/CallIdentifier.h:
+ (KJS::CallIdentifier::CallIdentifier):
+ (WTF::): Added HashTraits for CallIdentifiers to be used by a HashMap.
+ * profiler/HeavyProfile.cpp: Added.
+ (KJS::HeavyProfile::HeavyProfile):
+ (KJS::HeavyProfile::generateHeavyStructure):
+ (KJS::HeavyProfile::addNode):
+ (KJS::HeavyProfile::mergeProfiles):
+ (KJS::HeavyProfile::addAncestorsAsChildren):
+ * profiler/HeavyProfile.h: Added.
+ (KJS::HeavyProfile::create):
+ (KJS::HeavyProfile::heavyProfile):
+ (KJS::HeavyProfile::treeProfile):
+ * profiler/Profile.cpp: Removed old commented out includes.
+ * profiler/Profile.h: The m_head is needed by the HeavyProfile so it
+ is now protected as opposed to private.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode): Created a constructor to copy
+ ProfileNodes.
+ (KJS::ProfileNode::findChild): Added a null check to make HeavyProfile
+ children finding easier and avoid a potential crasher.
+ * profiler/ProfileNode.h: Mostly moved things around but also added some
+ functionality needed by HeavyProfile.
+ (KJS::ProfileNode::create):
+ (KJS::ProfileNode::functionName):
+ (KJS::ProfileNode::url):
+ (KJS::ProfileNode::lineNumber):
+ (KJS::ProfileNode::head):
+ (KJS::ProfileNode::setHead):
+ (KJS::ProfileNode::setNextSibling):
+ (KJS::ProfileNode::actualTotalTime):
+ (KJS::ProfileNode::actualSelfTime):
+ * profiler/TreeProfile.cpp: Implemented the ability to get a
+ HeavyProfile.
+ (KJS::TreeProfile::heavyProfile):
+ * profiler/TreeProfile.h:
+
+2008-07-08 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Added support for checking if an object has custom properties in its
+ property map. WebCore uses this to optimize marking DOM wrappers.
+
+2008-07-08 Simon Hausmann <hausmann@webkit.org>
+
+ Prospective Gtk/Wx build fixes, add ProfileGenerator.cpp to the build.
+
+ * GNUmakefile.am:
+ * JavaScriptCoreSources.bkl:
+
+2008-07-08 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Qt build, add ProfileGenerator.cpp to the build.
+
+ * JavaScriptCore.pri:
+
+2008-07-07 David Kilzer <ddkilzer@apple.com>
+
+ releaseFastMallocFreeMemory() should always be defined
+
+ Reviewed by Darin.
+
+ * JavaScriptCore.exp: Changed to export C++ binding for
+ WTF::releaseFastMallocFreeMemory() instead of C binding for
+ releaseFastMallocFreeMemory().
+ * wtf/FastMalloc.cpp: Moved definitions of
+ releaseFastMallocFreeMemory() to be in the WTF namespace
+ regardless whether FORCE_SYSTEM_MALLOC is defined.
+ * wtf/FastMalloc.h: Moved releaseFastMallocFreeMemory() from
+ extern "C" binding to WTF::releaseFastMallocFreeMemory().
+
+2008-07-07 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoff.
+
+ Bug 19926: URL causes crash within a minute
+ <https://bugs.webkit.org/show_bug.cgi?id=19926>
+
+ Add a check that lastGlobalObject is non-null in Machine::execute()
+ before copying its globals to the current register file.
+
+ In theory, it is possible to make a test case for this, but it will
+ take a while to get it right.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+
+2008-07-07 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Adele.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Fix a typo in a comment.
+
+2008-07-07 Steve Falkenburg <sfalken@apple.com>
+
+ Build fixes.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/testapi/testapi.vcproj:
+
+2008-07-07 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ When the profiler is running it gathers information and creates a
+ Profile. After it finishes the Profile can be sorted and have other
+ data refinements run over it. Both of these were done in the same class
+ before. Now I split the gathering operations into a new class called
+ ProfileGenerator.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * profiler/Profile.cpp: Removed code related to the gather stage of a
+ Profile's creation.
+ (KJS::Profile::create):
+ (KJS::Profile::Profile):
+ * profiler/Profile.h: Ditto.
+ (KJS::Profile::title):
+ (KJS::Profile::callTree):
+ (KJS::Profile::setHead):
+ * profiler/ProfileGenerator.cpp: Added. This is the class that will
+ handle the stage of creating a Profile. Once the Profile is finished
+ being created, this class goes away.
+ (KJS::ProfileGenerator::create):
+ (KJS::ProfileGenerator::ProfileGenerator):
+ (KJS::ProfileGenerator::title):
+ (KJS::ProfileGenerator::willExecute):
+ (KJS::ProfileGenerator::didExecute):
+ (KJS::ProfileGenerator::stopProfiling):
+ (KJS::ProfileGenerator::didFinishAllExecution):
+ (KJS::ProfileGenerator::removeProfileStart):
+ (KJS::ProfileGenerator::removeProfileEnd):
+ * profiler/ProfileGenerator.h: Added.
+ (KJS::ProfileGenerator::profile):
+ (KJS::ProfileGenerator::originatingGlobalExec):
+ (KJS::ProfileGenerator::pageGroupIdentifier):
+ (KJS::ProfileGenerator::client):
+ (KJS::ProfileGenerator::stoppedProfiling):
+ * profiler/Profiler.cpp: Now operates with the ProfileGenerator instead
+ of the Profile.
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::stopProfiling):
+ (KJS::Profiler::didFinishAllExecution): It is here that the Profile is
+ handed off to its client and the Profile Generator is no longer needed.
+ (KJS::dispatchFunctionToProfiles):
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+ * profiler/Profiler.h: Cleaned up the includes and subsequently the
+ forward declarations. Also use the new ProfileGenerator.
+ (KJS::ProfilerClient::~ProfilerClient):
+ (KJS::Profiler::currentProfiles):
+ * profiler/TreeProfile.cpp: Use Profile's new interface.
+ (KJS::TreeProfile::create):
+ (KJS::TreeProfile::TreeProfile):
+ * profiler/TreeProfile.h:
+
+2008-07-07 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Cameron Zwarich.
+
+ Third step in broad cleanup effort.
+
+ [ File list elided ]
+
+2008-07-06 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Cameron Zwarich.
+
+ Second step in broad cleanup effort.
+
+ [ File list elided ]
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Cameron Zwarich.
+
+ First step in broad cleanup effort.
+
+ [ File list elided ]
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Cameron Zwarich.
+
+ Rename list.h/cpp to ArgList.h/cpp.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.h:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ArgList.cpp: Copied from JavaScriptCore/kjs/list.cpp.
+ * kjs/ArgList.h: Copied from JavaScriptCore/kjs/list.h.
+ * kjs/IndexToNameMap.cpp:
+ * kjs/JSGlobalData.cpp:
+ * kjs/JSGlobalData.h:
+ * kjs/JSObject.h:
+ * kjs/collector.cpp:
+ * kjs/list.cpp: Removed.
+ * kjs/list.h: Removed.
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne builds again.
+
+ * kjs/BooleanPrototype.cpp:
+ * kjs/ErrorPrototype.cpp:
+ * kjs/FunctionPrototype.cpp:
+ * kjs/NumberPrototype.cpp:
+ * kjs/ObjectPrototype.cpp:
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Fix build on case-sensitive build systems.
+
+ * kjs/IndexToNameMap.cpp:
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Fix build.
+
+ * kjs/Arguments.cpp:
+ * kjs/BooleanPrototype.cpp:
+ * kjs/DateConstructor.cpp:
+ * kjs/ErrorPrototype.cpp:
+ * kjs/FunctionPrototype.cpp:
+ * kjs/NumberPrototype.cpp:
+ * kjs/ObjectPrototype.cpp:
+ * kjs/RegExpPrototype.cpp:
+ * kjs/StringConstructor.cpp:
+ * kjs/lookup.cpp:
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne build.
+
+ * kjs/JSGlobalObject.cpp:
+
+2008-07-05 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Cameron Zwarich.
+
+ Split Arguments, IndexToNameMap, PrototypeFunction, GlobalEvalFunction and
+ the functions on the global object out of JSFunction.h/cpp.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/Arguments.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
+ * kjs/Arguments.h: Copied from JavaScriptCore/kjs/JSFunction.h.
+ * kjs/GlobalEvalFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
+ * kjs/GlobalEvalFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h.
+ * kjs/IndexToNameMap.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
+ * kjs/IndexToNameMap.h: Copied from JavaScriptCore/kjs/JSFunction.h.
+ * kjs/JSActivation.cpp:
+ * kjs/JSFunction.cpp:
+ * kjs/JSFunction.h:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSGlobalObjectFunctions.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
+ * kjs/JSGlobalObjectFunctions.h: Copied from JavaScriptCore/kjs/JSFunction.h.
+ The functions on the global object should be in JSGlobalObject.cpp, but putting them there
+ was a 0.5% regression.
+
+ * kjs/PrototypeFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp.
+ * kjs/PrototypeFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h.
+ * kjs/Shell.cpp:
+ * kjs/lexer.cpp:
+ * kjs/ustring.cpp:
+
+2008-07-04 Sam Weinig <sam@webkit.org>
+
+ Really fix the mac build.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-04 Sam Weinig <sam@webkit.org>
+
+ Fix mac build.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-04 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne builds.
+
+ * kjs/Error.cpp:
+ * kjs/GetterSetter.cpp:
+ * kjs/JSImmediate.cpp:
+ * kjs/operations.cpp:
+
+2008-07-04 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Dan Bernstein.
+
+ Split Error and GetterSetter out of JSObject.h.
+
+ * API/JSCallbackObjectFunctions.h:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ClassInfo.h: Copied from JavaScriptCore/kjs/JSObject.h.
+ * kjs/Error.cpp: Copied from JavaScriptCore/kjs/JSObject.cpp.
+ * kjs/Error.h: Copied from JavaScriptCore/kjs/JSObject.h.
+ * kjs/GetterSetter.cpp:
+ * kjs/GetterSetter.h: Copied from JavaScriptCore/kjs/JSObject.h.
+ * kjs/JSObject.cpp:
+ * kjs/JSObject.h:
+ * kjs/nodes.h:
+
+2008-07-04 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Wx build, added TreeProfile.cpp to the build.
+
+ * JavaScriptCoreSources.bkl:
+
+2008-07-03 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix output path of recently-added script phase to reference the correct file.
+ This prevents Xcode from running the script phase unnecessarily, which caused
+ the generated header to be recreated and lead to AllInOneFile.cpp rebuilding.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-03 Mark Rowe <mrowe@apple.com>
+
+ Follow-up to the 64-bit build fix. Use intptr_t rather than ssize_t as
+ the latter is non-standard and does not exist on Windows.
+
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::lockCount):
+ (KJS::JSLock::lock):
+ (KJS::JSLock::unlock):
+ (KJS::JSLock::DropAllLocks::DropAllLocks):
+ * kjs/JSLock.h:
+
+2008-07-02 Mark Rowe <mrowe@apple.com>
+
+ Fix the 64-bit build. pthread_getspecific works with pointer-sized values,
+ so use ssize_t rather than int to track the lock count to avoid warnings about
+ truncating the result of pthread_getspecific.
+
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::lockCount):
+ (KJS::JSLock::lock):
+ (KJS::JSLock::unlock):
+ (KJS::JSLock::DropAllLocks::DropAllLocks):
+ * kjs/JSLock.h:
+
+2008-07-03 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Removed checking for the array get/put fast case from the array code.
+ Callers who want the fast case should call getIndex and/or setIndex
+ instead. (get_by_val and put_by_val already do this.)
+
+ SunSpider reports no change overall, but a 1.4% speedup on fannkuch and
+ a 3.6% speedup on nsieve.
+
+2008-07-03 Dan Bernstein <mitz@apple.com>
+
+ - Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Added TreeProfile.{h,cpp}.
+
+2008-07-03 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Anders Carlsson.
+
+ - Windows build fix
+
+ * VM/Machine.cpp:
+ (KJS::Machine::Machine):
+
+2008-07-03 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Fix the non-threaded build.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::threadInstanceInternal):
+
+2008-07-03 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Qt build, added TreeProfile to the build.
+
+ * JavaScriptCore.pri:
+
+2008-07-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Don't create unnecessary JSGlobalData instances.
+
+ * kjs/JSGlobalData.h:
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::threadInstanceExists):
+ (KJS::JSGlobalData::sharedInstanceExists):
+ (KJS::JSGlobalData::threadInstance):
+ (KJS::JSGlobalData::sharedInstance):
+ (KJS::JSGlobalData::threadInstanceInternal):
+ (KJS::JSGlobalData::sharedInstanceInternal):
+ Added methods to query instance existence.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreadingOnce):
+ Initialize thread instance static in a new way.
+
+ * API/JSBase.cpp:
+ (JSGarbageCollect):
+ * kjs/collector.cpp:
+ (KJS::Heap::collect):
+ Check for instance existence before accessing it.
+
+2008-07-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Cameron Zwarich.
+
+ Fixed https://bugs.webkit.org/show_bug.cgi?id=19862
+ REGRESSION (r34907): Gmail crashes in JavaScriptCore code while editing drafts
+
+ I was never able to reproduce this issue, but Cameron could, and he says
+ that this patch fixes it.
+
+ The crash seems tied to a timer or event handler callback. In such a case,
+ the sole reference to the global object may be in the current call frame,
+ so we can't depend on the global object to mark the call frame area in
+ the register file.
+
+ The new GC marking rule is: the global object is not responsible for
+ marking the whole register file -- it's just responsible for the globals
+ section it's tied to. The heap is responsible for marking the call frame area.
+
+2008-07-02 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Add the ability to trace JavaScriptCore garabge collections using dtrace.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Generate the dtrace probe header
+ file when building on a new enough version of Mac OS X.
+ * JavaScriptCorePrefix.h: Add our standard Mac OS X version detection macros.
+ * kjs/Tracing.d: Declare three dtrace probes.
+ * kjs/Tracing.h: Include the generated dtrace macros if dtrace is available,
+ otherwise provide versions that do nothing.
+ * kjs/collector.cpp:
+ (KJS::Heap::collect): Fire dtrace probes when starting a collection, after the
+ mark phase has completed, and when the collection is complete.
+ * wtf/Platform.h: Define HAVE_DTRACE when building on a new enough version of Mac OS X.
+
+2008-07-02 Geoffrey Garen <ggaren@apple.com>
+
+ Rubber stamped by Oliver Hunt.
+
+ Reduced the max register file size from 8MB to 2MB.
+
+ We still allow about 20,000 levels of recursion.
+
+2008-07-02 Alp Toker <alp@nuanti.com>
+
+ Build fix for r34960. Add TreeProfile.cpp to build.
+
+ * GNUmakefile.am:
+
+2008-07-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Optimized a[n] get for cases when a is an array or a string. When a is
+ an array, we optimize both get and put. When a is a string, we only
+ optimize get, since you can't put to a string.
+
+ SunSpider says 3.4% faster.
+
+2008-07-02 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ -Small cleanup in preparation for implementing Bottom-up.
+
+ * profiler/CallIdentifier.h: Rename debug function to make it clear of
+ its output and intention to be debug only.
+ (KJS::CallIdentifier::operator const char* ): Implement in terms of
+ c_str.
+ (KJS::CallIdentifier::c_str):
+ * profiler/ProfileNode.cpp: Impelment findChild() which will be needed
+ by the bottom-up implementation.
+ (KJS::ProfileNode::findChild):
+ * profiler/ProfileNode.h: Added comments to make the collections of
+ functions more clear.
+ (KJS::ProfileNode::operator==):
+ (KJS::ProfileNode::c_str):
+
+2008-07-02 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 19776: Number.toExponential() is incorrect for numbers between 0.1 and 1
+ <https://bugs.webkit.org/show_bug.cgi?id=19776>
+
+ Perform the sign check for the exponent on the actual exponent value,
+ which is 1 less than the value of decimalPoint, instead of on the value
+ of decimalPoint itself.
+
+ * kjs/NumberPrototype.cpp:
+ (KJS::exponentialPartToString):
+
+2008-07-02 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5951532> JSProfiler: Implement Bottom-Up view (19228)
+ - Subclass TreeProfile as I prepare for a HeavyProfile to be comming
+ later.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * profiler/Profile.cpp: By default we create a TreeProfile.
+ (KJS::Profile::create):
+ * profiler/Profile.h: Changes to the Profile class to make it amenable
+ to be inherited from.
+ (KJS::Profile::~Profile):
+ * profiler/TreeProfile.cpp: Added.
+ (KJS::TreeProfile::create):
+ (KJS::TreeProfile::TreeProfile):
+ (KJS::TreeProfile::heavyProfile):
+ * profiler/TreeProfile.h: Added.
+ (KJS::TreeProfile::treeProfile):
+
+2008-07-02 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Dan.
+
+ Broke CallIdentifier out into its own file. I did this because it's
+ going to grow a lot soon and I wanted this to be a separate patch.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * profiler/CallIdentifier.h: Added.
+ (KJS::CallIdentifier::CallIdentifier):
+ (KJS::CallIdentifier::operator==):
+ (KJS::CallIdentifier::operator!=):
+ (KJS::CallIdentifier::operator const char* ):
+ (KJS::CallIdentifier::toString):
+ * profiler/ProfileNode.h:
+
+2008-07-02 Simon Hausmann <hausmann@webkit.org>
+
+ Build fix. Implemented missing functions for single-threaded build.
+
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::JSLock):
+ (KJS::JSLock::lock):
+ (KJS::JSLock::unlock):
+ (KJS::JSLock::DropAllLocks::DropAllLocks):
+
+2008-07-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Another non-AllInOne build fix.
+
+ * kjs/JSGlobalObject.cpp: Include JSLock.h here, too.
+
+2008-07-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Non-AllInOne build fix.
+
+ * kjs/interpreter.cpp: Include JSLock.h.
+
+2008-06-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Disable JSLock for per-thread contexts.
+
+ No change on SunSpider.
+
+ * kjs/JSGlobalData.h:
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::sharedInstance):
+ Added isSharedInstance as a better way to tell whether the instance is shared (legacy).
+
+ * kjs/JSLock.cpp:
+ (KJS::createJSLockCount):
+ (KJS::JSLock::lockCount):
+ (KJS::setLockCount):
+ (KJS::JSLock::JSLock):
+ (KJS::JSLock::lock):
+ (KJS::JSLock::unlock):
+ (KJS::JSLock::currentThreadIsHoldingLock):
+ (KJS::JSLock::DropAllLocks::DropAllLocks):
+ (KJS::JSLock::DropAllLocks::~DropAllLocks):
+ * kjs/JSLock.h:
+ (KJS::JSLock::JSLock):
+ (KJS::JSLock::~JSLock):
+ Made JSLock and JSLock::DropAllLocks constructors take a parameter to decide whether to
+ actually lock a mutex, or only to increment recursion count. We cannot turn it into no-op
+ if we want to keep existing assertions working.
+ Made recursion count per-thread, now that locks may not lock.
+
+ * API/JSBase.cpp:
+ (JSEvaluateScript): Take JSLock after casting JSContextRef to ExecState* (which doesn't need
+ locking in any case), so that a decision whether to actually lock can be made.
+ (JSCheckScriptSyntax): Ditto.
+ (JSGarbageCollect): Only lock while collecting the shared heap, not the per-thread one.
+
+ * API/JSObjectRef.cpp:
+ (JSClassCreate): Don't lock, as there is no reason to.
+ (JSClassRetain): Ditto.
+ (JSClassRelease): Ditto.
+ (JSPropertyNameArrayRetain): Ditto.
+ (JSPropertyNameArrayRelease): Only lock while deleting the array, as that may touch
+ identifier table.
+ (JSPropertyNameAccumulatorAddName): Adding a string also involves an identifier table
+ lookup, and possibly modification.
+
+ * API/JSStringRef.cpp:
+ (JSStringCreateWithCharacters):
+ (JSStringCreateWithUTF8CString):
+ (JSStringRetain):
+ (JSStringRelease):
+ (JSStringGetUTF8CString):
+ (JSStringIsEqual):
+ * API/JSStringRefCF.cpp:
+ (JSStringCreateWithCFString):
+ JSStringRef operations other than releasing do not need locking.
+
+ * VM/Machine.cpp: Don't include unused JSLock.h.
+
+ * kjs/CollectorHeapIntrospector.cpp: (KJS::CollectorHeapIntrospector::statistics):
+ Don't take the lock for real, as heap introspection pauses the process anyway. It seems that
+ the existing code could cause deadlocks.
+
+ * kjs/Shell.cpp:
+ (functionGC):
+ (main):
+ (jscmain):
+ The test tool uses a per-thread context, so no real locking is required.
+
+ * kjs/collector.h:
+ (KJS::Heap::setGCProtectNeedsLocking): Optionally protect m_protectedValues access with a
+ per-heap mutex. This is only needed for WebCore Database code, which violates the "no data
+ migration between threads" by using ProtectedPtr on a background thread.
+ (KJS::Heap::isShared): Keep a shared flag here, as well.
+
+ * kjs/protect.h:
+ (KJS::::ProtectedPtr):
+ (KJS::::~ProtectedPtr):
+ (KJS::::operator):
+ (KJS::operator==):
+ (KJS::operator!=):
+ ProtectedPtr is ony used from WebCore, so it doesn't need to take JSLock. An assertion in
+ Heap::protect/unprotect guards agains possible future unlocked uses of ProtectedPtr in JSC.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap): Initialize m_isShared.
+ (KJS::Heap::~Heap): No need to lock for real during destruction, but must keep assertions
+ in sweep() working.
+ (KJS::destroyRegisteredThread): Registered thread list is only accessed for shared heap,
+ so locking is always needed here.
+ (KJS::Heap::registerThread): Ditto.
+ (KJS::Heap::markStackObjectsConservatively): Use m_isShared instead of comparing to a shared
+ instance for a small speedup.
+ (KJS::Heap::setGCProtectNeedsLocking): Create m_protectedValuesMutex. There is currently no
+ way to undo this - and ideally, Database code will be fixed to lo longer require this quirk.
+ (KJS::Heap::protect): Take m_protectedValuesMutex (if it exists) while accessing
+ m_protectedValues.
+ (KJS::Heap::unprotect): Ditto.
+ (KJS::Heap::markProtectedObjects): Ditto.
+ (KJS::Heap::protectedGlobalObjectCount): Ditto.
+ (KJS::Heap::protectedObjectCount): Ditto.
+ (KJS::Heap::protectedObjectTypeCounts): Ditto.
+
+ * kjs/ustring.cpp:
+ * kjs/ustring.h:
+ Don't include JSLock.h, which is no longer used here. As a result, an explicit include had
+ to be added to many files in JavaScriptGlue, WebCore and WebKit.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ * API/JSCallbackConstructor.cpp:
+ (KJS::constructJSCallback):
+ * API/JSCallbackFunction.cpp:
+ (KJS::JSCallbackFunction::call):
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::init):
+ (KJS::::getOwnPropertySlot):
+ (KJS::::put):
+ (KJS::::deleteProperty):
+ (KJS::::construct):
+ (KJS::::hasInstance):
+ (KJS::::call):
+ (KJS::::getPropertyNames):
+ (KJS::::toNumber):
+ (KJS::::toString):
+ (KJS::::staticValueGetter):
+ (KJS::::callbackGetter):
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreate):
+ (JSGlobalContextRetain):
+ (JSGlobalContextRelease):
+ * API/JSValueRef.cpp:
+ (JSValueIsEqual):
+ (JSValueIsStrictEqual):
+ (JSValueIsInstanceOfConstructor):
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ (JSValueToNumber):
+ (JSValueToStringCopy):
+ (JSValueToObject):
+ (JSValueProtect):
+ (JSValueUnprotect):
+ * JavaScriptCore.exp:
+ * kjs/PropertyNameArray.h:
+ (KJS::PropertyNameArray::globalData):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::checkSyntax):
+ (KJS::Interpreter::evaluate):
+ Pass a parameter to JSLock/JSLock::DropAllLocks to decide whether the lock needs to be taken.
+
+2008-07-01 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19834
+ Failed assertion in JavaScriptCore/VM/SegmentedVector.h:82
+
+ Creating a global object with a custom prototype resets it twice (wasteful!).
+ So, addStaticGlobals() was called twice, but JSGlobalObject::reset() didn't reset
+ the register array.
+
+ * kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::reset): Call setRegisterArray(0, 0).
+
+ * kjs/JSVariableObject.h: Changed registerArray to OwnArrayPtr. Also, added private copy
+ constructor and operator= to ensure that no one attempts to copy this object (for whatever
+ reason, I couldn't make Noncopyable work).
+
+ * kjs/JSGlobalObject.h: (KJS::JSGlobalObject::addStaticGlobals): Allocate registerArray
+ with new[].
+
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::copyRegisterArray): Allocate registerArray with new[].
+ (KJS::JSVariableObject::setRegisterArray): Avoid hitting an assertion in OwnArrayPtr when
+ "changing" the value from 0 to 0.
+
+2008-07-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed and/or reordered exception checks in array-style a[n] access.
+
+ SunSpider says 1.4% faster.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): No need to check for exceptions before
+ calling toString, toNumber and/or get. If the call ends up being observable
+ through toString, valueOf, or a getter, we short-circuit it there, instead.
+ In the op_del_by_val case, I removed the incorrect comment without actually
+ removing the code, since I didn't want to tempt the GCC fates!
+
+ * kjs/JSObject.cpp:
+ (KJS::callDefaultValueFunction): Added exception check to prevent
+ toString and valueOf functions from observing execution after an exception
+ has been thrown. This removes some of the burden of exception checking
+ from the machine.
+
+ (KJS::JSObject::defaultValue): Removed redundant exception check here.
+
+ * kjs/PropertySlot.cpp:
+ (KJS::PropertySlot::functionGetter): Added exception check to prevent
+ getter functions from observing execution after an exception has been
+ thrown. This removes some of the burden of exception checking from the
+ machine.
+
+2008-07-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Optimized a[n] get and put for cases where n is an immediate unsigned
+ value.
+
+ SunSpider says 3.5% faster.
+
+2008-07-01 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 19844: JavaScript Switch statement modifies "this"
+ <https://bugs.webkit.org/show_bug.cgi?id=19844>
+
+ Use a temporary when generating code for switch clauses to avoid
+ overwriting 'this' or a local variable.
+
+ * kjs/nodes.cpp:
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-07-01 Christian Dywan <christian@twotoasts.de>
+
+ Gtk+ build fix.
+
+ * kjs/list.cpp: Include "JSCell.h"
+
+2008-07-01 Kevin McCullough <kmccullough@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-07-01 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Anders Carlsson.
+
+ - Mac release build fix
+
+ * JavaScriptCore.exp:
+
+2008-07-01 Sam Weinig <sam@webkit.org>
+
+ Try and fix mac builds.
+
+ * JavaScriptCore.exp:
+
+2008-07-01 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne builds.
+
+ * kjs/DateMath.cpp:
+
+2008-07-01 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ Split JSCell and JSNumberCell class declarations out of JSValue.h
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/JSPropertyNameIterator.h:
+ * kjs/AllInOneFile.cpp:
+ * kjs/JSCell.cpp: Copied from JavaScriptCore/kjs/JSValue.cpp.
+ * kjs/JSCell.h: Copied from JavaScriptCore/kjs/JSValue.h.
+ (KJS::JSValue::getJSNumber):
+ * kjs/JSNumberCell.cpp:
+ * kjs/JSNumberCell.h: Copied from JavaScriptCore/kjs/JSValue.h.
+ * kjs/JSObject.h:
+ * kjs/JSString.cpp:
+ (KJS::jsString):
+ (KJS::jsOwnedString):
+ * kjs/JSString.h:
+ (KJS::JSValue::toThisJSString):
+ * kjs/JSValue.cpp:
+ * kjs/JSValue.h:
+
+2008-07-01 Anders Carlsson <andersca@apple.com>
+
+ Build fixes.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::addStaticGlobals):
+
+2008-07-01 Simon Hausmann <hausmann@webkit.org>
+
+ Build fix, include OwnPtr.h.
+
+ * kjs/RegExpConstructor.h:
+
+2008-06-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed a global object leak caused by the switch to one register file.
+
+ Don't unconditionally mark the register file, since that logically
+ makes all global variables GC roots, even when their global object is
+ no longer reachable.
+
+ Instead, make the global object associated with the register file
+ responsible for marking the register file.
+
+2008-06-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed the "registerBase" abstraction. Since the register file never
+ reallocates, we can keep direct pointers into it, instead of
+ <registerBase, offset> tuples.
+
+ SunSpider says 0.8% faster.
+
+2008-06-30 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by NOBODY (build fix).
+
+ Fix build by adding all (hopefully) the missing includes.
+
+ * kjs/BooleanPrototype.cpp:
+ * kjs/DateConstructor.cpp:
+ * kjs/ErrorPrototype.cpp:
+ * kjs/FunctionPrototype.cpp:
+ * kjs/NativeErrorConstructor.cpp:
+ * kjs/NumberPrototype.cpp:
+ * kjs/ObjectPrototype.cpp:
+ * kjs/RegExpConstructor.cpp:
+ * kjs/StringConstructor.cpp:
+ * kjs/StringPrototype.cpp:
+
+2008-06-30 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19830: REGRESSION (r34883): Google Reader doesn't show up feed list on sidebar
+ <https://bugs.webkit.org/show_bug.cgi?id=19830>
+
+ Ensure that we do not eliminate a write to a local register when doing
+ peephole optimizations.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ (KJS::CodeGenerator::emitJumpIfFalse):
+
+2008-06-30 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Alder.
+
+ Split InternalFunction into its own header file.
+
+ * API/JSCallbackFunction.h:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/ArrayConstructor.h:
+ * kjs/BooleanConstructor.h:
+ * kjs/DateConstructor.h:
+ * kjs/ErrorConstructor.h:
+ * kjs/FunctionConstructor.h:
+ * kjs/FunctionPrototype.h:
+ * kjs/InternalFunction.h: Copied from kjs/JSFunction.h.
+ * kjs/JSFunction.h:
+ * kjs/NativeErrorConstructor.h:
+ * kjs/NumberConstructor.h:
+ * kjs/ObjectConstructor.h:
+ * kjs/RegExpConstructor.h:
+ * kjs/StringConstructor.h:
+ * profiler/Profiler.cpp:
+
+2008-06-30 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Kevin McCullough.
+
+ Remove empty files Instruction.cpp, LabelID.cpp, Register.cpp and RegisterID.cpp.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Instruction.cpp: Removed.
+ * VM/LabelID.cpp: Removed.
+ * VM/Register.cpp: Removed.
+ * VM/RegisterID.cpp: Removed.
+
+2008-06-30 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped (reluctantly) by Kevin McCullough.
+
+ Rename date_object.h/cpp to DateInstance.h/cpp
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/DateConstructor.cpp:
+ * kjs/DateInstance.cpp: Copied from kjs/date_object.cpp.
+ * kjs/DateInstance.h: Copied from kjs/date_object.h.
+ * kjs/DatePrototype.cpp:
+ * kjs/DatePrototype.h:
+ * kjs/date_object.cpp: Removed.
+ * kjs/date_object.h: Removed.
+
+2008-06-30 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ Remove internal.cpp and move its contents to there own .cpp files.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/GetterSetter.cpp: Copied from kjs/internal.cpp.
+ * kjs/InternalFunction.cpp: Copied from kjs/internal.cpp.
+ * kjs/JSNumberCell.cpp: Copied from kjs/internal.cpp.
+ * kjs/JSString.cpp: Copied from kjs/internal.cpp.
+ * kjs/JSString.h:
+ * kjs/LabelStack.cpp: Copied from kjs/internal.cpp.
+ * kjs/NumberConstructor.cpp:
+ * kjs/NumberObject.cpp:
+ (KJS::constructNumber):
+ (KJS::constructNumberFromImmediateNumber):
+ * kjs/internal.cpp: Removed.
+
+2008-06-30 Adam Roben <aroben@apple.com>
+
+ Fix <rdar://5954749> Assertion failure due to HashTable's use of
+ operator&
+
+ HashTable was passing &value to constructDeletedValue, which in
+ classes like WebCore::COMPtr would cause an assertion. We now pass
+ value by reference instead of by address so that the HashTraits
+ implementations have more flexibility in constructing the deleted
+ value.
+
+ Reviewed by Ada Chan.
+
+ * VM/CodeGenerator.h: Updated for changes to HashTraits.
+ * wtf/HashTable.h:
+ (WTF::::deleteBucket): Changed to pass bucket by reference instead of
+ by address.
+ (WTF::::checkKey): Ditto.
+ * wtf/HashTraits.h:
+ (WTF::): Updated HashTraits for HashTable change.
+
+2008-07-01 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Cameron Zwarich.
+
+ Make RegisterFile really unmap memory on destruction.
+
+ This fixes run-webkit-tests --threaded, which ran out of address space in a few seconds.
+
+ * VM/RegisterFile.cpp: (KJS::RegisterFile::~RegisterFile): Unmap all the memory, not just
+ 1/4 of it.
+
+ * kjs/JSGlobalObject.h: Don't include RegisterFile.h, so that changes to it don't make
+ half of WebCore rebuild.
+
+ * VM/Machine.h: Don't forward declare RegisterFile, as RegisterFile.h is included already.
+
+ * VM/RegisterFile.h: (KJS::RegisterFile::RegisterFile): Assert that the allocation succeeded.
+
+2008-06-30 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Rubber-stamped by Oliver.
+
+ Correct the documentation for op_put_by_index.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-06-29 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19821: Merge the instruction pair (less, jfalse)
+ <https://bugs.webkit.org/show_bug.cgi?id=19821>
+
+ This is a 2.4% win on SunSpider. I needed to add an ALWAYS_INLINE
+ intrinisc to CodeGenerator::rewindBinaryOp() to avoid a massive
+ regression in regexp-dna.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::rewindBinaryOp):
+ (KJS::CodeGenerator::emitJumpIfFalse):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.cpp:
+ (KJS::):
+ * VM/Opcode.h:
+
+2008-06-29 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne builds.
+
+ * kjs/JSObject.cpp:
+ * kjs/JSValue.cpp:
+
+2008-06-29 Sam Weinig <sam@webkit.org>
+
+ Build fix for Qt.
+
+ * kjs/DateMath.cpp:
+ * kjs/DatePrototype.cpp:
+
+2008-06-29 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Cameron Zwarich.
+
+ Splits ErrorConstructor, ErrorPrototype, NativeErrorConstructor and
+ NativeErrorPrototype out of error_object.h/cpp and renames it ErrorInstance.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ArrayConstructor.cpp:
+ * kjs/ArrayPrototype.cpp:
+ * kjs/BooleanPrototype.cpp:
+ * kjs/DatePrototype.cpp:
+ * kjs/ErrorConstructor.cpp: Copied from kjs/error_object.cpp.
+ * kjs/ErrorConstructor.h: Copied from kjs/error_object.h.
+ * kjs/ErrorInstance.cpp: Copied from kjs/error_object.cpp.
+ * kjs/ErrorInstance.h: Copied from kjs/error_object.h.
+ * kjs/ErrorPrototype.cpp: Copied from kjs/error_object.cpp.
+ * kjs/ErrorPrototype.h: Copied from kjs/error_object.h.
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSObject.cpp:
+ * kjs/JSValue.cpp:
+ * kjs/NativeErrorConstructor.cpp: Copied from kjs/error_object.cpp.
+ * kjs/NativeErrorConstructor.h: Copied from kjs/error_object.h.
+ * kjs/NativeErrorPrototype.cpp: Copied from kjs/error_object.cpp.
+ * kjs/NativeErrorPrototype.h: Copied from kjs/error_object.h.
+ * kjs/NumberPrototype.cpp:
+ * kjs/RegExpConstructor.cpp:
+ * kjs/RegExpObject.cpp:
+ * kjs/RegExpPrototype.cpp:
+ * kjs/StringPrototype.cpp:
+ * kjs/error_object.cpp: Removed.
+ * kjs/error_object.h: Removed.
+ * kjs/internal.cpp:
+
+2008-06-29 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne build.
+
+ * kjs/DateConstructor.cpp:
+ * kjs/DateMath.cpp:
+ * kjs/JSObject.cpp:
+
+2008-06-29 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Oliver Hunt.
+
+ Splits DateConstructor and DatePrototype out of date_object.h/cpp
+ Moves shared Date code into DateMath.
+
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/DateConstructor.cpp: Copied from kjs/date_object.cpp.
+ * kjs/DateConstructor.h: Copied from kjs/date_object.h.
+ * kjs/DateMath.cpp:
+ (KJS::ymdhmsToSeconds):
+ (KJS::):
+ (KJS::skipSpacesAndComments):
+ (KJS::findMonth):
+ (KJS::parseDate):
+ (KJS::timeClip):
+ (KJS::formatDate):
+ (KJS::formatDateUTCVariant):
+ (KJS::formatTime):
+ * kjs/DateMath.h:
+ (KJS::gmtoffset):
+ * kjs/DatePrototype.cpp: Copied from kjs/date_object.cpp.
+ * kjs/DatePrototype.h: Copied from kjs/date_object.h.
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSObject.cpp:
+ * kjs/date_object.cpp:
+ * kjs/date_object.h:
+ * kjs/internal.cpp:
+
+2008-06-29 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Rubber-stamped by Cameron Zwarich
+
+ Fix Gtk non-AllInOne build
+
+ * GNUmakefile.am: include JSVariableObject.cpp
+ * kjs/RegExpConstructor.cpp: include RegExpObject.h
+ * kjs/RegExpObject.h: forward declare RegExpPrototype
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam and Cameron.
+
+ - fix https://bugs.webkit.org/show_bug.cgi?id=19805
+ Array.concat turns missing array elements into "undefined"
+
+ Test: fast/js/array-holes.html
+
+ * JavaScriptCore.exp: No longer export JSArray::getItem.
+
+ * kjs/ArrayPrototype.cpp:
+ (KJS::arrayProtoFuncConcat): Changed to use getProperty instead of
+ JSArray::getItem -- need to handle properties from the prototype chain
+ instead of ignoring them.
+
+ * kjs/JSArray.cpp: Removed getItem.
+ * kjs/JSArray.h: Ditto.
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Cameron.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19804
+ optimize access to arrays without "holes"
+
+ SunSpider says 1.8% faster.
+
+ * kjs/JSArray.cpp:
+ (KJS::JSArray::JSArray): Initialize m_fastAccessCutoff when creating
+ arrays. Also updated for new location of m_vectorLength.
+ (KJS::JSArray::getItem): Updated for new location of m_vectorLength.
+ (KJS::JSArray::getSlowCase): Added. Broke out the non-hot parts of
+ getOwnPropertySlot to make the hot part faster.
+ (KJS::JSArray::getOwnPropertySlot): Added a new faster case for
+ indices lower than m_fastAccessCutoff. We can do theese with no
+ additional checks or branches.
+ (KJS::JSArray::put): Added a new faster case for indices lower than
+ m_fastAccessCutoff. We can do theese with no additional checks or
+ branches. Moved the maxArrayIndex handling out of this function.
+ Added code to set m_fastAccessCutoff when the very last hole in
+ an array is filled; this is how the cutoff gets set for most arrays.
+ (KJS::JSArray::putSlowCase): Moved the rest of the put function logic
+ in here, to make the hot part of the put function faster.
+ (KJS::JSArray::deleteProperty): Added code to lower m_fastAccessCutoff
+ when a delete makes a new hole in the array.
+ (KJS::JSArray::getPropertyNames): Updated for new location of
+ m_vectorLength.
+ (KJS::JSArray::increaseVectorLength): Ditto.
+ (KJS::JSArray::setLength): Added code to lower m_fastAccessCutoff
+ when setLength makes the array smaller.
+ (KJS::JSArray::mark): Updated for new location of m_vectorLength.
+ (KJS::JSArray::sort): Ditto. Set m_fastAccessCutoff after moving
+ all the holes to the end of the array.
+ (KJS::JSArray::compactForSorting): Ditto.
+ (KJS::JSArray::checkConsistency): Added consistency checks fro
+ m_fastAccessCutoff and updated for the new location of m_vectorLength.
+
+ * kjs/JSArray.h: Added declarations for slow case functions.
+ Replaced m_vectorLength with m_fastAccessCutoff.
+
+2008-06-28 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Sam.
+
+ When executing a native call, check for an exception before writing the
+ return value.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-06-28 Mark Rowe <mrowe@apple.com>
+
+ Build fix. Flag headers as private or public as is appropriate.
+ These settings were accidentally removed during some project file cleanup.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ Splits RegExpConstructor and RegExpPrototype out of RegExpObject.h/cpp
+
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/RegExpConstructor.cpp: Copied from kjs/RegExpObject.cpp.
+ * kjs/RegExpConstructor.h: Copied from kjs/RegExpObject.h.
+ * kjs/RegExpObject.cpp:
+ * kjs/RegExpObject.h:
+ * kjs/RegExpPrototype.cpp: Copied from kjs/RegExpObject.cpp.
+ * kjs/RegExpPrototype.h: Copied from kjs/RegExpObject.h.
+ * kjs/StringPrototype.cpp:
+ * kjs/internal.cpp:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Fix non-AllInOne builds.
+
+ * kjs/StringConstructor.cpp:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ Rename string_object.h/cpp to StringObject.h/cpp and split out StringObjectThatMasqueradesAsUndefined,
+ StringConstructor and StringPrototype.
+
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * kjs/AllInOneFile.cpp:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/StringConstructor.cpp: Copied from JavaScriptCore/kjs/string_object.cpp.
+ * kjs/StringConstructor.h: Copied from JavaScriptCore/kjs/string_object.h.
+ * kjs/StringObject.cpp: Copied from JavaScriptCore/kjs/string_object.cpp.
+ * kjs/StringObject.h: Copied from JavaScriptCore/kjs/string_object.h.
+ * kjs/StringObjectThatMasqueradesAsUndefined.h: Copied from JavaScriptCore/kjs/string_object.h.
+ * kjs/StringPrototype.cpp: Copied from JavaScriptCore/kjs/string_object.cpp.
+ * kjs/StringPrototype.h: Copied from JavaScriptCore/kjs/string_object.h.
+ * kjs/internal.cpp:
+ * kjs/string_object.cpp: Removed.
+ * kjs/string_object.h: Removed.
+
+2008-06-28 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Gtk build fix: JSVariableObject is now part of AllInOne
+
+ * GNUmakefile.am:
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19801
+ add a feature so we can tell what regular expressions are taking time
+
+ * pcre/pcre_compile.cpp:
+ (jsRegExpCompile): Compile in the string if REGEXP_HISTOGRAM is on.
+
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute): Add hook to time execution.
+ (Histogram::~Histogram): Print a sorted list of what took time.
+ (Histogram::add): Accumulate records of what took time.
+ (HistogramTimeLogger::~HistogramTimeLogger): Hook that calls
+ Histogram::add at the right moment and creates the global histogram
+ object.
+
+ * pcre/pcre_internal.h: Define REGEXP_HISTOGRAM.
+
+ * pcre/pcre_tables.cpp: Added missing include of "config.h". Not needed
+ any more, but an omissions an earlier version of this patch detected.
+ * pcre/pcre_ucp_searchfuncs.cpp: Ditto.
+ * pcre/pcre_xclass.cpp: Ditto.
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Try and fix the Windows build again.
+
+ * kjs/RegExpObject.cpp:
+ * kjs/date_object.cpp:
+ * kjs/error_object.cpp:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ Remove unused StringConstructorFunction class.
+
+ * kjs/string_object.h:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Fix windows build.
+
+ * kjs/ArrayPrototype.cpp:
+ * kjs/BooleanPrototype.cpp:
+ * kjs/BooleanPrototype.h:
+ * kjs/FunctionPrototype.cpp:
+ * kjs/JSImmediate.cpp:
+ * kjs/JSObject.cpp:
+ * kjs/MathObject.cpp:
+ * kjs/NumberPrototype.cpp:
+ * kjs/NumberPrototype.h:
+ * kjs/ObjectConstructor.cpp:
+ * kjs/RegExpObject.h:
+ * kjs/error_object.h:
+ * kjs/string_object.cpp:
+
+2008-06-28 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Oliver Hunt.
+
+ Splits FunctionConstructor out of FunctionPrototype.h/cpp
+ Splits NumberConstructor and NumberPrototype out of NumberObject.h/cpp
+ Rename object_object.h/cpp to ObjectPrototype.h/cpp and split out ObjectConstructor.
+
+ * API/JSCallbackConstructor.cpp:
+ * API/JSClassRef.cpp:
+ * API/JSObjectRef.cpp:
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ArrayConstructor.cpp:
+ * kjs/ArrayConstructor.h:
+ * kjs/FunctionConstructor.cpp: Copied from JavaScriptCore/kjs/FunctionPrototype.cpp.
+ * kjs/FunctionConstructor.h: Copied from JavaScriptCore/kjs/FunctionPrototype.h.
+ * kjs/FunctionPrototype.cpp:
+ * kjs/FunctionPrototype.h:
+ * kjs/JSFunction.cpp:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSImmediate.cpp:
+ * kjs/MathObject.h:
+ * kjs/NumberConstructor.cpp: Copied from JavaScriptCore/kjs/NumberObject.cpp.
+ * kjs/NumberConstructor.h: Copied from JavaScriptCore/kjs/NumberObject.h.
+ * kjs/NumberObject.cpp:
+ * kjs/NumberObject.h:
+ * kjs/NumberPrototype.cpp: Copied from JavaScriptCore/kjs/NumberObject.cpp.
+ * kjs/NumberPrototype.h: Copied from JavaScriptCore/kjs/NumberObject.h.
+ * kjs/ObjectConstructor.cpp: Copied from JavaScriptCore/kjs/object_object.cpp.
+ * kjs/ObjectConstructor.h: Copied from JavaScriptCore/kjs/object_object.h.
+ * kjs/ObjectPrototype.cpp: Copied from JavaScriptCore/kjs/object_object.cpp.
+ * kjs/ObjectPrototype.h: Copied from JavaScriptCore/kjs/object_object.h.
+ * kjs/RegExpObject.h:
+ * kjs/Shell.cpp:
+ * kjs/error_object.h:
+ * kjs/internal.cpp:
+ * kjs/nodes.cpp:
+ * kjs/object_object.cpp: Removed.
+ * kjs/object_object.h: Removed.
+ * kjs/string_object.h:
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix https://bugs.webkit.org/show_bug.cgi?id=19796
+ optimize expressions with ignored results (especially post-increment)
+
+ SunSpider says 0.9% faster.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::tempDestination): Create a new temporary for
+ ignoredResult() too, just as we would for 0.
+ (KJS::CodeGenerator::finalDestination): Use the temporary if the
+ register passed in is ignoredResult() too, just as we would for 0.
+ (KJS::CodeGenerator::destinationForAssignResult): Return 0 if the
+ passed in register is ignoredResult(), just as we would for 0.
+ (KJS::CodeGenerator::moveToDestinationIfNeeded): Return 0 if the
+ register passed in is ignoredResult(). What matters is that we
+ don't want to emit a move. The return value won't be looked at.
+ (KJS::CodeGenerator::emitNode): Allow ignoredResult() and pass it
+ through to the node's emitCode function.
+
+ * VM/RegisterID.h:
+ (KJS::ignoredResult): Added. Special value to indicate the result of
+ a node will be ignored and need not be put in any register.
+
+ * kjs/nodes.cpp:
+ (KJS::NullNode::emitCode): Do nothing if dst == ignoredResult().
+ (KJS::BooleanNode::emitCode): Ditto.
+ (KJS::NumberNode::emitCode): Ditto.
+ (KJS::StringNode::emitCode): Ditto.
+ (KJS::RegExpNode::emitCode): Ditto.
+ (KJS::ThisNode::emitCode): Ditto.
+ (KJS::ResolveNode::emitCode): Do nothing if dst == ignoredResult() and
+ the identifier resolves to a local variable.
+ (KJS::ObjectLiteralNode::emitCode): Do nothing if dst == ignoredResult()
+ and the object is empty.
+ (KJS::PostIncResolveNode::emitCode): If dst == ignoredResult(), then do
+ nothing for the local constant case, and do a pre-increment in all the
+ other cases.
+ (KJS::PostDecResolveNode::emitCode): Ditto.
+ (KJS::PostIncBracketNode::emitCode): Ditto.
+ (KJS::PostDecBracketNode::emitCode): Ditto.
+ (KJS::PostIncDotNode::emitCode): Ditto.
+ (KJS::PostDecDotNode::emitCode): Ditto.
+ (KJS::DeleteValueNode::emitCode): Pass ignoredResult() when evaluating
+ the expression.
+ (KJS::VoidNode::emitCode): Ditto.
+ (KJS::TypeOfResolveNode::emitCode): If dst == ignoredResult(), do nothing
+ if the identifier resolves to a local variable, and don't bother generating
+ a typeof opcode in the other case.
+ (KJS::TypeOfValueNode::emitCode): Ditto.
+ (KJS::PreIncResolveNode::emitCode): Do nothing if dst == ignoredResult() and
+ the identifier resolves to a local constant.
+ (KJS::PreDecResolveNode::emitCode): Ditto.
+ (KJS::AssignResolveNode::emitCode): Turn ignoredResult() into 0 in a couple
+ places, because we need to put the result into a register so we can assign
+ it. At other sites this is taken care of by functions like finalDestination.
+ (KJS::CommaNode::emitCode): Pass ignoredResult() when evaluating the first
+ expression.
+ (KJS::ForNode::emitCode): Pass ignoredResult() when evaluating the first and
+ third expressions.
+ (KJS::ForInNode::emitCode): Pass ignoredResult() when evaluating the first
+ expression.
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19787
+ create most arrays from values in registers rather than with multiple put operations
+
+ SunSpider says 0.8% faster.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump): Added argv and argc parameters to new_array.
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Ditto.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitNewArray): Added.
+ * VM/CodeGenerator.h: Added ElementNode* argument to emitNewArray.
+
+ * kjs/nodes.cpp:
+ (KJS::ArrayNode::emitCode): Pass the ElementNode to emitNewArray so it can be
+ initialized with as many elements as possible. If the array doesn't have any
+ holes in it, that's all that's needed. If there are holes, then emit some separate
+ put operations for the other values in the array and for the length as needed.
+
+ * kjs/nodes.h: Added some accessors to ElementNode so the code generator can
+ iterate through elements and generate code to evaluate them. Now ArrayNode does
+ not need to be a friend. Also took out some unused PlacementNewAdoptType
+ constructors.
+
+2008-06-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ * kjs/nodes.h: Remove obsolete PlacementNewAdopt constructors.
+ We no longer mutate the AST in place.
+
+2008-06-28 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Build fix
+
+ * VM/Machine.cpp: include stdio.h for printf
+
+2008-06-27 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Fix platforms that don't use AllInOne.cpp
+
+ * kjs/BooleanConstructor.h:
+ * kjs/BooleanPrototype.h:
+ * kjs/FunctionPrototype.cpp:
+
+2008-06-27 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Oliver Hunt.
+
+ Splits ArrayConstructor out of ArrayPrototype.h/cpp
+ Splits BooleanConstructor and BooleanPrototype out of BooleanObject.h/cpp
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ArrayConstructor.cpp: Copied from kjs/ArrayPrototype.cpp.
+ * kjs/ArrayConstructor.h: Copied from kjs/ArrayPrototype.h.
+ * kjs/ArrayPrototype.cpp:
+ * kjs/ArrayPrototype.h:
+ * kjs/BooleanConstructor.cpp: Copied from kjs/BooleanObject.cpp.
+ * kjs/BooleanConstructor.h: Copied from kjs/BooleanObject.h.
+ * kjs/BooleanObject.cpp:
+ * kjs/BooleanObject.h:
+ * kjs/BooleanPrototype.cpp: Copied from kjs/BooleanObject.cpp.
+ * kjs/BooleanPrototype.h: Copied from kjs/BooleanObject.h.
+ * kjs/CommonIdentifiers.h:
+ * kjs/FunctionPrototype.cpp:
+ * kjs/JSArray.cpp:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSImmediate.cpp:
+ * kjs/Shell.cpp:
+ * kjs/internal.cpp:
+ * kjs/nodes.cpp:
+ * kjs/string_object.cpp:
+
+2008-06-27 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Sam.
+
+ Bug 18626: SQUIRRELFISH: support the "slow script" dialog <https://bugs.webkit.org/show_bug.cgi?id=18626>
+ <rdar://problem/5973931> Slow script dialog needs to be reimplemented for squirrelfish
+
+ Adds support for the slow script dialog in squirrelfish. This requires the addition
+ of three new op codes, op_loop, op_loop_if_true, and op_loop_if_less which have the
+ same behaviour as their simple jump equivalents but have an additional time out check.
+
+ Additional assertions were added to other jump instructions to prevent accidentally
+ creating loops with jump types that do not support time out checks.
+
+ Sunspider does not report a regression, however this appears very sensitive to code
+ layout and hardware, so i would expect up to a 1% regression on other systems.
+
+ Part of this required moving the old timeout logic from JSGlobalObject and into Machine
+ which is the cause of a number of the larger diff blocks.
+
+ * JavaScriptCore.exp:
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ (KJS::CodeGenerator::emitJumpScopes):
+ * VM/ExceptionHelpers.cpp:
+ (KJS::InterruptedExecutionError::isWatchdogException):
+ (KJS::createInterruptedExecutionException):
+ * VM/ExceptionHelpers.h:
+ * VM/LabelID.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::Machine):
+ (KJS::Machine::throwException):
+ (KJS::Machine::resetTimeoutCheck):
+ (KJS::getCurrentTime):
+ (KJS::Machine::checkTimeout):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ (KJS::Machine::setTimeoutTime):
+ (KJS::Machine::startTimeoutCheck):
+ (KJS::Machine::stopTimeoutCheck):
+ (KJS::Machine::initTimeout):
+ * VM/Opcode.cpp:
+ (KJS::):
+ * VM/Opcode.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ (KJS::JSGlobalObject::setTimeoutTime):
+ (KJS::JSGlobalObject::startTimeoutCheck):
+ * kjs/JSGlobalObject.h:
+ * kjs/JSObject.h:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-06-27 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Gtk and Qt build fix: Remove RegisterFileStack from the build
+ scripts.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+
+2008-06-27 Adele Peterson <adele@apple.com>
+
+ Reviewed by Geoff.
+
+ Build fixes.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * VM/RegisterFile.h:
+ (KJS::RegisterFile::RegisterFile):
+ * kjs/JSGlobalObject.cpp:
+ * kjs/collector.cpp:
+
+2008-06-27 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ One RegisterFile to rule them all!
+
+ SunSpider reports a 0.2% speedup.
+
+ This patch removes the RegisterFileStack abstraction and replaces it with
+ a single register file that
+
+ (a) allocates a fixed storage area, including a fixed area for global
+ vars, so that no operation may cause the register file to reallocate
+
+ and
+
+ (b) swaps between global storage areas when executing code in different
+ global objects.
+
+ This patch also changes the layout of the register file so that all call
+ frames, including call frames for global code, get a header. This is
+ required to support re-entrant global code. It also just makes things simpler.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addGlobalVar): New function. Differs from addVar in
+ that
+
+ (a) global vars don't contribute to a CodeBlock's numLocals count, since
+ global storage is fixed and allocated at startup
+
+ and
+
+ (b) references to global vars get shifted to elide intermediate stack
+ between "r" and the global storage area.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters): Updated this function to match the new
+ register file layout, and added the ability to dump exact identifiers
+ for the different parts of a call frame.
+
+ (KJS::Machine::unwindCallFrame): Updated this function to match the new
+ register file layout.
+
+ (KJS::Machine::execute): Updated this function to initialize a call frame
+ header for global code, and to swap global storage areas when switching
+ to execution in a new global object.
+
+ (KJS::Machine::privateExecute): Got rid of "safeForReentry" and re-reading
+ of registerBase because the register file is always safe for reentry now,
+ and registerBase never changes.
+
+ * VM/Machine.h: Moved the call frame header enum from Machine to RegisterFile,
+ to resolve a header dependency problem (a good sign that the enum belonged
+ in RegisterFile all along!)
+
+ * VM/RegisterFile.cpp:
+ * VM/RegisterFile.h: Changed RegisterFile to mmap a fixed size register
+ area. This allows us to avoid re-allocting the register file later on.
+ Instead, we rely on the OS to allocate physical pages to the register
+ file as necessary.
+
+ * VM/RegisterFileStack.cpp: Removed. Tada!
+ * VM/RegisterFileStack.h: Removed. Tada!
+
+ * kjs/DebuggerCallFrame.cpp: Updated this class to match the new
+ register file layout, greatly simplifying it in the process.
+
+ * kjs/JSActivation.h:
+ * kjs/JSActivation.cpp: Moved some of this logic up to JSVariableObject,
+ since the global object now needs to be able to tear off its registers
+ just like the activation object.
+
+ * kjs/JSFunction.cpp: No need to fiddle with the register file anymore.
+
+ * kjs/JSGlobalObject.h:
+ * kjs/JSGlobalObject.cpp: Updated JSGlobalObject to support moving its
+ global storage area into and out of the register file.
+
+ * kjs/PropertySlot.cpp: No need to fiddle with the register file anymore.
+
+ * kjs/collector.cpp: Renamed markStackObjectConservatively to
+ markConservatively, since we don't just mark stack objects this way.
+
+ Also, added code to mark the machine's register file.
+
+ * kjs/config.h: Moved some platforms #defines from here...
+ * wtf/Platform.h: ...to here, to support mmap/VirtualAlloc detection
+ in RegisterFile.h.
+
+2008-06-26 Mark Rowe <mrowe@apple.com>
+
+ Speculative fix for the Windows build.
+
+ * kjs/JSImmediate.cpp:
+
+2008-06-26 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Darin Adler and Geoff Garen.
+
+ Fix the malloc zone introspection functions so that malloc_zone_statistics does not give
+ bogus output in an application that uses JavaScriptCore.
+
+ * kjs/CollectorHeapIntrospector.cpp:
+ (KJS::CollectorHeapIntrospector::statistics): Return statistics about memory allocated by the collector.
+ * kjs/CollectorHeapIntrospector.h:
+ * wtf/FastMalloc.cpp: Zero out the statistics. FastMalloc doesn't track this information at present.
+ Returning zero for all values is preferable to returning bogus data.
+
+2008-06-26 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19721
+ speed up JavaScriptCore by not wrapping strings in objects just
+ to call functions on them
+
+ - optimize UString append and the replace function a bit
+
+ SunSpider says 1.8% faster.
+
+ * JavaScriptCore.exp: Updated.
+
+ * VM/JSPropertyNameIterator.cpp: Added include of JSString.h, now needed
+ because jsString returns a JSString*.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Removed the toObject call from native
+ function calls. Also removed code to put the this value into a register.
+
+ * kjs/BooleanObject.cpp:
+ (KJS::booleanProtoFuncToString): Rewrite to handle false and true
+ separately.
+
+ * kjs/FunctionPrototype.cpp:
+ (KJS::constructFunction): Use single-character append rather than building
+ a string for each character.
+ * kjs/JSFunction.cpp:
+ (KJS::globalFuncUnescape): Ditto.
+
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::prototype): Added. Gets the appropriate prototype for
+ use with an immediate value. To be used instead of toObject when doing a
+ get on an immediate value.
+ * kjs/JSImmediate.h: Added prototype.
+
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::toString): Tweaked formatting.
+
+ * kjs/JSObject.h:
+ (KJS::JSValue::get): Use prototype instead of toObject to avoid creating
+ an object wrapper just to search for properties. This also saves an
+ unnecessary hash table lookup since the object wrappers themselves don't
+ have any properties.
+
+ * kjs/JSString.h: Added toThisString and toThisJSString.
+
+ * kjs/JSValue.cpp:
+ (KJS::JSCell::toThisString): Added.
+ (KJS::JSCell::toThisJSString): Added.
+ (KJS::JSCell::getJSNumber): Added.
+ (KJS::jsString): Changed return type to JSString*.
+ (KJS::jsOwnedString): Ditto.
+
+ * kjs/JSValue.h:
+ (KJS::JSValue::toThisString): Added.
+ (KJS::JSValue::toThisJSString): Added.
+ (KJS::JSValue::getJSNumber): Added.
+
+ * kjs/NumberObject.cpp:
+ (KJS::NumberObject::getJSNumber): Added.
+ (KJS::integer_part_noexp): Append C string directly rather than first
+ turning it into a UString.
+ (KJS::numberProtoFuncToString): Use getJSNumber to check if the value
+ is a number rather than isObject(&NumberObject::info). This works for
+ immediate numbers, number cells, and NumberObject instances.
+ (KJS::numberProtoFuncToLocaleString): Ditto.
+ (KJS::numberProtoFuncValueOf): Ditto.
+ (KJS::numberProtoFuncToFixed): Ditto.
+ (KJS::numberProtoFuncToExponential): Ditto.
+ (KJS::numberProtoFuncToPrecision): Ditto.
+ * kjs/NumberObject.h: Added getJSNumber.
+
+ * kjs/PropertySlot.cpp: Tweaked comment.
+
+ * kjs/internal.cpp:
+ (KJS::JSString::toThisString): Added.
+ (KJS::JSString::toThisJSString): Added.
+ (KJS::JSString::getOwnPropertySlot): Changed code that searches the
+ prototype chain to start with the string prototype and not create a
+ string object.
+ (KJS::JSNumberCell::toThisString): Added.
+ (KJS::JSNumberCell::getJSNumber): Added.
+
+ * kjs/lookup.cpp:
+ (KJS::staticFunctionGetter): Moved here, because there's no point in
+ having a function that's only used for a function pointer be inline.
+ (KJS::setUpStaticFunctionSlot): New function for getStaticFunctionSlot.
+
+ * kjs/lookup.h:
+ (KJS::staticValueGetter): Don't mark this inline. It doesn't make sense
+ to have a function that's only used for a function pointer be inline.
+ (KJS::getStaticFunctionSlot): Changed to get properties from the parent
+ first before doing any handling of functions. This is the fastest way
+ to return the function once the initial setup is done.
+
+ * kjs/string_object.cpp:
+ (KJS::StringObject::getPropertyNames): Call value() instead of getString(),
+ avoiding an unnecessary virtual function call (the call to the type()
+ function in the implementation of the isString() function).
+ (KJS::StringObject::toString): Added.
+ (KJS::StringObject::toThisString): Added.
+ (KJS::StringObject::toThisJSString): Added.
+ (KJS::substituteBackreferences): Rewrote to use a appending algorithm
+ instead of a the old one that tried to replace in place.
+ (KJS::stringProtoFuncReplace): Merged this function and the replace function.
+ Replaced the hand-rolled dynamic arrays for source ranges and replacements
+ with Vector.
+ (KJS::stringProtoFuncToString): Handle JSString as well as StringObject.
+ Removed the separate valueOf implementation, since it can just share this.
+ (KJS::stringProtoFuncCharAt): Use toThisString, which handles JSString as
+ well as StringObject, and is slightly more efficient than the old code too.
+ (KJS::stringProtoFuncCharCodeAt): Ditto.
+ (KJS::stringProtoFuncConcat): Ditto.
+ (KJS::stringProtoFuncIndexOf): Ditto.
+ (KJS::stringProtoFuncLastIndexOf): Ditto.
+ (KJS::stringProtoFuncMatch): Ditto.
+ (KJS::stringProtoFuncSearch): Ditto.
+ (KJS::stringProtoFuncSlice): Ditto.
+ (KJS::stringProtoFuncSplit): Ditto.
+ (KJS::stringProtoFuncSubstr): Ditto.
+ (KJS::stringProtoFuncSubstring): Ditto.
+ (KJS::stringProtoFuncToLowerCase): Use toThisJSString.
+ (KJS::stringProtoFuncToUpperCase): Ditto.
+ (KJS::stringProtoFuncToLocaleLowerCase): Ditto.
+ (KJS::stringProtoFuncToLocaleUpperCase): Ditto.
+ (KJS::stringProtoFuncLocaleCompare): Ditto.
+ (KJS::stringProtoFuncBig): Use toThisString.
+ (KJS::stringProtoFuncSmall): Ditto.
+ (KJS::stringProtoFuncBlink): Ditto.
+ (KJS::stringProtoFuncBold): Ditto.
+ (KJS::stringProtoFuncFixed): Ditto.
+ (KJS::stringProtoFuncItalics): Ditto.
+ (KJS::stringProtoFuncStrike): Ditto.
+ (KJS::stringProtoFuncSub): Ditto.
+ (KJS::stringProtoFuncSup): Ditto.
+ (KJS::stringProtoFuncFontcolor): Ditto.
+ (KJS::stringProtoFuncFontsize): Ditto.
+ (KJS::stringProtoFuncAnchor): Ditto.
+ (KJS::stringProtoFuncLink): Ditto.
+
+ * kjs/string_object.h: Added toString, toThisString, and toThisJSString.
+
+ * kjs/ustring.cpp:
+ (KJS::UString::append): Added a version that takes a character pointer and
+ size, so we don't have to create a UString just to append to another UString.
+ * kjs/ustring.h:
+
+2008-06-26 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Maciej.
+
+ Make JSGlobalData per-thread.
+
+ No change on SunSpider total.
+
+ * wtf/ThreadSpecific.h: Re-enabled the actual implementation.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject): Re-added a JSLock-related assertion. We'll probably
+ want to preserve these somehow to keep legacy behavior in working condition.
+ (KJS::JSGlobalObject::init): Initialize globalData pointer earlier, so that it is ready
+ when updating JSGlobalObject linked list.
+
+ * kjs/JSGlobalObject.h: (KJS::JSGlobalObject::head): Changed head() to be non-static, and
+ to use JSGlobalData associated with the current object.
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreadingOnce): Removed a no longer needed
+ Heap::registerAsMainThread() call.
+
+ * kjs/JSGlobalData.h: Removed a lying lie comment - parserObjectExtraRefCounts is not
+ transient, and while newParserObjects may conceptually be such, there is still some node
+ manipulation going on outside Parser::parse which touches it.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::~JSGlobalData): Delete recently added members.
+ (KJS::JSGlobalData::sharedInstance): Actually use a separate instance.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap):
+ (KJS::Heap::~Heap): Added a destructor, which unconditionally deletes everything.
+ (KJS::Heap::sweep): Removed code related to "collect on main thread only" logic.
+ (KJS::Heap::collect): Ditto.
+ (KJS::Heap::globalObjectCount): Explicitly use per-thread instance of JSGlobalObject linked
+ list now that JSGlobalObject::head() is not static. Curently, WebCoreStatistics methods only
+ work with the main thread currently anyway.
+ (KJS::Heap::protectedGlobalObjectCount): Ditto.
+
+ * kjs/collector.h: Removed code related to "collect on main thread only" logic.
+
+ * JavaScriptCore.exp: Removed Heap::collectOnMainThreadOnly.
+
+2008-06-26 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19767
+ REGRESSION: Crash in sort() when visiting http://www.onnyturf.com/subway/
+
+ * kjs/JSArray.cpp: (KJS::AVLTreeAbstractorForArrayCompare::set_balance_factor):
+ Made changing balance factor from -1 to +1 work correctly.
+
+ * wtf/AVLTree.h: (KJS::AVLTreeDefaultBSet::operator[]): Added an assertion that catches
+ this slightly earlier.
+
+2008-06-25 Timothy Hatcher <timothy@apple.com>
+
+ Fixes an ASSERT in the profiler when starting multiple profiles
+ with the same name inside the same function/program.
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile): Initialize m_stoppedCallDepth to zero.
+ (KJS::Profile::stopProfiling): Set the current node to the parent,
+ because we are in a call that will not get a didExecute call.
+ (KJS::Profile::removeProfile): Increment m_stoppedCallDepth to
+ account for didExecute not being called for profile.
+ (KJS::Profile::willExecute): Increment m_stoppedCallDepth if stopped.
+ (KJS::Profile::didExecute): Decrement m_stoppedCallDepth if stopped and
+ greater than zero, and return early.
+ * profiler/Profile.h: Added stoppedProfiling().
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::findProfile): Removed.
+ (KJS::Profiler::startProfiling): Don't return early for stopped profiles.
+ (KJS::Profiler::stopProfiling): Skipp stopped profiles.
+ (KJS::Profiler::didFinishAllExecution): Code clean-up.
+ * profiler/Profiler.h: Removed findProfile.
+
+2008-06-25 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Attempt to fix Windows debug build. The compiler gives a warning when
+ Structured Exception Handling and destructors are used in the same
+ function. Using manual locking and unlocking instead of constructors
+ and destructors should fix the warning.
+
+ * kjs/Shell.cpp:
+ (main):
+
+2008-06-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Forgot to address a review comment about better names for tracked objects, doing it now.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ * kjs/JSGlobalData.h:
+ * kjs/nodes.cpp:
+ (KJS::ParserRefCounted::ParserRefCounted):
+ (KJS::ParserRefCounted::ref):
+ (KJS::ParserRefCounted::deref):
+ (KJS::ParserRefCounted::hasOneRef):
+ (KJS::ParserRefCounted::deleteNewObjects):
+
+2008-06-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Remove more threadInstance() calls.
+
+ * kjs/JSFunction.cpp:
+ (KJS::JSFunction::getParameterName):
+ (KJS::IndexToNameMap::unMap):
+ (KJS::Arguments::deleteProperty):
+ * kjs/JSFunction.h:
+ Access nullIdentifier without going to thread specific storage.
+
+ * JavaScriptCore.exp:
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ * kjs/JSGlobalData.h:
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+ * kjs/Parser.h:
+ (KJS::ParserRefCountedData::ParserRefCountedData):
+ (KJS::Parser::parse):
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ParserRefCounted::ParserRefCounted):
+ (KJS::ParserRefCounted::ref):
+ (KJS::ParserRefCounted::deref):
+ (KJS::ParserRefCounted::hasOneRef):
+ (KJS::ParserRefCounted::deleteNewObjects):
+ (KJS::Node::Node):
+ (KJS::StatementNode::StatementNode):
+ (KJS::BreakpointCheckStatement::BreakpointCheckStatement):
+ (KJS::ConstDeclNode::ConstDeclNode):
+ (KJS::BlockNode::BlockNode):
+ (KJS::ForInNode::ForInNode):
+ (KJS::ScopeNode::ScopeNode):
+ (KJS::ProgramNode::ProgramNode):
+ (KJS::ProgramNode::create):
+ (KJS::EvalNode::EvalNode):
+ (KJS::EvalNode::create):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::FunctionBodyNode::create):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::NullNode::):
+ (KJS::BooleanNode::):
+ (KJS::NumberNode::):
+ (KJS::ImmediateNumberNode::):
+ (KJS::StringNode::):
+ (KJS::RegExpNode::):
+ (KJS::ThisNode::):
+ (KJS::ResolveNode::):
+ (KJS::ElementNode::):
+ (KJS::ArrayNode::):
+ (KJS::PropertyNode::):
+ (KJS::PropertyListNode::):
+ (KJS::ObjectLiteralNode::):
+ (KJS::BracketAccessorNode::):
+ (KJS::DotAccessorNode::):
+ (KJS::ArgumentListNode::):
+ (KJS::ArgumentsNode::):
+ (KJS::NewExprNode::):
+ (KJS::EvalFunctionCallNode::):
+ (KJS::FunctionCallValueNode::):
+ (KJS::FunctionCallResolveNode::):
+ (KJS::FunctionCallBracketNode::):
+ (KJS::FunctionCallDotNode::):
+ (KJS::PrePostResolveNode::):
+ (KJS::PostIncResolveNode::):
+ (KJS::PostDecResolveNode::):
+ (KJS::PostfixBracketNode::):
+ (KJS::PostIncBracketNode::):
+ (KJS::PostDecBracketNode::):
+ (KJS::PostfixDotNode::):
+ (KJS::PostIncDotNode::):
+ (KJS::PostDecDotNode::):
+ (KJS::PostfixErrorNode::):
+ (KJS::DeleteResolveNode::):
+ (KJS::DeleteBracketNode::):
+ (KJS::DeleteDotNode::):
+ (KJS::DeleteValueNode::):
+ (KJS::VoidNode::):
+ (KJS::TypeOfResolveNode::):
+ (KJS::TypeOfValueNode::):
+ (KJS::PreIncResolveNode::):
+ (KJS::PreDecResolveNode::):
+ (KJS::PrefixBracketNode::):
+ (KJS::PreIncBracketNode::):
+ (KJS::PreDecBracketNode::):
+ (KJS::PrefixDotNode::):
+ (KJS::PreIncDotNode::):
+ (KJS::PreDecDotNode::):
+ (KJS::PrefixErrorNode::):
+ (KJS::UnaryOpNode::UnaryOpNode):
+ (KJS::UnaryPlusNode::):
+ (KJS::NegateNode::):
+ (KJS::BitwiseNotNode::):
+ (KJS::LogicalNotNode::):
+ (KJS::BinaryOpNode::BinaryOpNode):
+ (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode):
+ (KJS::MultNode::):
+ (KJS::DivNode::):
+ (KJS::ModNode::):
+ (KJS::AddNode::):
+ (KJS::SubNode::):
+ (KJS::LeftShiftNode::):
+ (KJS::RightShiftNode::):
+ (KJS::UnsignedRightShiftNode::):
+ (KJS::LessNode::):
+ (KJS::GreaterNode::):
+ (KJS::LessEqNode::):
+ (KJS::GreaterEqNode::):
+ (KJS::InstanceOfNode::):
+ (KJS::InNode::):
+ (KJS::EqualNode::):
+ (KJS::NotEqualNode::):
+ (KJS::StrictEqualNode::):
+ (KJS::NotStrictEqualNode::):
+ (KJS::BitAndNode::):
+ (KJS::BitOrNode::):
+ (KJS::BitXOrNode::):
+ (KJS::LogicalAndNode::):
+ (KJS::LogicalOrNode::):
+ (KJS::ConditionalNode::):
+ (KJS::ReadModifyResolveNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::ReadModifyBracketNode::):
+ (KJS::AssignBracketNode::):
+ (KJS::AssignDotNode::):
+ (KJS::ReadModifyDotNode::):
+ (KJS::AssignErrorNode::):
+ (KJS::CommaNode::):
+ (KJS::VarDeclCommaNode::):
+ (KJS::ConstStatementNode::):
+ (KJS::SourceElements::SourceElements):
+ (KJS::EmptyStatementNode::):
+ (KJS::DebuggerStatementNode::):
+ (KJS::ExprStatementNode::):
+ (KJS::VarStatementNode::):
+ (KJS::IfNode::):
+ (KJS::IfElseNode::):
+ (KJS::DoWhileNode::):
+ (KJS::WhileNode::):
+ (KJS::ForNode::):
+ (KJS::ContinueNode::):
+ (KJS::BreakNode::):
+ (KJS::ReturnNode::):
+ (KJS::WithNode::):
+ (KJS::LabelNode::):
+ (KJS::ThrowNode::):
+ (KJS::TryNode::):
+ (KJS::ParameterNode::):
+ (KJS::FuncExprNode::):
+ (KJS::FuncDeclNode::):
+ (KJS::CaseClauseNode::):
+ (KJS::ClauseListNode::):
+ (KJS::CaseBlockNode::):
+ (KJS::SwitchNode::):
+ Changed ParserRefCounted to hold a JSGlobalData pointer, and used it to replace
+ threadInstance calls.
+
+2008-06-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Make the JavaScript shell collect the heap from main() instead of
+ jscmain() to suppress leak messages in debug builds.
+
+ * kjs/Shell.cpp:
+ (main):
+ (jscmain):
+
+2008-06-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Make the conversion of the pair (less, jtrue) to jless use register
+ reference counting information for safety instead of requiring callers
+ to decide whether it is safe.
+
+ No changes on SunSpider codegen.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-06-24 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/6031594> JSProfiler: Profiler goes into an infinite
+ loop sometimes.
+ <rdar://problem/6031603> JSProfiler: Profiler asserts in debug and
+ give the wrong times in release
+
+ Fixed two issues found by Tim in the same test.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::removeProfileStart): No longer take profile's time from
+ all ancestors, but instead attribute it to its parent. Also add an
+ Assert to ensure we only delete the child we mean to.
+ (KJS::Profile::removeProfileEnd): Ditto for profileEnd.
+ (KJS::Profile::didExecute): Cleaned up the execution order and correctly
+ attribute all of the parent's time to the new node.
+ * profiler/ProfileNode.cpp: If this node does not have a startTime it
+ should not get a giant total time, but instead be 0.
+ (KJS::ProfileNode::endAndRecordCall):
+ * profiler/ProfileNode.h:
+ (KJS::ProfileNode::removeChild): Should reset the sibling pointers since
+ one of them has been removed.
+
+2008-06-24 Darin Adler <darin@apple.com>
+
+ Reviewed by Cameron.
+
+ - fix https://bugs.webkit.org/show_bug.cgi?id=19739
+ REGRESSION: fast/js/property-getters-and-setters.html fails
+
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::put): Remove an untested optimization I checked in by accident.
+ The two loops up the prototype chain both need to start from this; instead the
+ second loop was starting where the first loop left off.
+
+2008-06-24 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * kjs/nodes.cpp:
+
+2008-06-24 Joerg Bornemann <joerg.bornemann@trolltech.com>
+
+ Reviewed by Simon.
+
+ For the Qt build on Windows don't depend on the presence of GNU CPP
+ but use MSVC's preprocessor instead.
+ dftables accepts a --preprocessor option which is set in pcre.pri for MSVC platforms.
+
+ * pcre/dftables: Added support for specifying the preprocessor command
+ to use via --preprocessor, similar to
+ WebCore/bindings/scripts/generate-bindings.pl.
+ * pcre/pcre.pri: Pass --preprocessor='cl /e' to dftables, or more
+ generally speaking QMAKE_CC /E for the win32-msvc buildspecs.
+
+2008-06-24 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Qt build, added missing include.
+
+ * kjs/PropertySlot.cpp:
+
+2008-06-24 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Cameron Zwarich.
+
+ Make ParserRefCountedCounter actually perform a leak check.
+
+ * kjs/nodes.cpp:
+ (KJS::ParserRefCountedCounter::~ParserRefCountedCounter): Check for leaks in destructor,
+ not in constructor.
+ (KJS::ParserRefCountedCounter::increment):
+ (KJS::ParserRefCountedCounter::decrement):
+ (KJS::ParserRefCounted::ParserRefCounted):
+ (KJS::ParserRefCounted::~ParserRefCounted):
+ While at it, also made counting thread-safe.
+
+2008-06-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19730: REGRESSION (r34497): Text in alerts in "Leisure suit Larry" is not wrapped
+ <https://bugs.webkit.org/show_bug.cgi?id=19730>
+
+ Do not convert the pair (less, jtrue) to jless when jtrue is a jump
+ target. An example of this is when the condition of a while loop is a
+ LogicalOrNode.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitLabel):
+
+2008-06-20 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Adam Roben.
+
+ Fix compile with MinGW.
+
+ * kjs/Shell.cpp:
+ * wtf/Threading.h:
+ (WTF::atomicIncrement):
+ (WTF::atomicDecrement):
+
+2008-06-23 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Prepration for returning memory to the OS on Windows. Track whether a portion of a span of memory was returned to the OS.
+ If it was, ask that it be recommitted before returning it to the application as an allocated region.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::New): If the span was decommitted, ask that it be recommitted before returning it.
+ (WTF::TCMalloc_PageHeap::AllocLarge): Ditto.
+ (WTF::TCMalloc_PageHeap::Carve): When splitting a span, ensure that the decommitted state propogates to the two new spans.
+ (WTF::TCMalloc_PageHeap::Delete): When merging a span, ensure that the resulting span is marked as decommitted if any of the
+ spans being merged were marked as decommitted.
+ (WTF::TCMalloc_PageHeap::IncrementalScavenge): Mark as decommitted after releasing the span.
+ (WTF::TCMalloc_Central_FreeList::FetchFromSpans): Add an assertion to catch a decommitted span being returned to the application
+ without first being recommitted.
+ (WTF::TCMalloc_Central_FreeList::Populate): Ditto.
+ * wtf/TCSystemAlloc.cpp: Stub out TCMalloc_SystemCommit.
+ * wtf/TCSystemAlloc.h:
+
+2008-06-23 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Remove the sample member of Span when NO_TCMALLOC_SAMPLES is defined.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::Delete): Only update Span::sample if NO_TCMALLOC_SAMPLES is not defined.
+ (WTF::TCMallocStats::do_free): Ditto.
+
+2008-06-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - work toward https://bugs.webkit.org/show_bug.cgi?id=19721
+
+ More preparation toward making functions work on primitive types without
+ creating wrapper objects. No speedup this time, but prepares for a future
+ speedup without slowing things down.
+
+ SunSpider reports no change.
+
+ - Eliminated the implementsCall, callAsFunction and construct virtual
+ functions from JSObject. Instead, the CallData and ConstructData for
+ a native function includes a function pointer that the caller can use
+ directly. Changed all call sites to use CallData and ConstructData.
+
+ - Changed the "this" argument to native functions to be a JSValue rather
+ than a JSObject. This prepares us for passing primitives into these
+ functions. The conversion to an object now must be done inside the
+ function. Critically, if it's a function that can be called on a DOM
+ window object, then we have to be sure to call toThisObject on the
+ argument before we use it for anything even if it's already an object.
+
+ - Eliminated the practice of using constructor objects in the global
+ object to make objects of the various basic types. Since these
+ constructors can't be replaced by script, there's no reason to involve
+ a constructor object at all. Added functions to do the construction
+ directly.
+
+ - Made some more class members private and protected, including virtual
+ function overrides. This can catch code using unnecessarily slow virtual
+ function code paths when the type of an object is known statically. If we
+ later find a new reason use the members outside the class it's easy to
+ make them public again.
+
+ - Moved the declarations of the native implementations for functions out
+ of header files. These can have internal linkage and be declared inside
+ the source file.
+
+ - Changed PrototypeFunction to take function pointers with the right
+ arguments to be put directly into CallData. This eliminates the
+ need to have a separate PrototypeReflexiveFunction, and reveals that the
+ real purpose of that class included something else specific to eval --
+ storage of a cached global object. So renamed PrototypeReflexiveFunction
+ to GlobalEvalFunction.
+
+ * API/JSCallbackConstructor.cpp:
+ (KJS::constructJSCallback):
+ (KJS::JSCallbackConstructor::getConstructData):
+ * API/JSCallbackConstructor.h:
+ * API/JSCallbackFunction.cpp:
+ (KJS::JSCallbackFunction::implementsHasInstance):
+ (KJS::JSCallbackFunction::call):
+ (KJS::JSCallbackFunction::getCallData):
+ * API/JSCallbackFunction.h:
+ (KJS::JSCallbackFunction::classInfo):
+ * API/JSCallbackObject.h:
+ (KJS::JSCallbackObject::classRef):
+ (KJS::JSCallbackObject::classInfo):
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::getConstructData):
+ (KJS::::construct):
+ (KJS::::getCallData):
+ (KJS::::call):
+ * API/JSObjectRef.cpp:
+ (JSObjectMakeFunction):
+ (JSObjectIsFunction):
+ (JSObjectCallAsFunction):
+ (JSObjectCallAsConstructor):
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp:
+ (KJS::jsTypeStringForValue):
+ (KJS::Machine::privateExecute):
+ * kjs/ArrayPrototype.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncReverse):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSort):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ (KJS::ArrayConstructor::ArrayConstructor):
+ (KJS::constructArrayWithSizeQuirk):
+ (KJS::constructWithArrayConstructor):
+ (KJS::ArrayConstructor::getConstructData):
+ (KJS::callArrayConstructor):
+ (KJS::ArrayConstructor::getCallData):
+ * kjs/ArrayPrototype.h:
+ * kjs/BooleanObject.cpp:
+ (KJS::booleanProtoFuncToString):
+ (KJS::booleanProtoFuncValueOf):
+ (KJS::constructBoolean):
+ (KJS::constructWithBooleanConstructor):
+ (KJS::BooleanConstructor::getConstructData):
+ (KJS::callBooleanConstructor):
+ (KJS::BooleanConstructor::getCallData):
+ (KJS::constructBooleanFromImmediateBoolean):
+ * kjs/BooleanObject.h:
+ * kjs/CallData.h:
+ (KJS::):
+ * kjs/ConstructData.h:
+ (KJS::):
+ * kjs/FunctionPrototype.cpp:
+ (KJS::callFunctionPrototype):
+ (KJS::FunctionPrototype::getCallData):
+ (KJS::functionProtoFuncToString):
+ (KJS::functionProtoFuncApply):
+ (KJS::functionProtoFuncCall):
+ (KJS::constructWithFunctionConstructor):
+ (KJS::FunctionConstructor::getConstructData):
+ (KJS::callFunctionConstructor):
+ (KJS::FunctionConstructor::getCallData):
+ (KJS::constructFunction):
+ * kjs/FunctionPrototype.h:
+ * kjs/JSArray.cpp:
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key):
+ (KJS::JSArray::sort):
+ (KJS::constructEmptyArray):
+ (KJS::constructArray):
+ * kjs/JSArray.h:
+ (KJS::JSArray::classInfo):
+ * kjs/JSFunction.cpp:
+ (KJS::JSFunction::call):
+ (KJS::globalFuncEval):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncIsNaN):
+ (KJS::globalFuncIsFinite):
+ (KJS::globalFuncDecodeURI):
+ (KJS::globalFuncDecodeURIComponent):
+ (KJS::globalFuncEncodeURI):
+ (KJS::globalFuncEncodeURIComponent):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ (KJS::globalFuncKJSPrint):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeFunction::getCallData):
+ (KJS::GlobalEvalFunction::GlobalEvalFunction):
+ (KJS::GlobalEvalFunction::mark):
+ * kjs/JSFunction.h:
+ (KJS::InternalFunction::classInfo):
+ (KJS::InternalFunction::functionName):
+ (KJS::JSFunction::classInfo):
+ (KJS::GlobalEvalFunction::cachedGlobalObject):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ (KJS::JSGlobalObject::mark):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObject):
+ (KJS::JSGlobalObject::evalFunction):
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toObject):
+ * kjs/JSNotAnObject.cpp:
+ * kjs/JSNotAnObject.h:
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::put):
+ (KJS::callDefaultValueFunction):
+ (KJS::JSObject::defaultValue):
+ (KJS::JSObject::lookupGetter):
+ (KJS::JSObject::lookupSetter):
+ (KJS::JSObject::hasInstance):
+ (KJS::JSObject::fillGetterPropertySlot):
+ (KJS::Error::create):
+ (KJS::constructEmptyObject):
+ * kjs/JSObject.h:
+ (KJS::GetterSetter::GetterSetter):
+ (KJS::GetterSetter::getter):
+ (KJS::GetterSetter::setGetter):
+ (KJS::GetterSetter::setter):
+ (KJS::GetterSetter::setSetter):
+ * kjs/JSValue.cpp:
+ (KJS::JSCell::deleteProperty):
+ (KJS::call):
+ (KJS::construct):
+ * kjs/JSValue.h:
+ * kjs/MathObject.cpp:
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/MathObject.h:
+ * kjs/NumberObject.cpp:
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncValueOf):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberConstructor::NumberConstructor):
+ (KJS::constructWithNumberConstructor):
+ (KJS::NumberConstructor::getConstructData):
+ (KJS::callNumberConstructor):
+ (KJS::NumberConstructor::getCallData):
+ (KJS::constructNumber):
+ (KJS::constructNumberFromImmediateNumber):
+ * kjs/NumberObject.h:
+ (KJS::NumberObject::classInfo):
+ (KJS::NumberConstructor::classInfo):
+ * kjs/PropertySlot.cpp:
+ (KJS::PropertySlot::functionGetter):
+ * kjs/RegExpObject.cpp:
+ (KJS::regExpProtoFuncTest):
+ (KJS::regExpProtoFuncExec):
+ (KJS::regExpProtoFuncCompile):
+ (KJS::regExpProtoFuncToString):
+ (KJS::callRegExpObject):
+ (KJS::RegExpObject::getCallData):
+ (KJS::constructRegExp):
+ (KJS::constructWithRegExpConstructor):
+ (KJS::RegExpConstructor::getConstructData):
+ (KJS::callRegExpConstructor):
+ (KJS::RegExpConstructor::getCallData):
+ * kjs/RegExpObject.h:
+ (KJS::RegExpConstructor::classInfo):
+ * kjs/Shell.cpp:
+ (GlobalObject::GlobalObject):
+ (functionPrint):
+ (functionDebug):
+ (functionGC):
+ (functionVersion):
+ (functionRun):
+ (functionLoad):
+ (functionReadline):
+ (functionQuit):
+ * kjs/date_object.cpp:
+ (KJS::gmtoffset):
+ (KJS::formatLocaleDate):
+ (KJS::fillStructuresUsingDateArgs):
+ (KJS::DateInstance::getTime):
+ (KJS::DateInstance::getUTCTime):
+ (KJS::DateConstructor::DateConstructor):
+ (KJS::constructDate):
+ (KJS::DateConstructor::getConstructData):
+ (KJS::callDate):
+ (KJS::DateConstructor::getCallData):
+ (KJS::dateParse):
+ (KJS::dateNow):
+ (KJS::dateUTC):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetMilliSeconds):
+ (KJS::dateProtoFuncSetUTCMilliseconds):
+ (KJS::dateProtoFuncSetSeconds):
+ (KJS::dateProtoFuncSetUTCSeconds):
+ (KJS::dateProtoFuncSetMinutes):
+ (KJS::dateProtoFuncSetUTCMinutes):
+ (KJS::dateProtoFuncSetHours):
+ (KJS::dateProtoFuncSetUTCHours):
+ (KJS::dateProtoFuncSetDate):
+ (KJS::dateProtoFuncSetUTCDate):
+ (KJS::dateProtoFuncSetMonth):
+ (KJS::dateProtoFuncSetUTCMonth):
+ (KJS::dateProtoFuncSetFullYear):
+ (KJS::dateProtoFuncSetUTCFullYear):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/date_object.h:
+ (KJS::DateInstance::internalNumber):
+ (KJS::DateInstance::classInfo):
+ * kjs/error_object.cpp:
+ (KJS::errorProtoFuncToString):
+ (KJS::constructError):
+ (KJS::constructWithErrorConstructor):
+ (KJS::ErrorConstructor::getConstructData):
+ (KJS::callErrorConstructor):
+ (KJS::ErrorConstructor::getCallData):
+ (KJS::NativeErrorConstructor::construct):
+ (KJS::constructWithNativeErrorConstructor):
+ (KJS::NativeErrorConstructor::getConstructData):
+ (KJS::callNativeErrorConstructor):
+ (KJS::NativeErrorConstructor::getCallData):
+ * kjs/error_object.h:
+ (KJS::NativeErrorConstructor::classInfo):
+ * kjs/internal.cpp:
+ (KJS::JSNumberCell::toObject):
+ (KJS::JSNumberCell::toThisObject):
+ (KJS::GetterSetter::mark):
+ (KJS::GetterSetter::toPrimitive):
+ (KJS::GetterSetter::toBoolean):
+ (KJS::GetterSetter::toNumber):
+ (KJS::GetterSetter::toString):
+ (KJS::GetterSetter::toObject):
+ (KJS::InternalFunction::InternalFunction):
+ (KJS::InternalFunction::implementsHasInstance):
+ * kjs/lookup.h:
+ (KJS::HashEntry::):
+ * kjs/nodes.cpp:
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::makeFunction):
+ * kjs/object_object.cpp:
+ (KJS::objectProtoFuncValueOf):
+ (KJS::objectProtoFuncHasOwnProperty):
+ (KJS::objectProtoFuncIsPrototypeOf):
+ (KJS::objectProtoFuncDefineGetter):
+ (KJS::objectProtoFuncDefineSetter):
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ (KJS::objectProtoFuncPropertyIsEnumerable):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ (KJS::ObjectConstructor::ObjectConstructor):
+ (KJS::constructObject):
+ (KJS::constructWithObjectConstructor):
+ (KJS::ObjectConstructor::getConstructData):
+ (KJS::callObjectConstructor):
+ (KJS::ObjectConstructor::getCallData):
+ * kjs/object_object.h:
+ * kjs/string_object.cpp:
+ (KJS::replace):
+ (KJS::stringProtoFuncToString):
+ (KJS::stringProtoFuncValueOf):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::stringFromCharCode):
+ (KJS::StringConstructor::StringConstructor):
+ (KJS::constructWithStringConstructor):
+ (KJS::StringConstructor::getConstructData):
+ (KJS::callStringConstructor):
+ (KJS::StringConstructor::getCallData):
+ * kjs/string_object.h:
+
+2008-06-23 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19716: REGRESSION (SquirrelFish): Reproducible crash after entering a username at mint.com
+ <https://bugs.webkit.org/show_bug.cgi?id=19716>
+
+ When unwinding callframes for exceptions, check whether the callframe
+ was created by a reentrant native call to JavaScript after tearing off
+ the local variables instead of before.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame):
+
+2008-06-23 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Get testapi passing again in a debug build.
+
+ * API/testapi.c:
+ (main): Update the expected output of calling JSValueMakeString on a function object.
+
+2008-06-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Print a blank line when exiting the jsc interactive mode to ensure that the shell
+ prompt will start on a new line.
+
+ * kjs/Shell.cpp:
+ (runInteractive):
+
+2008-06-21 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Sam Weinig.
+
+ Tweak the paths of the items in the "tests" group to clean things up a little.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-06-21 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Sam Weinig.
+
+ Fix jsc to link against libedit.dylib rather than libedit.2.dylib.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-06-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Copy the JavaScriptCore shell (jsc) into JavaScriptCore.framework so that it will
+ be included in nightly builds.
+ https://bugs.webkit.org/show_bug.cgi?id=19691
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-06-21 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Mark Rowe.
+
+ Fix the build for non-Mac Darwin platforms by disabling their support
+ for readline in the JavaScript shell.
+
+ * kjs/config.h:
+
+2008-06-20 Timothy Hatcher <timothy@apple.com>
+
+ Use member function pointers for the Profile::forEach function.
+ Eliminating a few static functions and simplified things a little.
+
+ Reviewed by Alexey Proskuryakov.
+
+ * JavaScriptCore.exp: Change the symbol for forEach.
+ * profiler/Profile.cpp:
+ (KJS::Profile::forEach): Use a member function pointer.
+ * profiler/Profile.h:
+ (KJS::Profile::sortTotalTimeDescending): Pass a function pointer.
+ (KJS::Profile::sortTotalTimeAscending): Ditto.
+ (KJS::Profile::sortSelfTimeDescending): Ditto.
+ (KJS::Profile::sortSelfTimeAscending): Ditto.
+ (KJS::Profile::sortCallsDescending): Ditto.
+ * profiler/ProfileNode.h:
+ (KJS::ProfileNode::sortTotalTimeDescending): No longer static.
+ (KJS::ProfileNode::sortTotalTimeAscending): Ditto.
+ (KJS::ProfileNode::sortSelfTimeDescending): Ditto.
+ (KJS::ProfileNode::sortSelfTimeAscending): Ditto.
+ (KJS::ProfileNode::sortCallsDescending): Ditto.
+
+2008-06-20 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Remove unused destructors.
+
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+
+2008-06-20 Timothy Hatcher <timothy@apple.com>
+
+ Fixed an ASSERT(m_actualSelfTime <= m_actualTotalTime) when starting
+ and stopping a profile from the Develop menu. Also prevents
+ inserting an incorrect parent node as the new head after profiling
+ is stopped from the Develop menu.
+
+ Reviewed by Dan Bernstein.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::stopProfiling): If the current node is already the head
+ then there is no more need to record future nodes in didExecute.
+ (KJS::Profile::didExecute): Move the code of setupCurrentNodeAsStopped
+ into here since this was the only caller. When setting the total time
+ keep any current total time while adding the self time of the head.
+ (KJS::Profile::setupCurrentNodeAsStopped): Removed.
+ * profiler/Profile.h: Removed setupCurrentNodeAsStopped.
+
+2008-06-20 Kevin Ollivier <kevino@theolliviers.com>
+
+ !USE(MULTIPLE_THREADS) on Darwin build fix
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading):
+ * kjs/collector.h:
+
+2008-06-20 Kevin McCullough <kmccullough@apple.com>
+
+ -Leopard Build Fix.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::removeProfileStart):
+ (KJS::Profile::removeProfileEnd):
+
+2008-06-20 Kevin McCullough <kmccullough@apple.com>
+
+ Just giving credit.
+
+ * ChangeLog:
+
+2008-06-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim and Dan.
+
+ <rdar://problem/6024846> JSProfiler: ASSERT hit in Profiler.
+ - Because InspectorController can call startProfiling() and
+ stopProfiling() we cannot assert that console.profile() and
+ console.profileEnd() will be in the profile tree.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::removeProfileStart):
+ (KJS::Profile::removeProfileEnd):
+
+2008-06-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5958770> JSProfiler: Time incorrectly given to (idle)
+ if profiling is started and finished within the same function. (19230)
+ - Now we profile one more stack frame up from the last frame to allocate
+ the time spent in it, if it exists.
+
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp: We need to let the profiler know when the JS program
+ has finished since that is what will actually stop the profiler instead
+ of just calling stopProfiling().
+ (KJS::Machine::execute):
+ * profiler/Profile.cpp:
+ (KJS::Profile::create): Moved from Profile.h since it was getting pretty
+ long.
+ (KJS::Profile::Profile): We now have a client, which is a listener who
+ we will return this profile to, once it has actually finished.
+ (KJS::Profile::stopProfiling): Instead of fully stopping the profiler
+ here, we set the flag and keep it profiling in the background.
+ (KJS::Profile::didFinishAllExecution): This is where the profiler
+ actually finishes and creates the (idle) node if one should be made.
+ (KJS::Profile::removeProfileStart): Don't use m_currentNode since it is
+ needed by the profiler as it runs silently in the background.
+ (KJS::Profile::removeProfileEnd): Ditto.
+ (KJS::Profile::willExecute): Don't profile new functions if we have
+ stopped profiling.
+ (KJS::Profile::didExecute): Only record one more return as all the
+ remaining time will be attributed to that function.
+ (KJS::Profile::setupCurrentNodeAsStopped): Sets the current node's time.
+ * profiler/Profile.h: Added functions and variables for the above
+ changes.
+ (KJS::Profile::client):
+ * profiler/ProfileNode.h:
+ (KJS::CallIdentifier::toString): Debug method.
+ * profiler/Profiler.cpp: Added support for the ProfilerClient.
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::stopProfiling): No longer return sthe profile.
+ (KJS::Profiler::didFinishAllExecution): Now returns the profile to the
+ client instead of stopProfiling.
+ * profiler/Profiler.h:
+ (KJS::ProfilerClient::~ProfilerClient): Clients will implement this
+ interface.
+
+2008-06-19 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ Surpress compiler warning (int vs unsigned comparison).
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::toLower):
+
+2008-06-19 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Timothy Hatcher.
+
+ Introduce compiler define for MinGW, to have COMPILER(MINGW).
+
+ * wtf/Platform.h:
+
+2008-06-19 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Make Machine per-JSGlobalData.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitOpcode):
+ * VM/Machine.cpp:
+ (KJS::callEval):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::throwException):
+ (KJS::Machine::execute):
+ (KJS::Machine::debug):
+ * VM/Machine.h:
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::evaluate):
+ * kjs/DebuggerCallFrame.h:
+ (KJS::DebuggerCallFrame::DebuggerCallFrame):
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/ExecState.h:
+ (KJS::ExecState::machine):
+ * kjs/JSFunction.cpp:
+ (KJS::JSFunction::callAsFunction):
+ (KJS::JSFunction::argumentsGetter):
+ (KJS::JSFunction::callerGetter):
+ (KJS::JSFunction::construct):
+ (KJS::globalFuncEval):
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ * kjs/JSGlobalData.h:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-06-19 Alp Toker <alp@nuanti.com>
+
+ GTK+/autotools build fix. JSGlobalObject.cpp in now in
+ AllInOneFile.cpp and shouldn't be built separately.
+
+ * GNUmakefile.am:
+
+2008-06-19 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Get rid of some threadInstance calls.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+ * kjs/Shell.cpp:
+ (jscmain):
+
+2008-06-19 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Sam.
+
+ Fix an assertion failure at startup.
+
+ * kjs/JSObject.h: (KJS::JSObject::JSObject): Allow jsNull prototype in an assertion (I had
+ it fixed in a wrong copy of the file, so I wasn't getting the failure).
+
+2008-06-19 Alexey Proskuryakov <ap@webkit.org>
+
+ Build fix.
+
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap):
+ (KJS::allocateBlock):
+ * kjs/collector.h:
+ No, #if PLATFORM(UNIX) was not right. I've just moved the unsafe initialization back for now,
+ as the platforms that use that code path do not use multiple threads yet.
+
+2008-06-19 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows and Qt build fixes.
+
+ * kjs/collector.h:
+ * kjs/collector.cpp:
+ (KJS::Heap::Heap):
+ Wrapped m_pagesize in #if PLATFORM(UNIX), which should better match the sequence of #elifs
+ in allocateBlock(). Changed MIN_ARRAY_SIZE to be explicitly size_t, as this type is different
+ on different platforms.
+
+2008-06-17 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Prepare JavaScript heap for being per-thread.
+
+ * kjs/ExecState.h: Shuffle includes, making it possible to include ExecState.h in JSValue.h.
+ (KJS::ExecState::heap): Added an accessor.
+
+ * API/JSBase.cpp: (JSGarbageCollect): Collect both shared and per-thread heaps.
+
+ * API/JSContextRef.cpp: (JSGlobalContextCreate): When allocating JSGlobalObject, indicate
+ that it belongs to a shared heap.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/AllInOneFile.cpp:
+ Moved JSGlobalObject.cpp to AllInOneFile, as a build fix for inlineAllocate magic.
+
+ * VM/CodeGenerator.h: (KJS::CodeGenerator::globalExec): Added an accessor (working via
+ m_scopeChain).
+
+ * VM/RegisterFile.h:
+ (KJS::RegisterFile::mark):
+ * VM/RegisterFileStack.h:
+ (KJS::RegisterFileStack::mark):
+ Made these pseudo-mark functions take Heap*.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading): Initialize heap introspector.
+
+ * kjs/JSGlobalData.h: Added Heap to the structure.
+
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData): Initialize Heap.
+ (KJS::JSGlobalData::sharedInstance): Added a method to access shared global data instance
+ for legacy clients.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject): Changed to work with per-thread head; fixed list
+ maintenance logic.
+ (KJS::JSGlobalObject::init): Changed to work with per-thread head.
+ (KJS::JSGlobalObject::put): Assert that a cross-heap operation is not being attempted.
+ (KJS::JSGlobalObject::reset): Pass ExecState* where now required.
+ (KJS::JSGlobalObject::mark): Pass the current heap to RegisterFileStack::mark.
+ (KJS::JSGlobalObject::operator new): Overload operator new to use per-thread or shared heap.
+ * kjs/JSGlobalObject.h: Removed static s_head member.
+
+ * kjs/PropertyMap.h: (KJS::PropertyMap::PropertyMap): Removed unused SavedProperty.
+
+ * kjs/collector.h: Turned Collector into an actual object with its own data, renamed to Heap.
+ (KJS::Heap::initializeHeapIntrospector): Added.
+ (KJS::Heap::heap): Added a method to determine which heap a JSValue is in, if any.
+ (KJS::Heap::allocate): Made non-static.
+ (KJS::Heap::inlineAllocateNumber): Ditto.
+ (KJS::Heap::markListSet): Ditto.
+ (KJS::Heap::cellBlock): Ditto.
+ (KJS::Heap::cellOffset): Ditto.
+ (KJS::Heap::isCellMarked): Ditto.
+ (KJS::Heap::markCell): Ditto.
+ (KJS::Heap::reportExtraMemoryCost): Ditto.
+ (KJS::CollectorBlock): Added a back-reference to Heap for Heap::heap() method.
+ (KJS::SmallCellCollectorBlock): Ditto.
+
+ * kjs/collector.cpp: Changed MIN_ARRAY_SIZE to a #define to avoid a PIC branch. Removed
+ main thread related machinery.
+ (KJS::Heap::Heap): Initialize the newly added data members.
+ (KJS::allocateBlock): Marked NEVER_INLINE, as this is a rare case that uses a PIC branch.
+ Moved static pagesize to the class to make it safely initialized.
+ (KJS::Heap::heapAllocate): Initialize heap back reference after a new block is allocated.
+ (KJS::Heap::registerThread): Removed introspector initialization, as it is now performed
+ in InitializeThreading.cpp.
+ (KJS::Heap::markOtherThreadConservatively): Assert that the "other thread" case only occurs
+ for legacy clients using a shared heap.
+ (KJS::Heap::markStackObjectsConservatively): Moved fastMallocForbid/Allow down here, since
+ it doesn't need to be forbidden during other GC phases.
+
+ * kjs/JSImmediate.h:
+ (KJS::jsUndefined):
+ (KJS::jsNull):
+ (KJS::jsBoolean):
+ Moved from JSvalue.h, to make these usable in files that cannot include JSValue.h (such
+ as list.h).
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::staticFunctionGetter):
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeConstructor):
+ (JSObjectMakeFunction):
+ * API/JSValueRef.cpp:
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ * JavaScriptCore.exp:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitLoad):
+ * VM/JSPropertyNameIterator.cpp:
+ (KJS::JSPropertyNameIterator::create):
+ (KJS::JSPropertyNameIterator::next):
+ * VM/Machine.cpp:
+ (KJS::jsAddSlowCase):
+ (KJS::jsAdd):
+ (KJS::jsTypeStringForValue):
+ (KJS::scopeChainForCall):
+ (KJS::Machine::throwException):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ (KJS::Machine::retrieveArguments):
+ * kjs/ArrayPrototype.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ (KJS::ArrayConstructor::ArrayConstructor):
+ (KJS::ArrayConstructor::construct):
+ (KJS::ArrayConstructor::callAsFunction):
+ * kjs/BooleanObject.cpp:
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::BooleanConstructor::BooleanConstructor):
+ (KJS::BooleanConstructor::construct):
+ * kjs/FunctionPrototype.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ (KJS::functionProtoFuncToString):
+ (KJS::FunctionConstructor::FunctionConstructor):
+ (KJS::FunctionConstructor::construct):
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject):
+ * kjs/JSArray.cpp:
+ (KJS::JSArray::JSArray):
+ (KJS::JSArray::lengthGetter):
+ * kjs/JSFunction.cpp:
+ (KJS::JSFunction::lengthGetter):
+ (KJS::JSFunction::construct):
+ (KJS::Arguments::Arguments):
+ (KJS::encode):
+ (KJS::decode):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toObject):
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::registerThread):
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::put):
+ (KJS::JSObject::defineGetter):
+ (KJS::JSObject::defineSetter):
+ (KJS::Error::create):
+ * kjs/JSObject.h:
+ (KJS::JSObject::putDirect):
+ * kjs/JSString.h:
+ (KJS::JSString::JSString):
+ * kjs/JSValue.cpp:
+ (KJS::JSCell::operator new):
+ (KJS::jsString):
+ (KJS::jsOwnedString):
+ * kjs/JSValue.h:
+ (KJS::JSNumberCell::operator new):
+ (KJS::jsNumberCell):
+ (KJS::jsNaN):
+ (KJS::jsNumber):
+ (KJS::JSCell::marked):
+ (KJS::JSCell::mark):
+ (KJS::JSValue::toJSNumber):
+ * kjs/MathObject.cpp:
+ (KJS::MathObject::getValueProperty):
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/NumberObject.cpp:
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberConstructor::NumberConstructor):
+ (KJS::NumberConstructor::getValueProperty):
+ (KJS::NumberConstructor::construct):
+ (KJS::NumberConstructor::callAsFunction):
+ * kjs/RegExpObject.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::regExpProtoFuncToString):
+ (KJS::RegExpObject::getValueProperty):
+ (KJS::RegExpConstructor::RegExpConstructor):
+ (KJS::RegExpMatchesArray::fillArrayInstance):
+ (KJS::RegExpConstructor::arrayOfMatches):
+ (KJS::RegExpConstructor::getBackref):
+ (KJS::RegExpConstructor::getLastParen):
+ (KJS::RegExpConstructor::getLeftContext):
+ (KJS::RegExpConstructor::getRightContext):
+ (KJS::RegExpConstructor::getValueProperty):
+ (KJS::RegExpConstructor::construct):
+ * kjs/RegExpObject.h:
+ * kjs/Shell.cpp:
+ (GlobalObject::GlobalObject):
+ (functionGC):
+ (functionRun):
+ (functionReadline):
+ (jscmain):
+ * kjs/date_object.cpp:
+ (KJS::formatLocaleDate):
+ (KJS::DatePrototype::DatePrototype):
+ (KJS::DateConstructor::DateConstructor):
+ (KJS::DateConstructor::construct):
+ (KJS::DateConstructor::callAsFunction):
+ (KJS::DateFunction::DateFunction):
+ (KJS::DateFunction::callAsFunction):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::errorProtoFuncToString):
+ (KJS::ErrorConstructor::ErrorConstructor):
+ (KJS::ErrorConstructor::construct):
+ (KJS::NativeErrorPrototype::NativeErrorPrototype):
+ (KJS::NativeErrorConstructor::NativeErrorConstructor):
+ (KJS::NativeErrorConstructor::construct):
+ * kjs/identifier.h:
+ * kjs/internal.cpp:
+ (KJS::StringObject::create):
+ (KJS::JSString::lengthGetter):
+ (KJS::JSString::indexGetter):
+ (KJS::JSString::indexNumericPropertyGetter):
+ * kjs/interpreter.cpp:
+ * kjs/list.cpp:
+ (KJS::ArgList::slowAppend):
+ * kjs/list.h:
+ * kjs/lookup.h:
+ (KJS::staticFunctionGetter):
+ (KJS::cacheGlobalObject):
+ * kjs/nodes.cpp:
+ (KJS::Node::emitThrowError):
+ (KJS::StringNode::emitCode):
+ (KJS::ArrayNode::emitCode):
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::makeFunction):
+ * kjs/nodes.h:
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ (KJS::ObjectConstructor::ObjectConstructor):
+ (KJS::ObjectConstructor::construct):
+ * kjs/protect.h:
+ (KJS::gcProtect):
+ (KJS::gcUnprotect):
+ * kjs/string_object.cpp:
+ (KJS::StringObject::StringObject):
+ (KJS::StringPrototype::StringPrototype):
+ (KJS::replace):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::StringConstructor::StringConstructor):
+ (KJS::StringConstructor::construct):
+ (KJS::StringConstructor::callAsFunction):
+ (KJS::StringConstructorFunction::StringConstructorFunction):
+ (KJS::StringConstructorFunction::callAsFunction):
+ * kjs/string_object.h:
+ (KJS::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):
+ * kjs/ustring.h:
+ Updated for the above changes.
+
+2008-06-17 Timothy Hatcher <timothy@apple.com>
+
+ Added a type to DebuggerCallFrame so the under interface can
+ distinguish anonymous functions and program call frames.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19585
+
+ Reviewed by Geoff Garen.
+
+ * JavaScriptCore.exp: Export the DebuggerCallFrame::type symbol.
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::type): Added.
+ * kjs/DebuggerCallFrame.h:
+
+2008-06-17 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Tim H.
+
+ Remove bogus ASSERT which tripped every time for those who use PAC files.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+
+2008-06-17 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ <rdar://problem/5951534> JSProfiler: Don't profile console.profile()
+ or console.profileEnd()
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::stopProfiling): Moved the creation of the (idle) node to
+ the Profile (not ProfileNode). This makes sense since the Profile
+ should be the one to modify the profile tree. Also each stopProfiling()
+ does not need to check if it's the head node anymore. Also fixed an
+ oddity where I was using willExecute to create the node.
+ (KJS::Profile::removeProfileStart): Removes the call to console.profile
+ that started this profile.
+ (KJS::Profile::removeProfileEnd): Removes the call to console.profileEnd
+ that ended this profile.
+ * profiler/Profile.h:
+ * profiler/ProfileNode.cpp: Moved the creation of the (idle) node to
+ the Profile object.
+ (KJS::ProfileNode::stopProfiling):
+ * profiler/ProfileNode.h: Added some helper functions and whitespace to
+ facilitate readability and the removal of profile() and profileEnd()
+ from the Profile tree.
+ (KJS::CallIdentifier::operator const char* ):
+ (KJS::ProfileNode::firstChild):
+ (KJS::ProfileNode::lastChild):
+ (KJS::ProfileNode::removeChild):
+ (KJS::ProfileNode::toString):
+
+2008-06-17 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Rubber stamped by Adam Roben.
+
+ Include JSGlobalObject.h to fix the build.
+
+ * kjs/ScopeChain.cpp:
+
+2008-06-17 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Reduce code duplication in emitReadModifyAssignment().
+
+ * kjs/nodes.cpp:
+ (KJS::emitReadModifyAssignment):
+
+2008-06-17 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Sort includes alphabetically.
+
+ * kjs/nodes.cpp:
+
+2008-06-16 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 19596: LEAK: Gmail leaks SegmentedVector<RegisterID>
+ <https://bugs.webkit.org/show_bug.cgi?id=19596>
+
+ When growing SegmentedVector, we start adding segments at the position
+ of the last segment, overwriting it. The destructor frees allocated
+ segments starting at the segment of index 1, because the segment of
+ index 0 is assumed to be the initial inline segment. This causes a leak
+ of the segment that is referenced by index 0. Modifying grow() so that
+ it starts adding segments at the position after the last segment fixes
+ the leak.
+
+ Since the initial segment is a special case in the lookup code, this
+ bug never manifested itself via incorrect results.
+
+ * VM/SegmentedVector.h:
+ (KJS::SegmentedVector::grow):
+
+2008-06-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Alexey.
+
+ - removed nearly unused types.h and LocalStorageEntry.h headers
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/ExecState.h:
+ * kjs/LocalStorageEntry.h: Removed.
+ * kjs/RegExpObject.cpp:
+ * kjs/error_object.cpp:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/types.h: Removed.
+
+2008-06-16 Alp Toker <alp@nuanti.com>
+
+ Rubber-stamped by Geoff.
+
+ Change c++ to c in minidom and testapi emacs mode line comments.
+
+ * API/Node.h:
+ * API/NodeList.c:
+ * API/NodeList.h:
+ * API/testapi.c:
+
+2008-06-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Trying to fix Windows build.
+
+ * kjs/PropertyNameArray.h:
+ * kjs/identifier.cpp:
+ Include ExecState.h
+
+2008-06-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Slight cleanup to the SymbolTableEntry class.
+
+ Renamed isEmpty to isNull, since we usually use "empty" to mean "holds
+ the valid, empty value", and "null" to mean "holds no value".
+
+ Changed an "== 0" to a "!", to match our style guidelines.
+
+ Added some ASSERTs to verify the (possibly questionable) assumption that
+ all register indexes will have their high two bits set. Also clarified a
+ comment to make that assumption clear.
+
+2008-06-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Initialize functionQueueMutex in a safe manner.
+
+ * wtf/MainThread.cpp:
+ (WTF::functionQueueMutex): Made it an AtomicallyInitializedStatic.
+
+ (WTF::dispatchFunctionsFromMainThread):
+ (WTF::setMainThreadCallbacksPaused):
+ Assert that the current thread is main, meaning that the callbacksPaused static can be
+ accessed.
+
+2008-06-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Make Identifier construction use an explicitly passed IdentifierTable.
+
+ No change on SunSpider total.
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::getOwnPropertySlot):
+ (KJS::::put):
+ (KJS::::deleteProperty):
+ (KJS::::getPropertyNames):
+ * API/JSObjectRef.cpp:
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeFunction):
+ (JSObjectHasProperty):
+ (JSObjectGetProperty):
+ (JSObjectSetProperty):
+ (JSObjectDeleteProperty):
+ (OpaqueJSPropertyNameArray::OpaqueJSPropertyNameArray):
+ (JSObjectCopyPropertyNames):
+ * JavaScriptCore.exp:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::registerForLocal):
+ (KJS::CodeGenerator::isLocal):
+ (KJS::CodeGenerator::addConstant):
+ (KJS::CodeGenerator::findScopedProperty):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::globalData):
+ (KJS::CodeGenerator::propertyNames):
+ * VM/JSPropertyNameIterator.cpp:
+ (KJS::JSPropertyNameIterator::create):
+ * VM/Machine.cpp:
+ (KJS::Machine::throwException):
+ (KJS::Machine::privateExecute):
+ * kjs/ArrayPrototype.cpp:
+ (KJS::ArrayConstructor::ArrayConstructor):
+ * kjs/BooleanObject.cpp:
+ (KJS::BooleanConstructor::BooleanConstructor):
+ * kjs/FunctionPrototype.cpp:
+ (KJS::FunctionConstructor::FunctionConstructor):
+ (KJS::FunctionConstructor::construct):
+ * kjs/JSArray.cpp:
+ (KJS::JSArray::inlineGetOwnPropertySlot):
+ (KJS::JSArray::put):
+ (KJS::JSArray::deleteProperty):
+ (KJS::JSArray::getPropertyNames):
+ * kjs/JSFunction.cpp:
+ (KJS::Arguments::Arguments):
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::getOwnPropertySlot):
+ (KJS::JSObject::put):
+ (KJS::JSObject::putWithAttributes):
+ (KJS::JSObject::deleteProperty):
+ (KJS::JSObject::findPropertyHashEntry):
+ (KJS::JSObject::getPropertyNames):
+ (KJS::Error::create):
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames):
+ * kjs/NumberObject.cpp:
+ (KJS::NumberConstructor::NumberConstructor):
+ * kjs/PropertyNameArray.cpp:
+ (KJS::PropertyNameArray::add):
+ * kjs/PropertyNameArray.h:
+ (KJS::PropertyNameArray::PropertyNameArray):
+ (KJS::PropertyNameArray::addKnownUnique):
+ * kjs/PropertySlot.h:
+ (KJS::PropertySlot::getValue):
+ * kjs/RegExpObject.cpp:
+ (KJS::RegExpConstructor::RegExpConstructor):
+ * kjs/ScopeChain.cpp:
+ (KJS::ScopeChainNode::print):
+ * kjs/Shell.cpp:
+ (GlobalObject::GlobalObject):
+ * kjs/date_object.cpp:
+ (KJS::DateConstructor::DateConstructor):
+ * kjs/error_object.cpp:
+ (KJS::ErrorConstructor::ErrorConstructor):
+ (KJS::NativeErrorConstructor::NativeErrorConstructor):
+ * kjs/grammar.y:
+ * kjs/identifier.cpp:
+ (KJS::Identifier::add):
+ (KJS::Identifier::addSlowCase):
+ * kjs/identifier.h:
+ (KJS::Identifier::Identifier):
+ (KJS::Identifier::from):
+ (KJS::Identifier::equal):
+ (KJS::Identifier::add):
+ (KJS::operator==):
+ (KJS::operator!=):
+ * kjs/internal.cpp:
+ (KJS::JSString::getOwnPropertySlot):
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::lex):
+ (KJS::Lexer::makeIdentifier):
+ * kjs/lexer.h:
+ * kjs/lookup.cpp:
+ (KJS::HashTable::createTable):
+ * kjs/lookup.h:
+ (KJS::HashTable::initializeIfNeeded):
+ (KJS::HashTable::entry):
+ (KJS::getStaticPropertySlot):
+ (KJS::getStaticFunctionSlot):
+ (KJS::getStaticValueSlot):
+ (KJS::lookupPut):
+ * kjs/object_object.cpp:
+ (KJS::objectProtoFuncHasOwnProperty):
+ (KJS::objectProtoFuncDefineGetter):
+ (KJS::objectProtoFuncDefineSetter):
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ (KJS::objectProtoFuncPropertyIsEnumerable):
+ (KJS::ObjectConstructor::ObjectConstructor):
+ * kjs/string_object.cpp:
+ (KJS::StringObject::getOwnPropertySlot):
+ (KJS::StringObject::getPropertyNames):
+ (KJS::StringConstructor::StringConstructor):
+ Just pass ExecState or JSGlobalData everywhere. Identifier construction is now always
+ explicit.
+
+ * kjs/nodes.cpp: (KJS::RegExpNode::emitCode): Here, Identifier was created from a non-literal
+ char*, which was incorrect, as that uses the pointer value as a key.
+
+2008-06-16 Thiago Macieira <tjmaciei@trolltech.com>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19577
+
+ Fix compilation in C++ environments where C99 headers are not present
+
+ The stdbool.h header is a C99 feature, defining the "_Bool" type as well as the
+ "true" and "false" constants. But it's completely unnecessary in C++ as the
+ language already defines the "bool" type and its two values.
+
+ * API/JSBase.h:
+ * API/JSContextRef.h:
+ * API/JSObjectRef.h:
+ * API/JSStringRef.h:
+ * API/JSValueRef.h:
+
+2008-06-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by John.
+
+ <rdar://problem/6012509> JSProfiler: %s are incorrect if you exclude a
+ top level node like (idle)
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::focus):
+ (KJS::Profile::exclude): Subtract the selfTime from the totalTime of the
+ head since its self time will only be non-zero when one of its children
+ were excluded. Since the head's totalTime is used to calculate %s when
+ its totalTime is the same as the sum of all its visible childrens' times
+ their %s will sum to 100%.
+
+2008-06-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the profiler.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::willExecute):
+
+2008-06-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+ profiler.
+ - Remove the last of the uses of recursion in the profiler.
+
+ * JavaScriptCore.exp: Export the new function's signature.
+ * profiler/Profile.cpp:
+ (KJS::calculateVisibleTotalTime): Added a new static method for
+ recalculating the visibleTotalTime of methods after focus has changed
+ which are visible.
+ (KJS::stopProfiling):
+ (KJS::Profile::focus): Implemented focus without recursion.
+ * profiler/Profile.h: Moved implementation into the definition file.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::traverseNextNodePreOrder): Added an argument for
+ whether or not to process the children nodes, this allows focus to skip
+ sub trees which have been set as not visible.
+ (KJS::ProfileNode::calculateVisibleTotalTime): This function set's a
+ node's total visible time to the sum of its self time and its children's
+ total times.
+ (KJS::ProfileNode::focus): Implemented focus without recursion.
+ * profiler/ProfileNode.h:
+ (KJS::CallIdentifier::operator!= ):
+ (KJS::ProfileNode::setActualTotalTime): Expanded setting the total time
+ so that focus could modify only the visible total time.
+ (KJS::ProfileNode::setVisibleTotalTime):
+
+2008-06-16 Christian Dywan <christian@twotoasts.de>
+
+ Reviewed by Sam.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19552
+ JavaScriptCore headers use C++ style comments
+
+ Replace all C++ style comments with C style multiline
+ comments and remove all "mode" lines.
+
+ * API/JSBase.h:
+ * API/JSClassRef.h:
+ * API/JSContextRef.h:
+ * API/JSObjectRef.h:
+ * API/JSStringRef.h:
+ * API/JSStringRefBSTR.h:
+ * API/JSStringRefCF.h:
+ * API/JSValueRef.h:
+ * API/JavaScript.h:
+ * API/JavaScriptCore.h:
+
+2008-06-16 Christian Dywan <christian@twotoasts.de>
+
+ Reviewed by Sam.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19557
+ (JavaScriptCore) minidom uses C++ style comments
+
+ Use only C style comments in minidom sources
+
+ * API/JSNode.c:
+ (JSNode_appendChild):
+ (JSNode_removeChild):
+ * API/JSNode.h:
+ * API/JSNodeList.c:
+ (JSNodeList_getProperty):
+ * API/JSNodeList.h:
+ * API/Node.c:
+ * API/Node.h:
+ * API/NodeList.c:
+ (NodeList_new):
+ (NodeList_item):
+ * API/NodeList.h:
+ * API/minidom.c:
+ (createStringWithContentsOfFile):
+ * wtf/Assertions.h:
+ * wtf/UnusedParam.h:
+
+2008-06-16 Adriaan de Groot <groot@kde.org>
+
+ Reviewed by Simon.
+
+ Fix compilation on Solaris
+
+ On some systems, munmap takes a char* instead of a void* (contrary to POSIX and
+ Single Unix Specification). Since you can always convert from char* to void*
+ but not vice-versa, do the casting to char*.
+
+ * kjs/collector.cpp:
+ (KJS::allocateBlock):
+ (KJS::freeBlock):
+
+2008-06-16 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Make a UnaryOpNode class to reduce boilerplate code for UnaryPlusNode,
+ NegateNode, BitwiseNotNode, and LogicalNotNode.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::emitToJSNumber):
+ * kjs/nodes.cpp:
+ (KJS::UnaryOpNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::UnaryOpNode::UnaryOpNode):
+ (KJS::UnaryPlusNode::):
+ (KJS::NegateNode::):
+ (KJS::NegateNode::precedence):
+ (KJS::BitwiseNotNode::):
+ (KJS::BitwiseNotNode::precedence):
+ (KJS::LogicalNotNode::):
+ (KJS::LogicalNotNode::precedence):
+
+2008-06-16 Jan Michael Alonzo <jmalonzo@webkit.org>
+
+ Gtk build fix
+
+ * GNUmakefile.am:
+
+2008-06-15 Darin Adler <darin@apple.com>
+
+ - rename KJS::List to KJS::ArgList
+
+ * API/JSCallbackConstructor.cpp:
+ (KJS::JSCallbackConstructor::construct):
+ * API/JSCallbackConstructor.h:
+ * API/JSCallbackFunction.cpp:
+ (KJS::JSCallbackFunction::callAsFunction):
+ * API/JSCallbackFunction.h:
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::construct):
+ (KJS::::callAsFunction):
+ * API/JSObjectRef.cpp:
+ (JSObjectMakeFunction):
+ (JSObjectCallAsFunction):
+ (JSObjectCallAsConstructor):
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * kjs/ArrayPrototype.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncReverse):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSort):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ (KJS::ArrayConstructor::construct):
+ (KJS::ArrayConstructor::callAsFunction):
+ * kjs/ArrayPrototype.h:
+ * kjs/BooleanObject.cpp:
+ (KJS::booleanProtoFuncToString):
+ (KJS::booleanProtoFuncValueOf):
+ (KJS::BooleanConstructor::construct):
+ (KJS::BooleanConstructor::callAsFunction):
+ * kjs/BooleanObject.h:
+ * kjs/CommonIdentifiers.h:
+ * kjs/ExecState.h:
+ (KJS::ExecState::emptyList):
+ * kjs/FunctionPrototype.cpp:
+ (KJS::FunctionPrototype::callAsFunction):
+ (KJS::functionProtoFuncToString):
+ (KJS::functionProtoFuncApply):
+ (KJS::functionProtoFuncCall):
+ (KJS::FunctionConstructor::construct):
+ (KJS::FunctionConstructor::callAsFunction):
+ * kjs/FunctionPrototype.h:
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject):
+ * kjs/JSArray.cpp:
+ (KJS::JSArray::JSArray):
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key):
+ * kjs/JSArray.h:
+ * kjs/JSFunction.cpp:
+ (KJS::JSFunction::callAsFunction):
+ (KJS::JSFunction::construct):
+ (KJS::IndexToNameMap::IndexToNameMap):
+ (KJS::Arguments::Arguments):
+ (KJS::encode):
+ (KJS::decode):
+ (KJS::globalFuncEval):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncIsNaN):
+ (KJS::globalFuncIsFinite):
+ (KJS::globalFuncDecodeURI):
+ (KJS::globalFuncDecodeURIComponent):
+ (KJS::globalFuncEncodeURI):
+ (KJS::globalFuncEncodeURIComponent):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ (KJS::globalFuncKJSPrint):
+ (KJS::PrototypeFunction::callAsFunction):
+ (KJS::PrototypeReflexiveFunction::callAsFunction):
+ * kjs/JSFunction.h:
+ * kjs/JSGlobalData.h:
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toObject):
+ * kjs/JSNotAnObject.cpp:
+ (KJS::JSNotAnObject::construct):
+ (KJS::JSNotAnObject::callAsFunction):
+ * kjs/JSNotAnObject.h:
+ * kjs/JSObject.cpp:
+ (KJS::JSObject::put):
+ (KJS::JSObject::construct):
+ (KJS::JSObject::callAsFunction):
+ (KJS::Error::create):
+ * kjs/JSObject.h:
+ * kjs/MathObject.cpp:
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/MathObject.h:
+ * kjs/NumberObject.cpp:
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncValueOf):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberConstructor::construct):
+ (KJS::NumberConstructor::callAsFunction):
+ * kjs/NumberObject.h:
+ * kjs/RegExpObject.cpp:
+ (KJS::regExpProtoFuncTest):
+ (KJS::regExpProtoFuncExec):
+ (KJS::regExpProtoFuncCompile):
+ (KJS::regExpProtoFuncToString):
+ (KJS::RegExpObject::match):
+ (KJS::RegExpObject::test):
+ (KJS::RegExpObject::exec):
+ (KJS::RegExpObject::callAsFunction):
+ (KJS::RegExpConstructor::construct):
+ (KJS::RegExpConstructor::callAsFunction):
+ * kjs/RegExpObject.h:
+ * kjs/Shell.cpp:
+ (functionPrint):
+ (functionDebug):
+ (functionGC):
+ (functionVersion):
+ (functionRun):
+ (functionLoad):
+ (functionReadline):
+ (functionQuit):
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ * kjs/collector.h:
+ (KJS::Collector::markListSet):
+ * kjs/date_object.cpp:
+ (KJS::formatLocaleDate):
+ (KJS::fillStructuresUsingTimeArgs):
+ (KJS::fillStructuresUsingDateArgs):
+ (KJS::DateConstructor::construct):
+ (KJS::DateConstructor::callAsFunction):
+ (KJS::DateFunction::callAsFunction):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetMilliSeconds):
+ (KJS::dateProtoFuncSetUTCMilliseconds):
+ (KJS::dateProtoFuncSetSeconds):
+ (KJS::dateProtoFuncSetUTCSeconds):
+ (KJS::dateProtoFuncSetMinutes):
+ (KJS::dateProtoFuncSetUTCMinutes):
+ (KJS::dateProtoFuncSetHours):
+ (KJS::dateProtoFuncSetUTCHours):
+ (KJS::dateProtoFuncSetDate):
+ (KJS::dateProtoFuncSetUTCDate):
+ (KJS::dateProtoFuncSetMonth):
+ (KJS::dateProtoFuncSetUTCMonth):
+ (KJS::dateProtoFuncSetFullYear):
+ (KJS::dateProtoFuncSetUTCFullYear):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/date_object.h:
+ * kjs/debugger.h:
+ * kjs/error_object.cpp:
+ (KJS::errorProtoFuncToString):
+ (KJS::ErrorConstructor::construct):
+ (KJS::ErrorConstructor::callAsFunction):
+ (KJS::NativeErrorConstructor::construct):
+ (KJS::NativeErrorConstructor::callAsFunction):
+ * kjs/error_object.h:
+ * kjs/internal.cpp:
+ (KJS::JSNumberCell::toObject):
+ (KJS::JSNumberCell::toThisObject):
+ * kjs/list.cpp:
+ (KJS::ArgList::getSlice):
+ (KJS::ArgList::markLists):
+ (KJS::ArgList::slowAppend):
+ * kjs/list.h:
+ (KJS::ArgList::ArgList):
+ (KJS::ArgList::~ArgList):
+ * kjs/object_object.cpp:
+ (KJS::objectProtoFuncValueOf):
+ (KJS::objectProtoFuncHasOwnProperty):
+ (KJS::objectProtoFuncIsPrototypeOf):
+ (KJS::objectProtoFuncDefineGetter):
+ (KJS::objectProtoFuncDefineSetter):
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ (KJS::objectProtoFuncPropertyIsEnumerable):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ (KJS::ObjectConstructor::construct):
+ (KJS::ObjectConstructor::callAsFunction):
+ * kjs/object_object.h:
+ * kjs/string_object.cpp:
+ (KJS::replace):
+ (KJS::stringProtoFuncToString):
+ (KJS::stringProtoFuncValueOf):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::StringConstructor::construct):
+ (KJS::StringConstructor::callAsFunction):
+ (KJS::StringConstructorFunction::callAsFunction):
+ * kjs/string_object.h:
+
+2008-06-15 Darin Adler <darin@apple.com>
+
+ - new names for more JavaScriptCore files
+
+ * API/JSCallbackFunction.cpp:
+ * API/JSObjectRef.cpp:
+ * DerivedSources.make:
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/ArrayPrototype.cpp: Copied from JavaScriptCore/kjs/array_object.cpp.
+ * kjs/ArrayPrototype.h: Copied from JavaScriptCore/kjs/array_object.h.
+ * kjs/BooleanObject.cpp: Copied from JavaScriptCore/kjs/bool_object.cpp.
+ * kjs/BooleanObject.h: Copied from JavaScriptCore/kjs/bool_object.h.
+ * kjs/ExecState.cpp:
+ * kjs/ExecState.h:
+ * kjs/FunctionPrototype.cpp: Copied from JavaScriptCore/kjs/function_object.cpp.
+ * kjs/FunctionPrototype.h: Copied from JavaScriptCore/kjs/function_object.h.
+ * kjs/JSArray.cpp: Copied from JavaScriptCore/kjs/array_instance.cpp.
+ * kjs/JSArray.h: Copied from JavaScriptCore/kjs/array_instance.h.
+ * kjs/JSFunction.cpp:
+ * kjs/JSFunction.h:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSImmediate.cpp:
+ * kjs/JSObject.h:
+ * kjs/JSString.h:
+ * kjs/JSValue.h:
+ * kjs/JSVariableObject.cpp:
+ * kjs/MathObject.cpp: Copied from JavaScriptCore/kjs/math_object.cpp.
+ * kjs/MathObject.h: Copied from JavaScriptCore/kjs/math_object.h.
+ * kjs/NumberObject.cpp: Copied from JavaScriptCore/kjs/number_object.cpp.
+ * kjs/NumberObject.h: Copied from JavaScriptCore/kjs/number_object.h.
+ * kjs/PropertyMap.cpp: Copied from JavaScriptCore/kjs/property_map.cpp.
+ * kjs/PropertyMap.h: Copied from JavaScriptCore/kjs/property_map.h.
+ * kjs/PropertySlot.cpp: Copied from JavaScriptCore/kjs/property_slot.cpp.
+ * kjs/PropertySlot.h: Copied from JavaScriptCore/kjs/property_slot.h.
+ * kjs/RegExpObject.cpp: Copied from JavaScriptCore/kjs/regexp_object.cpp.
+ * kjs/RegExpObject.h: Copied from JavaScriptCore/kjs/regexp_object.h.
+ * kjs/ScopeChain.cpp: Copied from JavaScriptCore/kjs/scope_chain.cpp.
+ * kjs/ScopeChain.h: Copied from JavaScriptCore/kjs/scope_chain.h.
+ * kjs/ScopeChainMark.h: Copied from JavaScriptCore/kjs/scope_chain_mark.h.
+ * kjs/Shell.cpp:
+ * kjs/array_instance.cpp: Removed.
+ * kjs/array_instance.h: Removed.
+ * kjs/array_object.cpp: Removed.
+ * kjs/array_object.h: Removed.
+ * kjs/bool_object.cpp: Removed.
+ * kjs/bool_object.h: Removed.
+ * kjs/error_object.h:
+ * kjs/function_object.cpp: Removed.
+ * kjs/function_object.h: Removed.
+ * kjs/internal.cpp:
+ * kjs/math_object.cpp: Removed.
+ * kjs/math_object.h: Removed.
+ * kjs/nodes.cpp:
+ * kjs/number_object.cpp: Removed.
+ * kjs/number_object.h: Removed.
+ * kjs/object_object.cpp:
+ * kjs/property_map.cpp: Removed.
+ * kjs/property_map.h: Removed.
+ * kjs/property_slot.cpp: Removed.
+ * kjs/property_slot.h: Removed.
+ * kjs/regexp_object.cpp: Removed.
+ * kjs/regexp_object.h: Removed.
+ * kjs/scope_chain.cpp: Removed.
+ * kjs/scope_chain.h: Removed.
+ * kjs/scope_chain_mark.h: Removed.
+ * kjs/string_object.cpp:
+ * kjs/string_object.h:
+
+2008-06-15 Darin Adler <darin@apple.com>
+
+ - new names for a few key JavaScriptCore files
+
+ * API/JSBase.cpp:
+ * API/JSCallbackConstructor.h:
+ * API/JSCallbackFunction.cpp:
+ * API/JSCallbackFunction.h:
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ * API/JSClassRef.h:
+ * API/JSContextRef.cpp:
+ * API/JSObjectRef.cpp:
+ * API/JSStringRef.cpp:
+ * API/JSStringRefCF.cpp:
+ * API/JSValueRef.cpp:
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * VM/CodeBlock.cpp:
+ * VM/CodeGenerator.cpp:
+ * VM/ExceptionHelpers.cpp:
+ * VM/ExceptionHelpers.h:
+ * VM/JSPropertyNameIterator.cpp:
+ * VM/JSPropertyNameIterator.h:
+ * VM/Machine.cpp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/DateMath.cpp:
+ * kjs/DebuggerCallFrame.cpp:
+ * kjs/ExecState.cpp:
+ * kjs/JSActivation.cpp:
+ * kjs/JSFunction.cpp: Copied from JavaScriptCore/kjs/function.cpp.
+ * kjs/JSFunction.h: Copied from JavaScriptCore/kjs/function.h.
+ * kjs/JSImmediate.cpp:
+ * kjs/JSNotAnObject.h:
+ * kjs/JSObject.cpp: Copied from JavaScriptCore/kjs/object.cpp.
+ * kjs/JSObject.h: Copied from JavaScriptCore/kjs/object.h.
+ * kjs/JSString.h: Copied from JavaScriptCore/kjs/internal.h.
+ * kjs/JSValue.cpp: Copied from JavaScriptCore/kjs/value.cpp.
+ * kjs/JSValue.h: Copied from JavaScriptCore/kjs/value.h.
+ * kjs/JSVariableObject.h:
+ * kjs/JSWrapperObject.h:
+ * kjs/Shell.cpp:
+ * kjs/SymbolTable.h:
+ * kjs/array_instance.h:
+ * kjs/collector.cpp:
+ * kjs/date_object.cpp:
+ * kjs/date_object.h:
+ * kjs/error_object.cpp:
+ * kjs/function.cpp: Removed.
+ * kjs/function.h: Removed.
+ * kjs/function_object.cpp:
+ * kjs/function_object.h:
+ * kjs/grammar.y:
+ * kjs/internal.cpp:
+ * kjs/internal.h: Removed.
+ * kjs/lexer.cpp:
+ * kjs/list.h:
+ * kjs/lookup.h:
+ * kjs/nodes.h:
+ * kjs/object.cpp: Removed.
+ * kjs/object.h: Removed.
+ * kjs/object_object.h:
+ * kjs/operations.cpp:
+ * kjs/property_map.cpp:
+ * kjs/property_slot.cpp:
+ * kjs/property_slot.h:
+ * kjs/protect.h:
+ * kjs/regexp_object.cpp:
+ * kjs/scope_chain.cpp:
+ * kjs/string_object.h:
+ * kjs/ustring.cpp:
+ * kjs/value.cpp: Removed.
+ * kjs/value.h: Removed.
+ * profiler/Profile.cpp:
+ * profiler/Profiler.cpp:
+
+2008-06-15 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Sam.
+
+ - cut down on confusing uses of "Object" and "Imp" in
+ JavaScriptCore class names
+
+ * API/JSCallbackFunction.cpp:
+ (KJS::JSCallbackFunction::JSCallbackFunction):
+ * API/JSCallbackFunction.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/ExecState.h:
+ (KJS::ExecState::regExpTable):
+ (KJS::ExecState::regExpConstructorTable):
+ * kjs/JSGlobalData.cpp:
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::~JSGlobalData):
+ * kjs/JSGlobalData.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::objectConstructor):
+ (KJS::JSGlobalObject::functionConstructor):
+ (KJS::JSGlobalObject::arrayConstructor):
+ (KJS::JSGlobalObject::booleanConstructor):
+ (KJS::JSGlobalObject::stringConstructor):
+ (KJS::JSGlobalObject::numberConstructor):
+ (KJS::JSGlobalObject::dateConstructor):
+ (KJS::JSGlobalObject::regExpConstructor):
+ (KJS::JSGlobalObject::errorConstructor):
+ (KJS::JSGlobalObject::evalErrorConstructor):
+ (KJS::JSGlobalObject::rangeErrorConstructor):
+ (KJS::JSGlobalObject::referenceErrorConstructor):
+ (KJS::JSGlobalObject::syntaxErrorConstructor):
+ (KJS::JSGlobalObject::typeErrorConstructor):
+ (KJS::JSGlobalObject::URIErrorConstructor):
+ * kjs/array_object.cpp:
+ (KJS::ArrayConstructor::ArrayConstructor):
+ (KJS::ArrayConstructor::getConstructData):
+ (KJS::ArrayConstructor::construct):
+ (KJS::ArrayConstructor::callAsFunction):
+ * kjs/array_object.h:
+ * kjs/bool_object.cpp:
+ (KJS::BooleanObject::BooleanObject):
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::booleanProtoFuncValueOf):
+ (KJS::BooleanConstructor::BooleanConstructor):
+ (KJS::BooleanConstructor::getConstructData):
+ (KJS::BooleanConstructor::construct):
+ (KJS::BooleanConstructor::callAsFunction):
+ * kjs/bool_object.h:
+ * kjs/date_object.cpp:
+ (KJS::DatePrototype::DatePrototype):
+ (KJS::DateConstructor::DateConstructor):
+ (KJS::DateConstructor::getConstructData):
+ (KJS::DateConstructor::construct):
+ (KJS::DateConstructor::callAsFunction):
+ (KJS::DateFunction::DateFunction):
+ (KJS::DateFunction::callAsFunction):
+ * kjs/date_object.h:
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::ErrorConstructor::ErrorConstructor):
+ (KJS::ErrorConstructor::getConstructData):
+ (KJS::ErrorConstructor::construct):
+ (KJS::ErrorConstructor::callAsFunction):
+ (KJS::NativeErrorConstructor::NativeErrorConstructor):
+ (KJS::NativeErrorConstructor::getConstructData):
+ (KJS::NativeErrorConstructor::construct):
+ (KJS::NativeErrorConstructor::callAsFunction):
+ (KJS::NativeErrorConstructor::mark):
+ * kjs/error_object.h:
+ * kjs/function.cpp:
+ (KJS::JSFunction::JSFunction):
+ (KJS::JSFunction::mark):
+ (KJS::JSFunction::getOwnPropertySlot):
+ (KJS::JSFunction::put):
+ (KJS::JSFunction::deleteProperty):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
+ (KJS::PrototypeReflexiveFunction::mark):
+ * kjs/function.h:
+ * kjs/function_object.cpp:
+ (KJS::functionProtoFuncToString):
+ (KJS::FunctionConstructor::FunctionConstructor):
+ (KJS::FunctionConstructor::getConstructData):
+ (KJS::FunctionConstructor::construct):
+ (KJS::FunctionConstructor::callAsFunction):
+ * kjs/function_object.h:
+ * kjs/internal.cpp:
+ (KJS::StringObject::create):
+ (KJS::JSString::toObject):
+ (KJS::JSString::toThisObject):
+ (KJS::JSString::getOwnPropertySlot):
+ (KJS::InternalFunction::InternalFunction):
+ (KJS::InternalFunction::getCallData):
+ (KJS::InternalFunction::implementsHasInstance):
+ * kjs/math_object.cpp:
+ (KJS::MathObject::MathObject):
+ (KJS::MathObject::getOwnPropertySlot):
+ (KJS::MathObject::getValueProperty):
+ * kjs/math_object.h:
+ * kjs/number_object.cpp:
+ (KJS::NumberObject::NumberObject):
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncValueOf):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberConstructor::NumberConstructor):
+ (KJS::NumberConstructor::getOwnPropertySlot):
+ (KJS::NumberConstructor::getValueProperty):
+ (KJS::NumberConstructor::getConstructData):
+ (KJS::NumberConstructor::construct):
+ (KJS::NumberConstructor::callAsFunction):
+ * kjs/number_object.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::putDirectFunction):
+ * kjs/object.h:
+ * kjs/object_object.cpp:
+ (KJS::ObjectConstructor::ObjectConstructor):
+ (KJS::ObjectConstructor::getConstructData):
+ (KJS::ObjectConstructor::construct):
+ (KJS::ObjectConstructor::callAsFunction):
+ * kjs/object_object.h:
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp):
+ * kjs/regexp_object.cpp:
+ (KJS::regExpProtoFuncTest):
+ (KJS::regExpProtoFuncExec):
+ (KJS::regExpProtoFuncCompile):
+ (KJS::regExpProtoFuncToString):
+ (KJS::RegExpObject::RegExpObject):
+ (KJS::RegExpObject::~RegExpObject):
+ (KJS::RegExpObject::getOwnPropertySlot):
+ (KJS::RegExpObject::getValueProperty):
+ (KJS::RegExpObject::put):
+ (KJS::RegExpObject::putValueProperty):
+ (KJS::RegExpObject::match):
+ (KJS::RegExpObject::test):
+ (KJS::RegExpObject::exec):
+ (KJS::RegExpObject::getCallData):
+ (KJS::RegExpObject::callAsFunction):
+ (KJS::RegExpConstructorPrivate::RegExpConstructorPrivate):
+ (KJS::RegExpConstructor::RegExpConstructor):
+ (KJS::RegExpConstructor::performMatch):
+ (KJS::RegExpMatchesArray::RegExpMatchesArray):
+ (KJS::RegExpMatchesArray::~RegExpMatchesArray):
+ (KJS::RegExpMatchesArray::fillArrayInstance):
+ (KJS::RegExpConstructor::arrayOfMatches):
+ (KJS::RegExpConstructor::getBackref):
+ (KJS::RegExpConstructor::getLastParen):
+ (KJS::RegExpConstructor::getLeftContext):
+ (KJS::RegExpConstructor::getRightContext):
+ (KJS::RegExpConstructor::getOwnPropertySlot):
+ (KJS::RegExpConstructor::getValueProperty):
+ (KJS::RegExpConstructor::put):
+ (KJS::RegExpConstructor::putValueProperty):
+ (KJS::RegExpConstructor::getConstructData):
+ (KJS::RegExpConstructor::construct):
+ (KJS::RegExpConstructor::callAsFunction):
+ (KJS::RegExpConstructor::input):
+ * kjs/regexp_object.h:
+ * kjs/string_object.cpp:
+ (KJS::StringObject::StringObject):
+ (KJS::StringObject::getOwnPropertySlot):
+ (KJS::StringObject::put):
+ (KJS::StringObject::deleteProperty):
+ (KJS::StringObject::getPropertyNames):
+ (KJS::StringPrototype::StringPrototype):
+ (KJS::StringPrototype::getOwnPropertySlot):
+ (KJS::replace):
+ (KJS::stringProtoFuncToString):
+ (KJS::stringProtoFuncValueOf):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::StringConstructor::StringConstructor):
+ (KJS::StringConstructor::getConstructData):
+ (KJS::StringConstructor::construct):
+ (KJS::StringConstructor::callAsFunction):
+ (KJS::StringConstructorFunction::StringConstructorFunction):
+ (KJS::StringConstructorFunction::callAsFunction):
+ * kjs/string_object.h:
+ (KJS::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):
+ * profiler/Profiler.cpp:
+ (KJS::createCallIdentifier):
+
+2008-06-15 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Sam.
+
+ - use JS prefix and simpler names for basic JavaScriptCore types,
+ to complement JSValue and JSObject
+
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp:
+ (KJS::jsLess):
+ (KJS::jsLessEq):
+ (KJS::jsAdd):
+ (KJS::callEval):
+ (KJS::Machine::execute):
+ (KJS::Machine::retrieveArguments):
+ (KJS::Machine::retrieveCaller):
+ (KJS::Machine::getCallFrame):
+ (KJS::Machine::getFunctionAndArguments):
+ * VM/Machine.h:
+ * VM/Register.h:
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::functionName):
+ * kjs/ExecState.h:
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject):
+ * kjs/array_instance.cpp:
+ (KJS::JSArray::checkConsistency):
+ (KJS::JSArray::JSArray):
+ (KJS::JSArray::~JSArray):
+ (KJS::JSArray::getItem):
+ (KJS::JSArray::lengthGetter):
+ (KJS::JSArray::inlineGetOwnPropertySlot):
+ (KJS::JSArray::getOwnPropertySlot):
+ (KJS::JSArray::put):
+ (KJS::JSArray::deleteProperty):
+ (KJS::JSArray::getPropertyNames):
+ (KJS::JSArray::increaseVectorLength):
+ (KJS::JSArray::setLength):
+ (KJS::JSArray::mark):
+ (KJS::JSArray::sort):
+ (KJS::JSArray::compactForSorting):
+ (KJS::JSArray::lazyCreationData):
+ (KJS::JSArray::setLazyCreationData):
+ * kjs/array_instance.h:
+ * kjs/array_object.cpp:
+ (KJS::ArrayPrototype::ArrayPrototype):
+ (KJS::ArrayPrototype::getOwnPropertySlot):
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncSort):
+ (KJS::ArrayObjectImp::construct):
+ * kjs/array_object.h:
+ * kjs/completion.h:
+ * kjs/function.cpp:
+ (KJS::JSFunction::JSFunction):
+ (KJS::JSFunction::mark):
+ (KJS::JSFunction::getCallData):
+ (KJS::JSFunction::callAsFunction):
+ (KJS::JSFunction::argumentsGetter):
+ (KJS::JSFunction::callerGetter):
+ (KJS::JSFunction::lengthGetter):
+ (KJS::JSFunction::getOwnPropertySlot):
+ (KJS::JSFunction::put):
+ (KJS::JSFunction::deleteProperty):
+ (KJS::JSFunction::getParameterName):
+ (KJS::JSFunction::getConstructData):
+ (KJS::JSFunction::construct):
+ (KJS::IndexToNameMap::IndexToNameMap):
+ (KJS::Arguments::Arguments):
+ * kjs/function.h:
+ * kjs/function_object.cpp:
+ (KJS::functionProtoFuncToString):
+ (KJS::functionProtoFuncApply):
+ (KJS::FunctionObjectImp::construct):
+ * kjs/internal.cpp:
+ (KJS::JSString::toPrimitive):
+ (KJS::JSString::getPrimitiveNumber):
+ (KJS::JSString::toBoolean):
+ (KJS::JSString::toNumber):
+ (KJS::JSString::toString):
+ (KJS::StringInstance::create):
+ (KJS::JSString::toObject):
+ (KJS::JSString::toThisObject):
+ (KJS::JSString::lengthGetter):
+ (KJS::JSString::indexGetter):
+ (KJS::JSString::indexNumericPropertyGetter):
+ (KJS::JSString::getOwnPropertySlot):
+ (KJS::JSNumberCell::type):
+ (KJS::JSNumberCell::toPrimitive):
+ (KJS::JSNumberCell::getPrimitiveNumber):
+ (KJS::JSNumberCell::toBoolean):
+ (KJS::JSNumberCell::toNumber):
+ (KJS::JSNumberCell::toString):
+ (KJS::JSNumberCell::toObject):
+ (KJS::JSNumberCell::toThisObject):
+ (KJS::JSNumberCell::getUInt32):
+ (KJS::JSNumberCell::getTruncatedInt32):
+ (KJS::JSNumberCell::getTruncatedUInt32):
+ (KJS::GetterSetter::mark):
+ (KJS::GetterSetter::toPrimitive):
+ (KJS::GetterSetter::getPrimitiveNumber):
+ (KJS::GetterSetter::toBoolean):
+ (KJS::GetterSetter::toNumber):
+ (KJS::GetterSetter::toString):
+ (KJS::GetterSetter::toObject):
+ (KJS::GetterSetter::getOwnPropertySlot):
+ (KJS::GetterSetter::put):
+ (KJS::GetterSetter::toThisObject):
+ * kjs/internal.h:
+ (KJS::JSString::JSString):
+ (KJS::JSString::getStringPropertySlot):
+ * kjs/nodes.cpp:
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::makeFunction):
+ * kjs/nodes.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::put):
+ (KJS::JSObject::deleteProperty):
+ (KJS::JSObject::defineGetter):
+ (KJS::JSObject::defineSetter):
+ (KJS::JSObject::lookupGetter):
+ (KJS::JSObject::lookupSetter):
+ (KJS::JSObject::fillGetterPropertySlot):
+ * kjs/object.h:
+ (KJS::GetterSetter::GetterSetter):
+ * kjs/operations.cpp:
+ (KJS::equal):
+ (KJS::strictEqual):
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::containsGettersOrSetters):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpMatchesArray::getOwnPropertySlot):
+ (KJS::RegExpMatchesArray::put):
+ (KJS::RegExpMatchesArray::deleteProperty):
+ (KJS::RegExpMatchesArray::getPropertyNames):
+ (KJS::RegExpMatchesArray::RegExpMatchesArray):
+ (KJS::RegExpMatchesArray::fillArrayInstance):
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::StringInstance):
+ (KJS::replace):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ * kjs/string_object.h:
+ (KJS::StringInstance::internalValue):
+ * kjs/value.cpp:
+ (KJS::JSCell::getNumber):
+ (KJS::JSCell::getString):
+ (KJS::JSCell::getObject):
+ (KJS::jsString):
+ (KJS::jsOwnedString):
+ * kjs/value.h:
+ (KJS::JSNumberCell::JSNumberCell):
+ (KJS::jsNumberCell):
+ (KJS::JSValue::uncheckedGetNumber):
+ * profiler/Profiler.cpp:
+ (KJS::createCallIdentifier):
+ (KJS::createCallIdentifierFromFunctionImp):
+
+2008-06-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Alexey.
+
+ - add emitUnaryOp, emitNullaryOp and emitUnaryOpNoDst; use them
+
+ This removes some boilerplate code and also reduces the number of
+ places that will need to be changed to do on-demand emit of
+ loads (and thus support k operands).
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitUnaryOp):
+ (KJS::CodeGenerator::emitNullaryOp):
+ (KJS::CodeGenerator::emitUnaryOpNoDst):
+ (KJS::CodeGenerator::emitPushScope):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::emitNewObject):
+ (KJS::CodeGenerator::emitNewArray):
+ (KJS::CodeGenerator::emitNot):
+ (KJS::CodeGenerator::emitBitNot):
+ (KJS::CodeGenerator::emitToJSNumber):
+ (KJS::CodeGenerator::emitNegate):
+ (KJS::CodeGenerator::emitInstanceOf):
+ (KJS::CodeGenerator::emitTypeOf):
+ (KJS::CodeGenerator::emitIn):
+ (KJS::CodeGenerator::emitReturn):
+ (KJS::CodeGenerator::emitEnd):
+ (KJS::CodeGenerator::emitGetPropertyNames):
+
+2008-06-15 Alp Toker <alp@nuanti.com>
+
+ Rubber-stamped by Maciej.
+
+ Install 'jsc' application by default.
+
+ * GNUmakefile.am:
+
+2008-06-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - rename testkjs to jsc
+
+ * GNUmakefile.am:
+ * JavaScriptCore.vcproj/JavaScriptCore.sln:
+ * JavaScriptCore.vcproj/jsc: Added.
+ * JavaScriptCore.vcproj/jsc/jsc.vcproj: Copied from JavaScriptCore.vcproj/testkjs/testkjs.vcproj.
+ * JavaScriptCore.vcproj/testkjs: Removed.
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj: Removed.
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * jscore.bkl:
+ * kjs/Shell.cpp: Copied from kjs/testkjs.cpp.
+ (main):
+ (printUsageStatement):
+ (jscmain):
+ * kjs/jsc.pro: Copied from kjs/testkjs.pro.
+ * kjs/testkjs.cpp: Removed.
+ * kjs/testkjs.pro: Removed.
+ * tests/mozilla/expected.html:
+ * tests/mozilla/js1_2/Array/tostring_1.js:
+ * tests/mozilla/js1_2/Array/tostring_2.js:
+ * tests/mozilla/jsDriver.pl:
+
+2008-06-15 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Mac build fix.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/nodes.h:
+
+2008-06-15 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Change the spelling of PrecMultiplicitave to PrecMultiplicative.
+
+ * kjs/nodes.h:
+ (KJS::MultNode::precedence):
+ (KJS::DivNode::precedence):
+ (KJS::ModNode::precedence):
+
+2008-06-15 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Remove unused preprocessor macros related to exceptions in the old
+ interpreter.
+
+ * kjs/nodes.cpp:
+
+2008-06-15 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 19484: More instructions needs to use temporary registers
+ <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+ Fix codegen for all binary operations so that temporaries are used if
+ necessary. This was done by making BinaryOpNode and ReverseBinaryOpNode
+ subclasses of ExpressionNode, and eliminating the custom emitCode()
+ methods for the individual node classes.
+
+ This only adds 3 new instructions to SunSpider code, and there is no
+ difference in SunSpider execution time.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitBitNot):
+ (KJS::CodeGenerator::emitBinaryOp):
+ * VM/CodeGenerator.h:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::BinaryOpNode::emitCode):
+ (KJS::ReverseBinaryOpNode::emitCode):
+ (KJS::emitReadModifyAssignment):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+ * kjs/nodes.h:
+ (KJS::BinaryOpNode::BinaryOpNode):
+ (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode):
+ (KJS::MultNode::):
+ (KJS::DivNode::):
+ (KJS::DivNode::precedence):
+ (KJS::ModNode::):
+ (KJS::ModNode::precedence):
+ (KJS::AddNode::):
+ (KJS::AddNode::precedence):
+ (KJS::SubNode::):
+ (KJS::SubNode::precedence):
+ (KJS::LeftShiftNode::):
+ (KJS::LeftShiftNode::precedence):
+ (KJS::RightShiftNode::):
+ (KJS::RightShiftNode::precedence):
+ (KJS::UnsignedRightShiftNode::):
+ (KJS::UnsignedRightShiftNode::precedence):
+ (KJS::LessNode::):
+ (KJS::LessNode::precedence):
+ (KJS::GreaterNode::):
+ (KJS::GreaterNode::precedence):
+ (KJS::LessEqNode::):
+ (KJS::LessEqNode::precedence):
+ (KJS::GreaterEqNode::):
+ (KJS::GreaterEqNode::precedence):
+ (KJS::InstanceOfNode::):
+ (KJS::InstanceOfNode::precedence):
+ (KJS::InNode::):
+ (KJS::InNode::precedence):
+ (KJS::EqualNode::):
+ (KJS::EqualNode::precedence):
+ (KJS::NotEqualNode::):
+ (KJS::NotEqualNode::precedence):
+ (KJS::StrictEqualNode::):
+ (KJS::StrictEqualNode::precedence):
+ (KJS::NotStrictEqualNode::):
+ (KJS::NotStrictEqualNode::precedence):
+ (KJS::BitAndNode::):
+ (KJS::BitAndNode::precedence):
+ (KJS::BitOrNode::):
+ (KJS::BitOrNode::precedence):
+ (KJS::BitXOrNode::):
+ (KJS::BitXOrNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::LessNode::streamTo):
+ (KJS::GreaterNode::streamTo):
+ (KJS::LessEqNode::streamTo):
+ (KJS::GreaterEqNode::streamTo):
+ (KJS::InstanceOfNode::streamTo):
+ (KJS::InNode::streamTo):
+ (KJS::EqualNode::streamTo):
+ (KJS::NotEqualNode::streamTo):
+ (KJS::StrictEqualNode::streamTo):
+ (KJS::NotStrictEqualNode::streamTo):
+ (KJS::BitAndNode::streamTo):
+ (KJS::BitXOrNode::streamTo):
+ (KJS::BitOrNode::streamTo):
+
+2008-06-14 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Sam.
+
+ - rename a bunch of local symbols within the regular expression code to
+ follow our usual coding style, and do a few other name tweaks
+
+ * pcre/pcre_compile.cpp:
+ (CompileData::CompileData):
+ (checkEscape):
+ (readRepeatCounts):
+ (compileBranch):
+ (compileBracket):
+ (calculateCompiledPatternLength):
+ (returnError):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (MatchStack::MatchStack):
+ (MatchStack::canUseStackBufferForNextFrame):
+ (MatchStack::popCurrentFrame):
+ (match):
+ (tryFirstByteOptimization):
+ (tryRequiredByteOptimization):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Remove redundant uses of get().
+
+ * kjs/nodes.cpp:
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::AddNode::emitCode):
+ (KJS::SubNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+
+2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Make code generation not use a temporary for the left-hand side of an
+ expression if the right-hand side is a local variable.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::isLocal):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::leftHandSideNeedsCopy):
+ (KJS::CodeGenerator::emitNodeForLeftHandSide):
+ * kjs/nodes.cpp:
+ (KJS::ResolveNode::isPure):
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::AddNode::emitCode):
+ (KJS::SubNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::BooleanNode::):
+ (KJS::NumberNode::):
+ (KJS::StringNode::):
+
+2008-06-14 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - more of https://bugs.webkit.org/show_bug.cgi?id=17257
+ start ref counts at 1 instead of 0 for speed
+
+ * kjs/nodes.cpp:
+ (KJS::ParserRefCounted::hasOneRef): Added. Replaces refcount.
+ * kjs/nodes.h: Replaced refcount with hasOneRef.
+
+ * wtf/ListRefPtr.h:
+ (WTF::ListRefPtr::~ListRefPtr): Changed to use hasOneRef instead of
+ refcount, so this class can be used with the RefCounted template.
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::hasOneRef): Made const, since there's no reason for
+ it to be non-const.
+
+2008-06-14 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - initialize local vars as side effect of call instead of in bytecode
+ 1.004x speedup on SunSpider.
+
+ This removes just the dispatch overhead for these loads - in the
+ future, dead store elimination might be able to eliminate them
+ entirely.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator): For function blocks, don't
+ emit loads of undefined for var initialization.
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall): Instead, initialize locals
+ as part of the call.
+
+2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Remove helper functions in the parser that are no longer needed.
+
+ * kjs/grammar.y:
+
+2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19484: More instructions needs to use temporary registers
+ <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+ Make code generation for AddNode and SubNode use temporaries when
+ necessary.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::AddNode::emitCode):
+ (KJS::SubNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::AddNode::):
+ (KJS::SubNode::):
+
+2008-06-13 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Combine TrueNode and FalseNode to make BooleanNode, and remove the
+ unused class PlaceholderTrueNode.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::BooleanNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::BooleanNode::):
+ (KJS::BooleanNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::BooleanNode::streamTo):
+
+2008-06-13 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Eliminate the use of temporaries to store the left hand side of an
+ expression when the right hand side is a constant. This slightly
+ improves the generated bytecode for a few SunSpider tests, but it is
+ mostly in preparation for fixing
+
+ Bug 19484: More instructions needs to use temporary registers
+ <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::leftHandSideNeedsCopy):
+ (KJS::CodeGenerator::emitNodeForLeftHandSide):
+ * kjs/nodes.cpp:
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::FalseNode::):
+ (KJS::TrueNode::):
+ (KJS::NumberNode::):
+ (KJS::StringNode::):
+
+2008-06-13 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - prettify opcode stats output
+
+ I changed things to be a bit more aligned, also there is a new
+ section listing most common opcodes and most common sequences that
+ include them.
+
+ * VM/Opcode.cpp:
+ (KJS::OpcodeStats::~OpcodeStats):
+ * VM/Opcode.h:
+
+2008-06-13 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+ profiler.
+ - Remove recursion from exclude(). This leaves only focus() to fix.
+
+ * JavaScriptCore.exp: Change the signatures of the exported functions.
+ * profiler/Profile.cpp:
+ (KJS::Profile::forEach): I added a traverseNextNodePreOrder() function
+ and so needed to distinguish the other function by labeling it
+ traverseNextNodePostOrder().
+ (KJS::Profile::exclude): All new exclude that iteratively walks the tree
+ * profiler/Profile.h:
+ (KJS::Profile::focus): Add a null check for m_head.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::traverseNextNodePostOrder): Renamed
+ (KJS::ProfileNode::traverseNextNodePreOrder): Walks the tree in pre-
+ order, where the parent is processed before the children.
+ (KJS::ProfileNode::setTreeVisible): Iterate over the sub-tree and set
+ all of the nodes visible value. This changes another function that used
+ recursion.
+ (KJS::ProfileNode::exclude): Remove recursion from this function.
+ Because we now check for m_visible and we are walking the tree in pre-
+ order we do not need to check if an excluded node is in an excluded
+ sub-tree.
+ * profiler/ProfileNode.h: Added specific selfTime functions to
+ facilitate exclude().
+ (KJS::ProfileNode::setSelfTime):
+ (KJS::ProfileNode::setActualSelfTime):
+ (KJS::ProfileNode::setVisibleSelfTime):
+
+2008-06-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19434
+ speed up SunSpider by avoiding some string boxing
+
+ Speeds up SunSpider by 1.1%.
+
+ Optimized code path for getting built-in properties from strings -- avoid
+ boxing with a string object in that case. We can make further changes to avoid
+ even more boxing, but this change alone is a win.
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::JSCallbackObject::staticValueGetter): Use isObject instead of inherits
+ in asssert, since the type of slotBase() is now JSValue, not JSObject.
+ (KJS::JSCallbackObject::staticFunctionGetter): Ditto.
+ (KJS::JSCallbackObject::callbackGetter): Ditto.
+
+ * kjs/internal.cpp:
+ (KJS::StringImp::getPrimitiveNumber): Updated for change of data member name.
+ (KJS::StringImp::toBoolean): Ditto.
+ (KJS::StringImp::toNumber): Ditto.
+ (KJS::StringImp::toString): Ditto.
+ (KJS::StringInstance::create): Added; avoids a bit of cut and paste code.
+ (KJS::StringImp::toObject): Use StringInstance::create.
+ (KJS::StringImp::toThisObject): Ditto.
+ (KJS::StringImp::lengthGetter): Added. Replaces the getter that used to live in
+ the StringInstance class.
+ (KJS::StringImp::indexGetter): Ditto.
+ (KJS::StringImp::indexNumericPropertyGetter): Ditto.
+ (KJS::StringImp::getOwnPropertySlot): Added. Deals with built in properties of
+ the string class without creating a StringInstance.
+
+ * kjs/internal.h:
+ (KJS::StringImp::getStringPropertySlot): Added. To be used by both the string
+ and string object getOwnPropertySlot function.
+
+ * kjs/lookup.h:
+ (KJS::staticFunctionGetter): Updated since slotBase() is now a JSValue rather
+ than a JSObject.
+
+ * kjs/object.h: Removed PropertySlot::slotBase() function, which can now move
+ back into property_slot.h where it belongs since it doesn't have to cast to
+ JSObject*.
+
+ * kjs/property_slot.cpp:
+ (KJS::PropertySlot::functionGetter): Updated since slot.slotBase() is now a JSValue*
+ instead of JSObject*. setGetterSlot still guarantees the base is a JSObject*.
+ * kjs/property_slot.h:
+ (KJS::PropertySlot::PropertySlot): Changed base to JSValue* intead of JSCell*.
+ (KJS::PropertySlot::setStaticEntry): Ditto.
+ (KJS::PropertySlot::setCustom): Ditto.
+ (KJS::PropertySlot::setCustomIndex): Ditto.
+ (KJS::PropertySlot::setCustomNumeric): Ditto.
+ (KJS::PropertySlot::slotBase): Moved inline here since it no longer involves a
+ downcast to JSObject*.
+ (KJS::PropertySlot::setBase): Changed to JSValue*.
+
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::getOwnPropertySlot): Changed to use getStringPropertySlot
+ instead of coding the properties here. This allows sharing the code with StringImp.
+
+ * kjs/string_object.h: Removed inlineGetOwnPropertySlot, lengthGetter, and indexGetter.
+ Made one of the constructors protected.
+
+ * kjs/value.h: Made getOwnPropertySlot private in the JSCell class -- this is better
+ since it's not the real JSObject getOwnPropertySlot semantic and most callers shouldn't
+ use it.
+
+2008-06-12 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Maciej.
+
+ Preparation to making JavaScript heap per-thread.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ * kjs/collector.h:
+ (KJS::Collector::markListSet):
+ The collector now holds the list of protected lists itself, to be made per-instance.
+
+ * kjs/list.h: Changed to hold a pointer to a mark set this list is in, if any.
+ (KJS::List::List): Explicitly initialize m_size with zero, as m_vector.size() is
+ guaranteed to be such anyway.
+ (KJS::List::append): Changed the fast case to only be executed as long as inline buffer
+ is used, because otherwise, we now do more expensive checks.
+
+ * kjs/list.cpp:
+ (KJS::List::markLists): Renamed from markProtectedListsSlowCase, made it take the list set
+ as a parameter.
+ (KJS::List::slowAppend): If a non-immediate value is appended, the list needs to be added
+ to an appropriate Heap's protected list. For now, a static Collector::markListSet() is
+ used, but the code is layed out in preparation to making the switch to multiple heaps.
+
+ * JavaScriptCore.exp: Updated export list.
+
+2008-06-12 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 19510: CodeBlock::needsFullScopeChain not always set for global code
+ <https://bugs.webkit.org/show_bug.cgi?id=19510>
+
+ This fixes the symptoms by using CodeGenerator::m_codeType to determine
+ when to use temporaries instead of CodeBlock::needsFullScopeChain, but
+ it does not fix the problem itself.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::leftHandSideNeedsCopy):
+
+2008-06-11 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 19498: REGRESSION (r34497): crash while loading GMail
+ <https://bugs.webkit.org/show_bug.cgi?id=19498>
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpIfTrueMayCombine):
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-06-11 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - a little bit of cleanup and prep for some upcoming optimizations
+
+ * JavaScriptCore.exp: Re-sorted this file (with sort command line tool).
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump): Fixed printf to avoid warnings -- to use %lu we
+ need to make sure the type is unsigned long.
+ * kjs/object.cpp:
+ (KJS::Error::create): Eliminated unused error names array, and also put
+ the strings into the code since there was already a switch statment.
+ This also avoids having to contemplate a hypothetical access past the
+ end of the array.
+ * kjs/object.h: Got rid of errorNames.
+ * kjs/property_slot.cpp: Deleted unused ungettableGetter.
+ * kjs/property_slot.h: Ditto.
+ * wtf/AlwaysInline.h: Added LIKELY alongside UNLIKELY.
+
+2008-06-11 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 19457: Create fused opcodes for tests and conditional jumps
+ <https://bugs.webkit.org/show_bug.cgi?id=19457>
+
+ Add a new jless instruction, and modify the code generator to emit it
+ instead of the pair (less, jtrue).
+
+ Gives a 3.6% improvement on SunSpider.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::emitOpcode):
+ (KJS::CodeGenerator::retrieveLastBinaryOp):
+ (KJS::CodeGenerator::rewindBinaryOp):
+ (KJS::CodeGenerator::emitJump):
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ (KJS::CodeGenerator::emitJumpIfFalse):
+ (KJS::CodeGenerator::emitMove):
+ (KJS::CodeGenerator::emitNot):
+ (KJS::CodeGenerator::emitEqual):
+ (KJS::CodeGenerator::emitNotEqual):
+ (KJS::CodeGenerator::emitStrictEqual):
+ (KJS::CodeGenerator::emitNotStrictEqual):
+ (KJS::CodeGenerator::emitLess):
+ (KJS::CodeGenerator::emitLessEq):
+ (KJS::CodeGenerator::emitPreInc):
+ (KJS::CodeGenerator::emitPreDec):
+ (KJS::CodeGenerator::emitPostInc):
+ (KJS::CodeGenerator::emitPostDec):
+ (KJS::CodeGenerator::emitToJSNumber):
+ (KJS::CodeGenerator::emitNegate):
+ (KJS::CodeGenerator::emitAdd):
+ (KJS::CodeGenerator::emitMul):
+ (KJS::CodeGenerator::emitDiv):
+ (KJS::CodeGenerator::emitMod):
+ (KJS::CodeGenerator::emitSub):
+ (KJS::CodeGenerator::emitLeftShift):
+ (KJS::CodeGenerator::emitRightShift):
+ (KJS::CodeGenerator::emitUnsignedRightShift):
+ (KJS::CodeGenerator::emitBitAnd):
+ (KJS::CodeGenerator::emitBitXOr):
+ (KJS::CodeGenerator::emitBitOr):
+ (KJS::CodeGenerator::emitBitNot):
+ (KJS::CodeGenerator::emitInstanceOf):
+ (KJS::CodeGenerator::emitTypeOf):
+ (KJS::CodeGenerator::emitIn):
+ (KJS::CodeGenerator::emitLoad):
+ (KJS::CodeGenerator::emitNewObject):
+ (KJS::CodeGenerator::emitNewArray):
+ (KJS::CodeGenerator::emitResolve):
+ (KJS::CodeGenerator::emitGetScopedVar):
+ (KJS::CodeGenerator::emitPutScopedVar):
+ (KJS::CodeGenerator::emitResolveBase):
+ (KJS::CodeGenerator::emitResolveWithBase):
+ (KJS::CodeGenerator::emitResolveFunction):
+ (KJS::CodeGenerator::emitGetById):
+ (KJS::CodeGenerator::emitPutById):
+ (KJS::CodeGenerator::emitPutGetter):
+ (KJS::CodeGenerator::emitPutSetter):
+ (KJS::CodeGenerator::emitDeleteById):
+ (KJS::CodeGenerator::emitGetByVal):
+ (KJS::CodeGenerator::emitPutByVal):
+ (KJS::CodeGenerator::emitDeleteByVal):
+ (KJS::CodeGenerator::emitPutByIndex):
+ (KJS::CodeGenerator::emitNewFunction):
+ (KJS::CodeGenerator::emitNewRegExp):
+ (KJS::CodeGenerator::emitNewFunctionExpression):
+ (KJS::CodeGenerator::emitCall):
+ (KJS::CodeGenerator::emitReturn):
+ (KJS::CodeGenerator::emitEnd):
+ (KJS::CodeGenerator::emitConstruct):
+ (KJS::CodeGenerator::emitPushScope):
+ (KJS::CodeGenerator::emitPopScope):
+ (KJS::CodeGenerator::emitDebugHook):
+ (KJS::CodeGenerator::emitComplexJumpScopes):
+ (KJS::CodeGenerator::emitJumpScopes):
+ (KJS::CodeGenerator::emitNextPropertyName):
+ (KJS::CodeGenerator::emitGetPropertyNames):
+ (KJS::CodeGenerator::emitCatch):
+ (KJS::CodeGenerator::emitThrow):
+ (KJS::CodeGenerator::emitNewError):
+ (KJS::CodeGenerator::emitJumpSubroutine):
+ (KJS::CodeGenerator::emitSubroutineReturn):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.cpp:
+ * VM/Opcode.h:
+
+2008-06-11 Darin Adler <darin@apple.com>
+
+ Reviewed by Alexey.
+
+ - fix https://bugs.webkit.org/show_bug.cgi?id=19442
+ JavaScript array implementation doesn't maintain m_numValuesInVector when sorting
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::checkConsistency): Added. Empty inline version for when
+ consistency checks are turned off.
+ (KJS::ArrayInstance::ArrayInstance): Check consistency after construction.
+ (KJS::ArrayInstance::~ArrayInstance): Check consistency before destruction.
+ (KJS::ArrayInstance::put): Check consistency before and after.
+ (KJS::ArrayInstance::deleteProperty): Ditto.
+ (KJS::ArrayInstance::setLength): Ditto.
+ (KJS::compareByStringPairForQSort): Use typedef for clarity.
+ (KJS::ArrayInstance::sort): Check consistency before and after. Also broke the loop
+ to set up sorting into two separate passes. Added FIXMEs about various exception
+ safety issues. Added code to set m_numValuesInVector after sorting.
+ (KJS::ArrayInstance::compactForSorting): Ditto.
+
+ * kjs/array_instance.h: Added a definition of an enum for the types of consistency
+ check and a declaration of the consistency checking function.
+
+2008-06-10 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix. Link against libedit on Mac since HAVE(READLINE) is defined there.
+
+ * jscore.bkl:
+
+2008-06-10 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=16503
+ match limit takes at least 13% of the time on the SunSpider regexp-dna test
+
+ Make the limit test slightly more efficient. It is not clear how much of a win it is,
+ as the improvement on regexp-dna varies from 2.3% to 0.6% depending on what revision I
+ apply the patch to. Today, the win on regexp-dna was minimal, but the total win was whopping
+ 0.5%, due to random code generation changes.
+
+ * pcre/pcre_exec.cpp: (match): Avoid loading a constant on each iteration.
+
+2008-06-09 Alp Toker <alp@nuanti.com>
+
+ gcc3/autotools build fix. Add explicit -O2 -fno-strict-aliasing to
+ each of the tools since these are no longer set globally.
+
+ * GNUmakefile.am:
+
+2008-06-09 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Sam.
+
+ Add an include for readline/history.h to fix the build for Darwin users
+ with the GNU readline library installed. Also, clean up the style of
+ the HAVE(READLINE) check.
+
+ * kjs/testkjs.cpp:
+ (runInteractive):
+
+2008-06-09 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 17531: Add interactive mode to testkjs
+ <https://bugs.webkit.org/show_bug.cgi?id=17531>
+
+ This is a cleaned up version of Sam's earlier patch to add an
+ interactive mode to testkjs.
+
+ Readline support is only enabled on Darwin platforms for now, but
+ other ports can enable it by defining HAVE_READLINE in kjs/config.h.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/config.h:
+ * kjs/testkjs.cpp:
+ (Options::Options):
+ (runWithScripts):
+ (runInteractive):
+ (printUsageStatement):
+ (parseArguments):
+ (kjsmain):
+
+2008-06-08 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Bug 19346: REGRESSION: Mootools 1.2 Class inheritance broken in post-SquirrelFish merge
+ <https://bugs.webkit.org/show_bug.cgi?id=19346>
+
+ A check for whether a function's caller is eval code accidentally included
+ the case where the caller's caller is native code. Add a CodeType field to
+ CodeBlock and use this for the eval caller test instead.
+
+ * VM/CodeBlock.h:
+ (KJS::CodeBlock::CodeBlock):
+ (KJS::ProgramCodeBlock::ProgramCodeBlock):
+ (KJS::EvalCodeBlock::EvalCodeBlock):
+ * VM/Machine.cpp:
+ (KJS::getCallerFunctionOffset):
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::generateCode):
+ (KJS::ProgramNode::generateCode):
+
+2008-06-07 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Dan Bernstein.
+
+ Bug 17928: testkjs shouldn't require "-f"
+ <https://bugs.webkit.org/show_bug.cgi?id=17928>
+
+ * kjs/testkjs.cpp:
+ (printUsageStatement):
+ (parseArguments):
+
+2008-06-07 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Eric.
+
+ Bug 17548: JavaScriptCore print(a, b) differs from Spidermonkey Behavior
+ <https://bugs.webkit.org/show_bug.cgi?id=17548>
+
+ * kjs/testkjs.cpp:
+ (functionPrint):
+
+2008-06-07 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Sam.
+
+ Bug 17547: JavaScriptCore print() differs from Spidermonkey Behavior
+ <https://bugs.webkit.org/show_bug.cgi?id=17547>
+
+ * kjs/testkjs.cpp:
+ (functionPrint):
+
+2008-06-07 Alexey Proskuryakov <ap@webkit.org>
+
+ More build fixes.
+
+ * kjs/JSGlobalData.cpp: Fixed an included file name for case-sensitive file systems, fixed
+ JSGlobalData::threadInstance() for non-multithreaded builds.
+
+2008-06-07 Alexey Proskuryakov <ap@webkit.org>
+
+ Build fix - actually adding JSGlobalData.cpp to non-Mac builds!
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCoreSources.bkl:
+
+2008-06-07 Alexey Proskuryakov <ap@webkit.org>
+
+ Try to fix Gtk/gcc 4.3 build.
+
+ * kjs/JSGlobalData.h: Include ustring.h instead of forward-declaring UString::Rep.
+
+2008-06-06 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Combine per-thread objects into one, to make it easier to support legacy clients (for
+ which they shouldn't be really per-thread).
+
+ No change on SunSpider total.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Added JSGlobalData.{h,cpp}
+
+ * kjs/JSGlobalData.cpp: Added.
+ (KJS::JSGlobalData::JSGlobalData):
+ (KJS::JSGlobalData::~JSGlobalData):
+ (KJS::JSGlobalData::threadInstance):
+ * kjs/JSGlobalData.h: Added.
+ This class encapsulates all data that should be per-thread (or shared between legacy clients).
+ It will also keep a Heap pointer, but right now, Heap (Collector) methods are all static.
+
+ * kjs/identifier.h:
+ (KJS::Identifier::Identifier):
+ Added a constructor explicitly taking JSGlobalData to access IdentifierTable. Actually,
+ all of them should, but this will be a separate patch.
+
+ * kjs/identifier.cpp:
+ (KJS::IdentifierTable::literalTable):
+ (KJS::createIdentifierTable):
+ (KJS::deleteIdentifierTable):
+ (KJS::Identifier::add):
+ (KJS::Identifier::addSlowCase):
+ Combined IdentifierTable and LiteralIdentifierTable into a single class for simplicity.
+
+ * kjs/grammar.y: kjsyyparse now takes JSGlobalData, not just a Lexer.
+
+ * kjs/nodes.cpp:
+ (KJS::Node::Node):
+ (KJS::EvalFunctionCallNode::emitCode):
+ (KJS::ScopeNode::ScopeNode):
+ Changed to access Lexer and Parser via JSGlobalData::threadInstance(). This is also a
+ temporary measure, they will need to use JSGlobalData explicitly.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::callEval):
+ * kjs/CommonIdentifiers.cpp:
+ (KJS::CommonIdentifiers::CommonIdentifiers):
+ * kjs/CommonIdentifiers.h:
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::evaluate):
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/ExecState.h:
+ (KJS::ExecState::globalData):
+ (KJS::ExecState::identifierTable):
+ (KJS::ExecState::propertyNames):
+ (KJS::ExecState::emptyList):
+ (KJS::ExecState::lexer):
+ (KJS::ExecState::parser):
+ (KJS::ExecState::arrayTable):
+ (KJS::ExecState::dateTable):
+ (KJS::ExecState::mathTable):
+ (KJS::ExecState::numberTable):
+ (KJS::ExecState::RegExpImpTable):
+ (KJS::ExecState::RegExpObjectImpTable):
+ (KJS::ExecState::stringTable):
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreadingOnce):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
+ (KJS::JSGlobalObject::head):
+ (KJS::JSGlobalObject::globalData):
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+ * kjs/Parser.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::getParameterName):
+ (KJS::IndexToNameMap::unMap):
+ (KJS::globalFuncEval):
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::checkSyntax):
+ (KJS::Interpreter::evaluate):
+ * kjs/lexer.cpp:
+ (kjsyylex):
+ * kjs/lexer.h:
+ * kjs/testkjs.cpp:
+ (prettyPrintScript):
+ Updated for the above changes. Most of threadInstance uses here will need to be replaced with
+ explicitly passed pointers to support legacy JSC clients.
+
+ * JavaScriptCore.exp: Removed KJS::parser().
+
+2008-06-06 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 19424: Add support for logging opcode pair counts
+ <https://bugs.webkit.org/show_bug.cgi?id=19424>
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.cpp:
+ (KJS::OpcodeStats::OpcodeStats):
+ (KJS::compareOpcodeIndices):
+ (KJS::compareOpcodePairIndices):
+ (KJS::OpcodeStats::~OpcodeStats):
+ (KJS::OpcodeStats::recordInstruction):
+ (KJS::OpcodeStats::resetLastInstruction):
+ * VM/Opcode.h:
+
+2008-06-06 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+ profiler.
+ - Change the remaining functions that do not take arguments, from using
+ recursion to using iteration.
+
+ * JavaScriptCore.exp:
+ * profiler/Profile.cpp:
+ (KJS::stopProfiling):
+ (KJS::restoreAll):
+ (KJS::Profile::stopProfiling): Use foreach instead of recursion.
+ (KJS::Profile::restoreAll): Ditto.
+ * profiler/Profile.h:
+ * profiler/ProfileNode.cpp: Remove recursion.
+ (KJS::ProfileNode::stopProfiling):
+ (KJS::ProfileNode::restore):
+ * profiler/ProfileNode.h:
+
+2008-06-05 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey.
+
+ Fix Greater and GreaterEq nodes to emit code for the left
+ and right sub-expressions in the correct order.
+
+ * kjs/nodes.cpp:
+ (KJS::GreaterNode::emitCode):
+ (KJS::GreaterEqNode::emitCode):
+
+2008-06-05 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Alp Toker.
+
+ Fix whitespaces.
+
+ * kjs/collector.cpp:
+ (KJS::getPlatformThreadRegisters):
+
+2008-06-05 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Darin.
+
+ Support compiling JavaScriptCore for ARM.
+
+ * kjs/collector.cpp:
+ (KJS::getPlatformThreadRegisters):
+ (KJS::otherThreadStackPointer):
+
+2008-06-05 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Jon.
+
+ - Name changes.
+
+ * JavaScriptCore.exp:
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile):
+ (KJS::Profile::stopProfiling):
+ (KJS::Profile::didExecute):
+ (KJS::Profile::forEach):
+ (KJS::Profile::debugPrintData):
+ (KJS::Profile::debugPrintDataSampleStyle):
+ * profiler/Profile.h:
+ (KJS::Profile::callTree):
+ (KJS::Profile::totalTime):
+ (KJS::Profile::sortTotalTimeDescending):
+ (KJS::Profile::sortTotalTimeAscending):
+ (KJS::Profile::sortSelfTimeDescending):
+ (KJS::Profile::sortSelfTimeAscending):
+ (KJS::Profile::sortCallsDescending):
+ (KJS::Profile::sortCallsAscending):
+ (KJS::Profile::sortFunctionNameDescending):
+ (KJS::Profile::sortFunctionNameAscending):
+ (KJS::Profile::focus):
+ (KJS::Profile::exclude):
+ (KJS::Profile::restoreAll):
+
+2008-06-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Stephanie Lewis.
+
+ Added the -fno-move-loop-invariants flag to the pcre_exec.cpp build, to
+ tell GCC not to perform loop invariant motion, since GCC's loop
+ invariant motion doesn't do very well with computed goto code.
+
+ SunSpider reports no change.
+
+2008-06-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Stephanie Lewis.
+
+ Added the -fno-tree-pre flag to the Machine.cpp build, to tell GCC not
+ to perform Partial Redundancy Elimination (PRE) on trees in Machine.cpp,
+ since GCC's PRE doesn't do very well with computed goto code.
+
+ SunSpider reports a .7% speedup.
+
+2008-06-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Stephanie Lewis (or maybe the other way around).
+
+ Minor change to PCRE to help out certain compilers.
+
+ SunSpider reports no change, maybe a small speedup.
+
+ * pcre/pcre_exec.cpp:
+ (match): Use instructionPtr++ a little less, to avoid confusing the
+ optimizer.
+
+2008-06-05 Alexey Proskuryakov <ap@webkit.org>
+
+ Re-landing an independent part of a previously rolled out threading patch.
+
+ * wtf/ThreadSpecific.h: Make sure to initialize POD thread-specific varaibles, too
+ (replaced "new T" with "new T()").
+
+2008-06-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Hyatt.
+
+ - force inlining of a template function that only has one call site per specialization
+ 1.3% speedup on SunSpider
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate): This template function is only
+ called from allocate() and allocateNumber() (once per
+ specialization) and the extra call overhead for GC allocation
+ shows up, so force inlining.
+
+2008-06-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Alexey and Oliver.
+
+ - remove profiler fetch hack
+ I measure an 0.5% progression from this, others show a wash. It seems not needed any more.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-06-05 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 19400: subscript operator does not protect base when necessary
+ <https://bugs.webkit.org/show_bug.cgi?id=19400>
+
+ Use a temporary for the base in BracketAccessorNode if the subscript
+ might possibly modify it.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::BracketAccessorNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::BracketAccessorNode::):
+
+2008-06-04 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Maciej Stachowiak.
+
+ Big cleanup of formatting and whitespace.
+
+2008-06-04 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Add an option to dump statistics on executed instructions.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.cpp:
+ (KJS::OpcodeStats::~OpcodeStats):
+ (KJS::OpcodeStats::recordInstruction):
+ * VM/Opcode.h:
+
+2008-06-04 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+ profiler.
+ - This patch removes the use of recursion for the sort functions.
+
+ * JavaScriptCore.exp: Change the signatures of the functions being
+ exported.
+ * profiler/Profile.cpp:
+ (KJS::Profile::sort): This generic function will accept any of the
+ static sort functions and apply them to the whole tree.
+ * profiler/Profile.h: All of the sorting functions now call the new
+ sort() function.
+ (KJS::Profile::sortTotalTimeDescending):
+ (KJS::Profile::sortTotalTimeAscending):
+ (KJS::Profile::sortSelfTimeDescending):
+ (KJS::Profile::sortSelfTimeAscending):
+ (KJS::Profile::sortCallsDescending):
+ (KJS::Profile::sortCallsAscending):
+ (KJS::Profile::sortFunctionNameDescending):
+ (KJS::Profile::sortFunctionNameAscending):
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode): m_head used to point to the head node
+ if this was the head node. It now points to null to make iteration easy
+ (KJS::ProfileNode::willExecute): Now must check if m_head is null, this
+ check used to happend in the constructor.
+ (KJS::ProfileNode::stopProfiling): Again the check is slightly different
+ to determine if this is the head.
+ (KJS::ProfileNode::traverseNextNode): This function returns the next
+ node in post order.
+ (KJS::ProfileNode::sort): This generic function will sort according to
+ the comparator passed in, then reset the children pointers to macth the
+ new order.
+ * profiler/ProfileNode.h: The sorting function were removed from the
+ definition file and instead use the new generic sort() function
+ (KJS::ProfileNode::totalPercent): because the head can now be empty we
+ need to check here too for the head node.
+ (KJS::ProfileNode::selfPercent): Ditto
+ (KJS::ProfileNode::firstChild): This function is necessary for the
+ iterative algorithm in Profile.cpp.
+ (KJS::ProfileNode::sortTotalTimeDescending):
+ (KJS::ProfileNode::sortTotalTimeAscending):
+ (KJS::ProfileNode::sortSelfTimeDescending):
+ (KJS::ProfileNode::sortSelfTimeAscending):
+ (KJS::ProfileNode::sortCallsDescending):
+ (KJS::ProfileNode::sortCallsAscending):
+ (KJS::ProfileNode::sortFunctionNameDescending):
+ (KJS::ProfileNode::sortFunctionNameAscending):
+ (KJS::ProfileNode::childrenBegin):
+ (KJS::ProfileNode::childrenEnd):
+ (KJS::ProfileNode::totalTimeDescendingComparator):
+ (KJS::ProfileNode::totalTimeAscendingComparator):
+ (KJS::ProfileNode::selfTimeDescendingComparator):
+ (KJS::ProfileNode::selfTimeAscendingComparator):
+ (KJS::ProfileNode::callsDescendingComparator):
+ (KJS::ProfileNode::callsAscendingComparator):
+ (KJS::ProfileNode::functionNameDescendingComparator):
+ (KJS::ProfileNode::functionNameAscendingComparator):
+
+2008-06-04 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Fix JSClassCreate to work with old JSCore API threading model.
+
+ No change on SunSpider.
+
+ * API/JSClassRef.cpp: (OpaqueJSClass::OpaqueJSClass): Since JSClass is constructed without
+ a context, there is no way for it to create Identifiers.
+ Also, added initializeThreading(), just for good measure.
+
+ * API/JSCallbackObjectFunctions.h: (KJS::::getPropertyNames): Make an Identifier out of the
+ string here, because propertyNames.add() needs that.
+
+ * kjs/identifier.cpp:
+ * kjs/identifier.h:
+ (KJS::Identifier::equal):
+ * kjs/ustring.cpp:
+ (KJS::equal):
+ Moved equal() from identifier.h to ustring.h, because it's not really about Identifiers,
+ and to make it possible to use it from StrHash.
+ Include StrHash.h from ustring.h to avoid having the behavior depend on headers that happen
+ to be included.
+
+ * wtf/StrHash.h: Removed.
+ * kjs/ustring.h: Made RefPtr<UString::Rep> use the same default hash as UString::Rep* (it
+ used to default to pointer equality). Moved the whole StrHash header into ustring.h.
+
+ * JavaScriptCore.exp: Export equal() for WebCore use (this StrHash is used in c_class.cpp,
+ jni_class.cpp, and npruntime.cpp).
+
+2008-06-04 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Darin.
+
+ Fix spacing in collector.{h,cpp}.
+
+ * kjs/collector.cpp:
+ * kjs/collector.h:
+
+2008-06-03 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Build fix. The cleanup in r34355 missed a method.
+
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+
+2008-06-03 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19269
+ speed up SunSpider by eliminating the toObject call for most get/put/delete
+
+ Makes standalone SunSpider 1.025x as fast as before.
+
+ The getOwnPropertySlot virtual function now takes care of the toObject call
+ for get. Similarly, the put function (and later deleteProperty) does the
+ same for those operations. To do this, the virtual functions were moved from
+ the JSObject class to the JSCell class. Also, since the caller no longer knows
+ the identity of the "original object", which is used by JavaScript-function
+ based getters, changed the PropertySlot class so the original object is
+ already stored in the slot when getOwnPropertySlot is called, if the caller
+ intends to call getValue.
+
+ This affected the old interpreter code enough that the easiest thing for me
+ was to just delete it. While I am not certain the mysterious slowdown is not
+ still occurring, the net change is definitely a significant speedup.
+
+ * JavaScriptCore.exp: Updated.
+
+ * VM/Machine.cpp: Moved the UNLIKELY macro into AlwaysInline.h.
+ (KJS::resolve): Set up the originalObject in the PropertySlot before
+ calling getPropertySlot. Also removed the originalObject argument from
+ getValue.
+ (KJS::resolve_skip): Ditto.
+ (KJS::resolveBaseAndProperty): Ditto.
+ (KJS::resolveBaseAndFunc): Ditto.
+ (KJS::Machine::privateExecute): Removed the toObject calls from the get and
+ put functions where possible, instead calling directly with JSValue and letting
+ the JSValue and JSCell calls handle toObject. Same for toThisObject.
+
+ * kjs/ExecState.h: Removed OldInterpreterExecState.
+
+ * API/JSBase.cpp: Updated includes.
+
+ * kjs/LocalStorageEntry.h: Removed contents. Later we can remove the file too.
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::lengthGetter): Removed originalObject argumet.
+ (KJS::ArrayInstance::inlineGetOwnPropertySlot): Don't pass a base value to
+ setValueSlot. Also use UNLIKELY around the "getting elements past the end of
+ the array" code path; less common than successfully getting an element.
+
+ * kjs/array_object.cpp:
+ (KJS::getProperty): Initialize the PropertySlot with the original object.
+ Don't pass the original object to the get function.
+ (KJS::arrayProtoFuncFilter): Ditto.
+ (KJS::arrayProtoFuncMap): Ditto.
+ (KJS::arrayProtoFuncEvery): Ditto.
+ (KJS::arrayProtoFuncForEach): Ditto.
+ (KJS::arrayProtoFuncSome): Ditto.
+
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct): Removed an obsolete comment.
+
+ * kjs/grammar.y: Eliminated support for some of the node types that were
+ used to optimize executing from the syntax tree.
+
+ * kjs/internal.cpp:
+ (KJS::StringImp::toThisObject): Added. Same as toObject.
+ (KJS::NumberImp::toThisObject): Ditto.
+ (KJS::GetterSetterImp::getOwnPropertySlot): Added. Not reached.
+ (KJS::GetterSetterImp::put): Ditto.
+ (KJS::GetterSetterImp::toThisObject): Ditto.
+
+ * kjs/internal.h: Added toThisObject to NumberImp for speed.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::shift): Changed shift to just do a single character, to unroll
+ the loop and especially to make the one character case faster.
+ (KJS::Lexer::setCode): Call shift multiple times instead of passing a number.
+ (KJS::Lexer::lex): Ditto.
+ (KJS::Lexer::matchPunctuator): Ditto. Also removed unneeded elses after returns.
+ (KJS::Lexer::scanRegExp): Ditto.
+ * kjs/lexer.h: Removed the count argument from shift.
+
+ * kjs/math_object.cpp:
+ (KJS::mathProtoFuncPow): Call jsNaN instead of jsNumber(NaN).
+
+ * kjs/nodes.cpp: Removed some of the things needed only for the pre-SquirrelFish
+ execution model.
+ (KJS::ForNode::emitCode): Handle cases where some expressions are missing by
+ not emitting any code at all. The old way was to emit code for "true", but
+ this is an unnecessary remnant of the old way of doing things.
+
+ * kjs/nodes.h: Removed some of the things needed only for the pre-SquirrelFish
+ execution model.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::fillGetterPropertySlot): Changed to only pass in the getter
+ function. The old code passed in a base, but it was never used when
+ actually getting the property; the toThisObject call was pointless. Also
+ changed to not pass a base for setUndefined.
+
+ * kjs/object.h: Added the new JSCell operations to GetterSetterImp.
+ Never called.
+ (KJS::JSObject::get): Initialize the object in the PropertySlot and don't
+ pass it in getValue.
+ (KJS::JSObject::getOwnPropertySlotForWrite): Removed the base argument
+ in calls to setValueSlot.
+ (KJS::JSObject::getOwnPropertySlot): Ditto.
+ (KJS::JSValue::get): Added. Here because it calls through to JSObject.
+ A version of JSObject::get that also handles the other types of JSValue
+ by creating the appropriate wrapper. Saves the virtual call to toObject.
+ (KJS::JSValue::put): Ditto.
+ (KJS::JSValue::deleteProperty): Ditto.
+
+ * kjs/property_slot.cpp:
+ (KJS::PropertySlot::undefinedGetter): Removed the originalObject argument.
+ (KJS::PropertySlot::ungettableGetter): Ditto.
+ (KJS::PropertySlot::functionGetter): Ditto. Use the value in the base
+ as the "this" object, which will be set to the original object by the new
+ PropertySlot initialization code. Also call toThisObject. The old code did
+ not do this, but needed to so we can properly handle the activation object
+ like the other similar code paths.
+
+ * kjs/property_slot.h:
+ (KJS::PropertySlot::PropertySlot): Added a constructor that takes a base
+ object. In debug builds, set the base to 0 if you don't pass one.
+ (KJS::PropertySlot::getValue): Don't take or pass the originalObject.
+ (KJS::PropertySlot::setValueSlot): Don't take a base object, and clear the
+ base object in debug builds.
+ (KJS::PropertySlot::setGetterSlot): Ditto.
+ (KJS::PropertySlot::setUndefined): Ditto.
+ (KJS::PropertySlot::setUngettable): Ditto.
+ (KJS::PropertySlot::slotBase): Assert that a base object is present.
+ This will fire if someone actually calls the get function without having
+ passed in a base object and the getter needs it.
+ (KJS::PropertySlot::setBase): Added. Used by the code that implements
+ toObject so it can supply the original object after the fact.
+ (KJS::PropertySlot::clearBase): Added. Clears the base, but is debug-only
+ code because it's an error to fetch the base if you don't have a guarantee
+ it was set.
+
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::JSCallbackObject::cachedValueGetter):
+ (KJS::JSCallbackObject::staticValueGetter):
+ (KJS::JSCallbackObject::staticFunctionGetter):
+ (KJS::JSCallbackObject::callbackGetter):
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::getOwnPropertySlot):
+ (KJS::JSActivation::argumentsGetter):
+ * kjs/JSActivation.h:
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet):
+ * kjs/array_instance.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::argumentsGetter):
+ (KJS::FunctionImp::callerGetter):
+ (KJS::FunctionImp::lengthGetter):
+ (KJS::Arguments::mappedIndexGetter):
+ * kjs/function.h:
+ * kjs/lookup.h:
+ (KJS::staticFunctionGetter):
+ (KJS::staticValueGetter):
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::lengthGetter):
+ (KJS::StringInstance::indexGetter):
+ (KJS::stringInstanceNumericPropertyGetter):
+ * kjs/string_object.h:
+ Removed originalObject arguments from getters. Don't pass base values to
+ the various PropertySlot functions that no longer take them.
+
+ * kjs/value.cpp:
+ (KJS::JSCell::getOwnPropertySlot): Added. Calls toObject and then sets the slot.
+ This function has to always return true, because the caller can't walk the prototype
+ chain. Because of that, we do a getPropertySlot, not getOwnPropertySlot, which works
+ for the caller. This is private, only called by getOwnPropertySlotInternal.
+ (KJS::JSCell::put): Added. Calls toObject and then put.
+ (KJS::JSCell::toThisObject): Added. Calls toObject.
+
+ * kjs/value.h: Added get, put, and toThisObject to both JSValue
+ and JSCell. These take care of the toObject operation without an additional virtual
+ function call, and so make the common "already an object" case faster.
+
+ * wtf/AlwaysInline.h: Moved the UNLIKELY macro here for now. Maybe we can find a
+ better place later, or rename this header.
+
+2008-06-03 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Tim.
+
+ Bug 12983: Web Inspector break on the debugger keyword
+ <https://bugs.webkit.org/show_bug.cgi?id=12983>
+
+ Added a DebuggerStatementNode to handle codegen, and added a new
+ DidReachBreakPoint debug event (which will hopefully be useful
+ if we ever move breakpoint management into JSC proper). Also
+ added didReachBreakpoint to Debugger to allow us to actually respond
+ to this event.
+
+ * VM/CodeBlock.cpp:
+ (KJS::debugHookName):
+ * VM/Machine.cpp:
+ (KJS::Machine::debug):
+ * VM/Machine.h:
+ * kjs/debugger.h:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::DebuggerStatementNode::emitCode):
+ (KJS::DebuggerStatementNode::execute):
+ * kjs/nodes.h:
+ (KJS::DebuggerStatementNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::DebuggerStatementNode::streamTo):
+
+2008-06-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - document remaining opcodes.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Document call, call_eval,
+ construct, ret and end opcodes.
+
+2008-06-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Document throw and catch opcodes.
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Removed JSObject::call, since it just called JSObject::callAsFunction.
+
+ SunSpider reports no change.
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ A little cleanup in the CodeGenerator.
+
+ * VM/CodeGenerator.cpp: A few changes here.
+
+ (1) Removed remaining cases of the old hack of putting "this" into the
+ symbol table; replaced with explicit tracking of m_thisRegister.
+
+ (2) Made m_thisRegister behave the same for function, eval, and program
+ code, removing the static programCodeThis() function.
+
+ (3) Added a feature to nix a ScopeNode's declaration stacks when done
+ compiling, to save memory.
+
+ (4) Removed code that copied eval declarations into special vectors: we
+ just use the originals in the ScopeNode now.
+
+ * VM/CodeGenerator.h: Removed unneded parameters from the CodeGenerator
+ constructor: we just use get that data from the ScopeNode now.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute): When executing an eval node, don't iterate a
+ special copy of its declarations; iterate the originals, instead.
+
+ * kjs/nodes.cpp: Moved responsibility for knowing what AST data to throw
+ away into the CodeGenerator. Nodes no longer call shrinkCapacity on
+ their data directly.
+
+ * kjs/nodes.h: Changed FunctionStack to ref its contents, so declaration
+ data stays around even after we've thrown away the AST, unless we explicitly
+ throw away the declaration data, too. This is useful for eval code, which
+ needs to reference its declaration data at execution time. (Soon, it will
+ be useful for program code, too, since program code should do the same.)
+
+2008-06-02 Adam Roben <aroben@apple.com>
+
+ Build fix for non-AllInOne builds
+
+ * kjs/array_object.cpp: Added a missing #include.
+
+2008-06-02 Kevin McCullough <kmccullough@apple.com>
+
+ Took out accidental confilct lines I checked in.
+
+ * ChangeLog:
+
+2008-06-02 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5969992> JSProfiler: Remove the recursion limit in the
+ profiler
+ Implement Next Sibling pointers as groundwork for removing the recursion
+ limit in the profiler.
+
+ * profiler/ProfileNode.cpp: Also I renamed parentNode and headNode since
+ 'node' is redundant.
+ (KJS::ProfileNode::ProfileNode): Initialize the nextSibling.
+ (KJS::ProfileNode::willExecute): If there are already children then the
+ new child needs to be the nextSibling of the last child.
+ (KJS::ProfileNode::didExecute):
+ (KJS::ProfileNode::addChild): Ditto.
+ (KJS::ProfileNode::stopProfiling):
+ (KJS::ProfileNode::sortTotalTimeDescending): For all of the sorting
+ algorithms once the children are sorted their nextSibling pointers need
+ to be reset to reflect the new order.
+ (KJS::ProfileNode::sortTotalTimeAscending):
+ (KJS::ProfileNode::sortSelfTimeDescending):
+ (KJS::ProfileNode::sortSelfTimeAscending):
+ (KJS::ProfileNode::sortCallsDescending):
+ (KJS::ProfileNode::sortCallsAscending):
+ (KJS::ProfileNode::sortFunctionNameDescending):
+ (KJS::ProfileNode::sortFunctionNameAscending):
+ (KJS::ProfileNode::resetChildrensSiblings): This new function simply
+ loops over all of the children and sets their nextSibling pointers to
+ the next child in the Vector
+ (KJS::ProfileNode::debugPrintData):
+ * profiler/ProfileNode.h:
+ (KJS::ProfileNode::parent):
+ (KJS::ProfileNode::setParent):
+ (KJS::ProfileNode::nextSibling):
+ (KJS::ProfileNode::setNextSibling):
+ (KJS::ProfileNode::totalPercent):
+ (KJS::ProfileNode::selfPercent):
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Removed the recursion limit from JSObject::call, since the VM does
+ recursion checking now.
+
+ This should allow us to remove JSObject::call entirely, netting a small
+ speedup.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Adele Peterson.
+
+ Added a specific affordance for avoiding stack overflow when converting
+ recursive arrays to string, in preparation for removing generic stack
+ overflow checking from JSObject::call.
+
+ Tested by fast/js/toString-stack-overflow.html.
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Alice Liu.
+
+ Refactored some hand-rolled code to call ScopeChain::globalObject instead.
+
+2008-06-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed ASSERT due to execution continuing after an exception is thrown
+ during array sort.
+
+ * kjs/array_instance.cpp:
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key): Don't call the
+ custom comparator function if an exception has been thrown. Just return
+ 1 for everything, so the sort completes quickly. (The result will be
+ thrown away.)
+
+2008-05-30 Timothy Hatcher <timothy@apple.com>
+
+ Made the starting line number of scripts be 1-based throughout the engine.
+ This cleans up script line numbers so they are all consistent now and fixes
+ some cases where script execution was shown as off by one line in the debugger.
+
+ No change in SunSpider.
+
+ Reviewed by Oliver Hunt.
+
+ * API/minidom.c:
+ (main): Pass a line number of 1 instead of 0 to parser().parse().
+ * API/testapi.c:
+ (main): Ditto. And removes a FIXME and changed an assertEqualsAsNumber
+ to use 1 instead of 2 for the line number.
+ * VM/Machine.cpp:
+ (KJS::callEval): Pass a line number of 1 instead of 0.
+ (KJS::Machine::debug): Use firstLine for WillExecuteProgram instead of
+ lastLine. Use lastLine for DidExecuteProgram instead of firstLine.
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::evaluate): Pass a line number of 1 instead of
+ 0 to parser().parse().
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse): ASSERT startingLineNumber is greatter than 0. Change
+ the startingLineNumber to be 1 if it was less than or equal to 0. This is needed
+ for release builds to maintain compatibility with the JavaScriptCore API.
+ * kjs/function.cpp:
+ (KJS::globalFuncEval): Pass a line number of 1 instead of 0 to parser().parse().
+ * kjs/function_object.cpp:
+ (FunctionObjectImp::construct): Pass a line number of 1 instead of 0 to construct().
+ * kjs/lexer.cpp:
+ (Lexer::setCode): Made yylineno = startingLineNumber instead of adding 1.
+ * kjs/testkjs.cpp:
+ (functionRun): Pass a line number of 1 instead of 0 to Interpreter::evaluate().
+ (functionLoad): Ditto.
+ (prettyPrintScript): Ditto.
+ (runWithScripts): Ditto.
+ * profiler/Profiler.cpp:
+ (WebCore::createCallIdentifier): Removed a plus 1 of startingLineNumber.
+
+2008-05-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up SunSpider by optimizing immediate number cases
+
+ Also fixed a JavaScriptCore regression seen on PowerPC - we didn't clip left shift
+ parameter to 0...31.
+
+ 0.5% improvement on SunSpider overall, although a 8.5 regression on bitops-3bit-bits-in-byte.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::toTruncatedUInt32): Added. Same as getTruncatedInt32, but casts the result
+ to unsigned.
+
+2008-05-30 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up SunSpider by optimizing immediate number cases
+
+ Also fixed two JavaScriptCore regressions seen on PowerPC - we didn't clip right shift
+ parameter to 0...31.
+
+ 1.6% improvement on SunSpider, without significant regressions on any tests.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ Added fast paths for >>, ==, ===, !=, !==. Changed order of memory accesses in many
+ cases, making them less dependent on gcc's ability to properly assign registers. With this,
+ I could move exception checks back into slow code paths, and saw less randomness in general.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::rightShiftImmediateNumbers):
+ Added.
+
+2008-05-29 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fixed <rdar://problem/5972943> REGRESSION(r33979): Flash clips do not play on cnn.com
+
+ Finally blocks could clobber registers that had to remain live
+ until they returned. This patch takes a conservative approach and
+ makes sure that finally blocks do not reuse any registers that
+ were previously allocated for the function. In the future this
+ could probably be tightened up to be less profligate with the
+ register allocation.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::highestUsedRegister):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::TryNode::emitCode):
+
+2008-05-29 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * kjs/array_instance.cpp:
+
+2008-05-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19294
+ <rdar://problem/5969062> A crash when iterating over a sparse array backwards.
+
+ * kjs/array_instance.cpp: Turned sparseArrayCutoff into a macro, so that using max() on it
+ doesn't cause a PIC branch.
+ (KJS::ArrayInstance::increaseVectorLength): Added a comment about this function not
+ preserving class invariants.
+ (KJS::ArrayInstance::put): Update m_storage after reallocation. Move values that fit to
+ the vector from the map in all code paths.
+
+2008-05-29 Thiago Macieira <tjmaciei@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fix compilation in Solaris with Sun CC
+
+ Lots of WebKit code uses C99 functions that, strict as it
+ is, the Solaris system doesn't provide in C++. So we must define them
+ for both GCC and the Sun CC.
+
+ * wtf/MathExtras.h:
+
+2008-05-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Anders.
+
+ Fix codegen for assignment being used as a function.
+
+ FunctionCallValueNode::emitCode failed to account for the
+ potential of the function expression to allocate arbitrary
+ registers.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallValueNode::emitCode):
+
+2008-05-27 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ Fixed https://bugs.webkit.org/show_bug.cgi?id=19183
+ REGRESSION (r33979): Crash in DebuggerCallFrame::functionName when
+ clicking button in returnEvent-crash.html
+
+ Added two new debugger hooks, willExecuteProgram and didExecuteProgram,
+ along with code to generate them, code to invoke them when unwinding
+ due to an exception, and code to dump them.
+
+ SunSpider reports no change.
+
+ * VM/CodeBlock.cpp:
+ (KJS::debugHookName): I had to mark this function NEVER_INLINE to avoid
+ a .4% performance regression. The mind boggles.
+
+2008-05-28 Adam Roben <aroben@apple.com>
+
+ Fix JavaScriptCore tests on OS X
+
+ We were quoting the path to testkjs too late, after it had already
+ been combined with spaces and other options.
+
+ * tests/mozilla/jsDriver.pl:
+ (top level): Move path quoting from here...
+ (sub get_kjs_engine_command): ...to here.
+
+2008-05-28 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Oliver.
+
+ <rdar://problem/5968071> "const f" crashes in JavaScriptCore
+
+ Make sure to null check the initializer.
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::emitCodeSingle):
+
+2008-05-28 Adam Roben <aroben@apple.com>
+
+ Make run-javascriptcore-tests work with a space in the path to testkjs
+
+ Reviewed by Alexey Proskuryakov.
+
+ * tests/mozilla/jsDriver.pl: Quote the path to the engine so that
+ spaces will be interpreted correctly.
+
+2008-05-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Fixed a misguiding comment - my measurement for negative numbers only included cases
+ where both operands were negative, which is not very interesting.
+
+ * VM/Machine.cpp:
+
+2008-05-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Maciej.
+
+ Based on a patch by Oliver Hunt.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up SunSpider by optimizing immediate number cases
+
+ 1.4% speedup on SunSpider.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::incImmediateNumber):
+ (KJS::JSImmediate::decImmediateNumber):
+ Added fast paths for ++ and --.
+
+ (KJS::JSImmediate::canDoFastAdditiveOperations): Corrected a comment.
+
+2008-05-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up SunSpider by optimizing immediate number cases
+
+ 2% speedup overall, maximum 10% on controlflow-recursive and bitops-3bit-bits-in-byte,
+ but a 4% regression on bitops-bits-in-byte and bitops-bitwise-and.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::canDoFastAdditiveOperations):
+ (KJS::JSImmediate::addImmediateNumbers):
+ (KJS::JSImmediate::subImmediateNumbers):
+ Added fast cases that work with positive values less than 2^30.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Use the above operations. Also updated SunSpider frequencies
+ with my results (looks like tag values have changed, not sure what caused the minor variation
+ in actual frequencies).
+
+2008-05-27 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ Remove code that appended Cygwin's /bin directory to PATH.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj:
+ Prepend Cygwin's /bin directory to PATH. We prepend instead of append
+ so that Cygwin's utilities will win out over Win32 versions of the
+ same utilities (particularly perl). We do the prepend here instead of
+ in the Makefile because nmake doesn't seem to like prepending to PATH
+ inside the Makefile. This also matches the way WebCoreGenerated works.
+
+2008-05-27 Adam Roben <aroben@apple.com>
+
+ Roll out r34163
+
+ A better fix is on the way.
+
+ * DerivedSources.make:
+ * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh:
+
+2008-05-27 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * DerivedSources.make: Don't generate the bytecode docs if
+ OMIT_BYTECODE_DOCS is set to 1.
+ * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Set
+ OMIT_BYTECODE_DOCS for production builds.
+
+2008-05-27 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Geoff and Maciej.
+
+ <rdar://problem/5806428>
+ https://bugs.webkit.org/show_bug.cgi?id=17925
+ Crash in KJS::JSObject::put after setting this.__proto__
+
+ Set slotIsWriteable to false for __proto__, we want setting __proto__ to go through JSObject::put instead.
+
+ * kjs/object.h:
+ (KJS::JSObject::getOwnPropertySlotForWrite):
+
+2008-05-27 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fixes to catch up with SquirrelFish, etc.
+
+ * JavaScriptCoreSources.bkl:
+ * jscore.bkl:
+ * wtf/Platform.h:
+
+2008-05-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up SunSpider by optimizing immediate number cases
+
+ Add immediate number cases for the &, |, and ^ operators.
+ Makes standalone SunSpider 1.010x faster.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Add areBothImmediateNumbers special cases
+ for the &, |, and ^ operators.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::xorImmediateNumbers): Added.
+ (KJS::JSImmediate::orImmediateNumbers): Added.
+
+2008-05-26 Stephanie Lewis <slewis@apple.com>
+
+ Windows build fix.
+
+ * kjs/testkjs.cpp:
+
+2008-05-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Anders.
+
+ - make addStaticGlobals protected instead of private so subclasses can use it
+
+ * JavaScriptCore.exp:
+ * kjs/JSGlobalObject.h:
+
+2008-05-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed <rdar://problem/5960859> After an eval of a non-string or a syntax
+ error, all profile stack frames are incorrect
+
+ SunSpider reports a .3% speedup, possibly because eval of a string is a
+ little more efficient now.
+
+ * VM/Machine.cpp:
+ (KJS::callEval): Make sure to call didExecute when returning early. I
+ simplified this function to remove one early return, making the job
+ of adding special code to early returns easier.
+
+ (KJS::Machine::execute): Use the new function ExecState when notifying
+ the profiler. (This doesn't change behavior now, but it might prevent
+ subtle errors in the future.)
+
+2008-05-23 Tor Arne Vestbø <tavestbo@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fixed toLower and toUpper implementations to allow being called
+ with a null result pointer and resultLength, to determine the
+ number of characters needed for the case conversion.
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::toLower):
+ (WTF::Unicode::toUpper):
+
+2008-05-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Fixing a typo in the previous commit made as a last minute change.
+
+ * kjs/regexp_object.cpp:
+
+2008-05-24 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Changed regular expression matching result array to be lazily filled, because many callers
+ only care about it being non-null.
+
+ 2% improvement on Acid3 test 26.
+
+ * kjs/array_instance.cpp: Added a void* member to ArrayStorage for ArrayInstance subclasses
+ to use.
+ * kjs/array_instance.h:
+ (KJS::ArrayInstance::lazyCreationData):
+ (KJS::ArrayInstance::setLazyCreationData):
+ Added methods to access it from subclasses.
+
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpMatchesArray::RegExpMatchesArray):
+ (KJS::RegExpMatchesArray::getOwnPropertySlot):
+ (KJS::RegExpMatchesArray::put):
+ (KJS::RegExpMatchesArray::deleteProperty):
+ (KJS::RegExpMatchesArray::getPropertyNames):
+ (KJS::RegExpMatchesArray::fillArrayInstanceIfNeeded):
+ (KJS::RegExpMatchesArray::~RegExpMatchesArray):
+ (KJS::RegExpObjectImp::arrayOfMatches):
+ RegExpMatchesArray is a subclass of ArrayInstance that isn't filled until
+ accessed for the first time.
+
+2008-05-24 Alp Toker <alp@nuanti.com>
+
+ Win32/gcc build fix. Remove MSVC assumption.
+
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SlowLock):
+
+2008-05-24 Oleg Finkelshteyn <olegfink@gmail.com>
+
+ Rubber-stamped, tweaked and landed by Alexey.
+
+ Build fix for gcc 4.3.
+
+ * JavaScriptCore/kjs/testkjs.cpp:
+ * JavaScriptCore/VM/CodeBlock.cpp:
+ Add missing standard includes.
+
+2008-05-23 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Geoff.
+
+ <rdar://problem/5959886> REGRESSION: Assertion failure in JSImmediate::toString when loading GMail (19217)
+
+ Change List to store a JSValue*** pointer + an offset instead of a JSValue** pointer to protect against the case where
+ a register file changes while a list object points to its buffer.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject):
+ * kjs/list.cpp:
+ (KJS::List::getSlice):
+ * kjs/list.h:
+ (KJS::List::List):
+ (KJS::List::at):
+ (KJS::List::append):
+ (KJS::List::begin):
+ (KJS::List::end):
+ (KJS::List::buffer):
+
+2008-05-23 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5960012> JSProfiler: Stack overflow if recursion is
+ too deep.
+ -Use a simple depth limit to restrict too deep of recursion.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::willExecute):
+ (KJS::Profile::didExecute):
+ * profiler/Profile.h:
+
+2008-05-23 Geoffrey Garen <ggaren@apple.com>
+
+ Rolling back in r34085, with performance resolved.
+
+ Apparently, passing the eval function to callEval gave GCC a hernia.
+
+ Reviewed by Darin Adler, Kevin McCullough, and Oliver Hunt.
+
+ Fixed <rdar://problem/5959447> Crashes and incorrect reporting in the
+ JavaScript profiler
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame): Fixed incorrect reporting / a crash
+ when unwinding from inside eval and/or program code: detect the
+ difference, and do the right thing. Also, be sure to notify the profiler
+ *before* deref'ing the scope chain, since the profiler uses the scope chain.
+
+ (KJS::Machine::execute): Fixed incorrect reporting / crash when calling
+ a JS function re-entrently: Machine::execute(FunctionBodyNode*...)
+ should not invoke the didExecute hook, because op_ret already does that.
+ Also, use the new function's ExecState when calling out to the profiler.
+ (Not important now, but could have become a subtle bug later.)
+
+ (KJS::Machine::privateExecute): Fixed a hard to reproduce crash when
+ profiling JS functions: notify the profiler *before* deref'ing the scope
+ chain, since the profiler uses the scope chain.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::call): Removed these hooks, because they are now unnecessary.
+
+ * profiler/Profile.cpp: Added a comment to explain a subtlety that only
+ Kevin and I understood previously. (Now, the whole world can understand!)
+
+ * profiler/Profiler.cpp:
+ (KJS::shouldExcludeFunction): Don't exclude .call and .apply. That was
+ a hack to fix bugs that no longer exist.
+
+ Finally, sped things up a little bit by changing the "Is the profiler
+ running?" check into an ASSERT, since we only call into the profiler
+ when it's running:
+
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+
+2008-05-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ - fixed <rdar://problem/5957662> REGRESSION(r33943-r33980): Can't send email , attach file or save as draft from hotmail.com
+
+ SunSpider reports no change.
+
+ This is a reworking of r34073, which I rolled out because it caused
+ lots of crashes.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator): Use removeDirect to nix old
+ properties whose names collide with new functions. (Don't use putWithAttributes
+ because that tries to write to the register file, which hasn't grown to
+ fit this program yet.)
+
+2008-05-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ As allocateNumber is used via jsNumberCell outside of JavaScriptCore,
+ we need to provide a non-inlined version of it to avoid creating a
+ weak external symbol.
+
+ * JavaScriptCore.exp:
+ * kjs/AllInOneFile.cpp:
+ * kjs/collector.cpp:
+ (KJS::Collector::allocate):
+ (KJS::Collector::allocateNumber):
+ * kjs/collector.h:
+ (KJS::Collector::allocate):
+ (KJS::Collector::inlineAllocateNumber):
+ * kjs/value.h:
+ (KJS::NumberImp::operator new):
+
+2008-05-23 Geoffrey Garen <ggaren@apple.com>
+
+ Rolled out r34073 because it caused lots of layout test crashes.
+
+2008-05-23 Geoffrey Garen <ggaren@apple.com>
+
+ Rolled out r34085 because it measured as a 7.6% performance regression.
+
+2008-05-23 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add the
+ profiler directory to the include path.
+
+2008-05-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Anders.
+
+ SQUIRRELFISH: JavaScript error messages are missing informative text
+
+ Partial fix.
+ Tidy up error messages, makes a couple of them provide slightly more info.
+ Inexplicably leads to a 1% SunSpider Progression.
+
+ * VM/ExceptionHelpers.cpp:
+ (KJS::createError):
+ (KJS::createInvalidParamError):
+ (KJS::createNotAConstructorError):
+ (KJS::createNotAFunctionError):
+ * VM/ExceptionHelpers.h:
+ * VM/Machine.cpp:
+ (KJS::isNotObject):
+
+2008-05-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Tim H.
+
+ Fix call stack reported by profiler when entering event handlers.
+
+ JSObject::call was arbitrarily notifying the profiler when it was
+ called, even if it was JS code, which notifies the profile on entry
+ in any case.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+
+2008-05-16 Alp Toker <alp@nuanti.com>
+
+ Build fix for gcc 3. Default constructor required in ExecState,
+ used by OldInterpreterExecState.
+
+ * kjs/ExecState.h:
+ (KJS::ExecState::ExecState):
+
+2008-05-23 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix <rdar://problem/5954997> global-recursion-on-full-stack.html crashes under guardmalloc.
+
+ Growing the register file with uncheckedGrow from within Machine::execute is not safe as the
+ register file may be too close to its maximum size to grow successfully. By using grow,
+ checking the result and throwing a stack overflow error we can avoid crashing.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFile.h: Remove the now-unused uncheckedGrow.
+
+2008-05-23 Oliver Hunt <oliver@apple.com>
+
+ RS=Kevin McCullough
+
+ Remove JAVASCRIPT_PROFILER define
+
+ * VM/Machine.cpp:
+ (KJS::callEval):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * kjs/config.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+
+2008-05-23 Oliver Hunt <oliver@apple.com>
+
+ <rdar://problem/5951561> Turn on JavaScript Profiler
+
+ Reviewed by Kevin McCullough.
+
+ Flipped the switch on the profiler, rearranged how we
+ signal the the profiler is active so that calls aren't
+ needed in the general case.
+
+ Also fixed the entry point for Machine::execute(FunctionBodyNode..)
+ to correctly indicate function exit.
+
+ Results in a 0.7-1.0% regression in SunSpider :-(
+
+ * VM/Machine.cpp:
+ (KJS::callEval):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * kjs/config.h:
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::profiler):
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::stopProfiling):
+ * profiler/Profiler.h:
+ (KJS::Profiler::enabledProfilerReference):
+
+2008-05-23 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Qt build by adding profiler/ to the include search path.
+
+ * JavaScriptCore.pri:
+
+2008-05-22 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ Fix a bug in the profiler where time in the current function is given to
+ (idle).
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::didExecute): Set the start time and then call didExecute
+ to calculate the time spent in this function.
+ * profiler/ProfileNode.cpp: Remove confusing calculations that are no
+ longer necessary.
+ (KJS::ProfileNode::insertNode):
+ * profiler/ProfileNode.h: Expose access to the start time to allow the
+ simpler time calculations above.
+ (KJS::ProfileNode::startTime):
+ (KJS::ProfileNode::setStartTime):
+
+2008-05-22 Adam Roben <aroben@apple.com>
+
+ Show "(Function object)" instead of "(JSInpectorCallbackWrapper
+ object)" in profiles
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/Profiler.cpp:
+ (KJS::createCallIdentifier): Use JSObject::className instead of
+ getting the class name from the ClassInfo directly. JSObject
+ subclasses can override className to provide a custom class name, and
+ it seems like we should honor that.
+
+2008-05-22 Timothy Hatcher <timothy@apple.com>
+
+ Added Profile::restoreAll and added ProfileNode::restoreAll
+ to the export file.
+
+ Reviewed by Adam Roben.
+
+ * JavaScriptCore.exp:
+ * profiler/Profile.h:
+
+2008-05-22 Alp Toker <alp@nuanti.com>
+
+ GTK+ build fix. Add JavaScriptCore/profiler to include path.
+
+ * GNUmakefile.am:
+
+2008-05-22 Adam Roben <aroben@apple.com>
+
+ Implement sub-millisecond profiling on Windows
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/ProfileNode.cpp:
+ (KJS::getCount): Added. On Windows, we use QueryPerformanceCounter. On
+ other platforms, we use getCurrentUTCTimeWithMicroseconds.
+ (KJS::ProfileNode::endAndRecordCall): Use getCount instead of
+ getCurrentUTCTimeWithMicroseconds.
+ (KJS::ProfileNode::startTimer): Ditto.
+
+2008-05-22 Adam Roben <aroben@apple.com>
+
+ Fix a profiler assertion when calling a NodeList as a function
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/Profiler.cpp:
+ (KJS::createCallIdentifier): Don't assert when a non-function object
+ is called as a function. Instead, build up a CallIdentifier using the
+ object's class name.
+
+2008-05-22 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5951529> JSProfiler: Allow the profiler to "Exclude" a
+ profile node.
+ -Implement 'exclude'; where the excluded node attributes its time to its
+ parent's self time.
+
+ * JavaScriptCore.exp: Export the exclude function.
+ * profiler/Profile.h:
+ (KJS::Profile::exclude):
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::setTreeVisible): New function that allows a change in
+ visiblitiy to be propogated to all the children of a node.
+ (KJS::ProfileNode::exclude): If the node matches the callIdentifier then
+ set the visiblity of this node and all of its children to false and
+ attribute it's total time to it's caller's self time.
+ * profiler/ProfileNode.h:
+
+2008-05-22 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix access to static global variables in Windows release builds.
+
+ * kjs/JSGlobalObject.h: Don't store a reference to an Identifier
+ in GlobalPropertyInfo as the Identifier is likely to be a temporary
+ and therefore may be destroyed before the GlobalPropertyInfo.
+
+2008-05-22 Kevin McCullough <kmccullough@apple.com>
+
+ Build fix.
+
+ * VM/Machine.cpp:
+ (KJS::callEval):
+
+2008-05-22 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5951561> Turn on JavaScript Profiler
+ Get basic JS profiling working.
+ Even with this patch the profiler will not be compiled in because we do
+ not know the extend, if any, of the performance regression it would cause
+ when it is not in use. However with these changes, if the profiler were
+ on, it would not crash and show good profiling data.
+
+ * VM/Machine.cpp: Instrument the calls sites that are needed for profiling.
+ (KJS::callEval):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * kjs/function.cpp: Ditto.
+ (KJS::globalFuncEval):
+ * kjs/interpreter.cpp: Ditto.
+ (KJS::Interpreter::evaluate):
+ * profiler/Profile.cpp:
+ (KJS::Profile::willExecute):
+ (KJS::Profile::didExecute): Because we do not get a good context when
+ startProfiling is called it is possible that m_currentNode will be at the
+ top of the known stack when a didExecute() is called. What we then do is
+ create a new node that represents the function being exited and insert
+ it between the head and the currently known children, since they should
+ be children of this new node.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode):
+ (KJS::ProfileNode::willExecute): Rename the add function for consistency.
+ (KJS::ProfileNode::addChild): Appends the child to this node but also
+ sets the parent pointer of the children to this node.
+ (KJS::ProfileNode::insertNode): Insert a node between this node and its
+ children. Also set the time for the new node since it is now exiting
+ and we don't really know when it started.
+ (KJS::ProfileNode::stopProfiling):
+ (KJS::ProfileNode::startTimer):
+ * profiler/ProfileNode.h:
+ (KJS::CallIdentifier::toString): Added for debugging.
+ (KJS::ProfileNode::setParent):
+ (KJS::ProfileNode::setSelfTime): Fixed an old bug where we set the
+ visibleTotalTime not the visibleSelfTime.
+ (KJS::ProfileNode::children):
+ (KJS::ProfileNode::toString): Added for debugging.
+ * profiler/Profiler.cpp: remove unecessary calls.
+ (KJS::Profiler::startProfiling):
+
+2008-05-22 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Rename register arguments for op_call, op_call_eval, op_end, and op_construct
+ to document what they are for.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall):
+ (KJS::CodeGenerator::emitCallEval):
+ (KJS::CodeGenerator::emitEnd):
+ (KJS::CodeGenerator::emitConstruct):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-05-22 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Bug 19116: SquirrelFish shouldn't regress on variable lookups
+ <https://bugs.webkit.org/show_bug.cgi?id=19116>
+
+ Last of the multiscope look up optimisations. This is a wash overall on SunSpider
+ but is a factor of 5-10 improvement in multiscope read/write/modify (eg. ++, --, +=,
+ ... applied to any non-local var).
+
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+
+2008-05-22 David Kilzer <ddkilzer@apple.com>
+
+ <rdar://problem/5954233> Add method to release free memory from FastMalloc
+
+ Patch suggested by Mark Rowe. Rubber-stamped by Maciej.
+
+ * JavaScriptCore.exp: Export _releaseFastMallocFreeMemory.
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMallocStats::): Added releaseFastMallocFreeMemory() for both
+ system malloc and FastMalloc code paths.
+ * wtf/FastMalloc.h: Define releaseFastMallocFreeMemory().
+
+2008-05-22 Oliver Hunt <oliver@apple.com>
+
+ RS=Maciej.
+
+ Roll out r34020 as it causes recursion tests to fail.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+
+2008-05-22 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Mark.
+
+ Don't leak the SymbolTable when compiling eval code.
+
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::generateCode):
+
+2008-05-22 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Oliver.
+
+ Qt build fix.
+
+ * JavaScriptCore.pri: Added DebuggerCallFrame to the build.
+ * VM/LabelID.h: Include limits.h for UINT_MAX.
+ * wtf/VectorTraits.h: Include memory for std::auto_ptr.
+
+2008-05-22 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Removed the old recursion guard mechanism, since squirrelfish has its
+ own mechanism. Also removed some old JS call tracing code, since we
+ have other ways to do that, too.
+
+ SunSpider reports no change.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+
+2008-05-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fixed <rdar://problem/5954979> crash on celtic kane JS benchmark
+
+ * kjs/nodes.cpp:
+ (KJS::WithNode::emitCode):
+ (KJS::TryNode::emitCode):
+
+2008-05-21 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Maciej and Geoff.
+
+ <rdar://problem/5951561> Turn on JavaScript Profiler
+ -As part of the effort to turn on the profiler it would be helpful if it
+ did not need ExecStates to represent the stack location of the currently
+ executing statement.
+ -We now create each node as necessary with a reference to the current
+ node and each node knows its parent so that the tree can be made without
+ the entire stack.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile): The current node starts at the head.
+ (KJS::Profile::stopProfiling): The current node is cleared when profiling
+ stops.
+ (KJS::Profile::willExecute): The current node either adds a new child or
+ starts and returns a reference to an already existing child if the call
+ ID that is requested already exists.
+ (KJS::Profile::didExecute): The current node finishes and returns its
+ parent.
+ * profiler/Profile.h: Use a single callIdentifier instead of a vector
+ since we no longer use the whole stack.
+ * profiler/ProfileNode.cpp: Now profile nodes keep a reference to their
+ parent.
+ (KJS::ProfileNode::ProfileNode): Initialize the parent.
+ (KJS::ProfileNode::didExecute): Record the time and return the parent.
+ (KJS::ProfileNode::addOrStartChild): If the given callIdentifier is
+ already a child, start it and return it, otherwise create a new one and
+ return that.
+ (KJS::ProfileNode::stopProfiling): Same logic, just use the new function.
+ * profiler/ProfileNode.h: Utilize the parent.
+ (KJS::ProfileNode::create):
+ (KJS::ProfileNode::parent):
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::startProfiling): Here is the only place where the
+ ExecState is used to figure out where in the stack the profiler is
+ currently profiling.
+ (KJS::dispatchFunctionToProfiles): Only send one CallIdentifier instead
+ of a vector of them.
+ (KJS::Profiler::willExecute): Ditto.
+ (KJS::Profiler::didExecute): Ditto.
+ (KJS::createCallIdentifier): Create only one CallIdentifier.
+ (KJS::createCallIdentifierFromFunctionImp): Ditto.
+ * profiler/Profiler.h:
+
+2008-05-21 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - https://bugs.webkit.org/show_bug.cgi?id=19180
+ speed up the < operator for the case when both values are integers
+
+ Makes standalone SunSpider 1.022x faster.
+
+ * VM/Machine.cpp:
+ (KJS::jsLess): Add a special case for when both are numbers that fit in a JSImmediate.
+
+2008-05-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver and Sam.
+
+ - fixed <rdar://problem/5815631> REGRESSION (r31239): Multiscope optimisation of function calls results in incorrect this value (breaks tvtv.de)
+
+ Track global this value in the scope chain so we can retrieve it
+ efficiently but it follows lexical scope properly.
+
+ * kjs/ExecState.h:
+ (KJS::ExecState::globalThisValue):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+ * kjs/scope_chain.h:
+ (KJS::ScopeChainNode::ScopeChainNode):
+ (KJS::ScopeChainNode::globalThisObject):
+ (KJS::ScopeChainNode::push):
+ (KJS::ScopeChain::ScopeChain):
+
+2008-05-21 Kevin McCullough <kmccullough@apple.com>
+
+ Sadness :(
+
+ * kjs/config.h:
+
+2008-05-21 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Maciej.
+
+ <rdar://problem/5950867> JSProfiler: Allow the profiler to "Focus" a
+ profile node.
+ - This patch updatest the times of the visible nodes correctly, but to do
+ so, some of the design of the ProfileNode changed.
+
+ * JavaScriptCore.exp: export focus' symbol.
+ * profiler/Profile.cpp: ProfileNodes now take a reference to the head of
+ the profile tree to get up-to-date accurate total profile time.
+ (KJS::Profile::Profile): Pass 0 for the head node.
+ (KJS::Profile::stopProfiling): stopProfiling no longer needs the time
+ passed into it, since it can get it from the head and it does not need to
+ be told it is the head because it can figure it out on it's own.
+ (KJS::Profile::willExecute): Set the head node for each created node.
+ * profiler/Profile.h:
+ (KJS::Profile::focus): Instead of taking a CallIdentifier that the caller
+ would have to create, now focus() takes a ProfileNode that they should
+ already have a reference to and focus() can extract the CallIdentifier
+ from it.
+ * profiler/ProfileNode.cpp: Create actual and visible versions fo the
+ total and self times for focus and exclude. Also add a head node
+ reference so that nodes can get information from their head.
+ (KJS::ProfileNode::ProfileNode):
+ (KJS::ProfileNode::stopProfiling): Rename the total and self time
+ variables and set the visual ones to the actual ones, so that without any
+ changes to the visual versions of these variables, their times will match
+ the actual times.
+ (KJS::ProfileNode::focus): Now focus() has a bool to force it's children
+ to be visible if this node is visible. If this node does not match the
+ CallIdentifier being focused then the visibleTotalTime is only updated if
+ one or more of it's children is the CallIdentifier being focused.
+ (KJS::ProfileNode::restoreAll): Restores all variables with respect to
+ the visible data in the ProfileNode.
+ (KJS::ProfileNode::endAndRecordCall): Name change.
+ (KJS::ProfileNode::debugPrintData): Dump the new variables.
+ (KJS::ProfileNode::debugPrintDataSampleStyle): Name change.
+ * profiler/ProfileNode.h: Use the new variables and reference to the head
+ node.
+ (KJS::ProfileNode::create):
+ (KJS::ProfileNode::totalTime):
+ (KJS::ProfileNode::setTotalTime):
+ (KJS::ProfileNode::selfTime):
+ (KJS::ProfileNode::setSelfTime):
+ (KJS::ProfileNode::totalPercent):
+ (KJS::ProfileNode::selfPercent):
+ (KJS::ProfileNode::setVisible):
+
+2008-05-21 Alp Toker <alp@nuanti.com>
+
+ GTK+/UNIX testkjs build fix. Include signal.h.
+
+ * kjs/testkjs.cpp:
+
+2008-05-21 Oliver Hunt <oliver@apple.com>
+
+ Yet more windows build fixes
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-05-21 Oliver Hunt <oliver@apple.com>
+
+ Yet more windows build fixes
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-05-21 Alp Toker <alp@nuanti.com>
+
+ GTK+ build fix. Add DebuggerCallFrame.cpp and take AllInOneFile.cpp
+ changes into account.
+
+ * GNUmakefile.am:
+
+2008-05-21 Oliver Hunt <oliver@apple.com>
+
+ Add DebuggerCallFrame.{h,cpp} to the project file
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-05-21 Alp Toker <alp@nuanti.com>
+
+ GTK+ port build fixes following squirrelfish merge r33979.
+
+ * GNUmakefile.am:
+
+2008-05-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - save a hash lookup wne writing to global properties
+ 0.3% speedup on SunSpider, 7% on bitops-bitwise-and
+
+ * VM/Machine.cpp:
+ (KJS::resolveBase): Check for being a the end of the scope chain
+ before hash lookup.
+
+2008-05-21 Alp Toker <alp@nuanti.com>
+
+ Rubber-stamped by Maciej.
+
+ Replace non-standard #pragma marks with comments to avoid compiler
+ warnings.
+
+ * profiler/ProfileNode.cpp:
+
+2008-05-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ Fix layout test failure in fast/dom/getter-on-window-object2 introduced in r33961.
+
+ * JavaScriptCore.exp:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::defineGetter):
+ (KJS::JSGlobalObject::defineSetter):
+ * kjs/JSGlobalObject.h:
+
+=== End merge of squirrelfish ===
+
+2008-05-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ Merged with trunk WebCore's new debugger.
+
+ * kjs/DebuggerCallFrame.cpp:
+ (KJS::DebuggerCallFrame::evaluate): Changed this function to separate
+ the exception value from the return value. The WebKit debugger treats
+ them as one, but the WebCore debugger doesn't.
+
+ * kjs/DebuggerCallFrame.h:
+ (KJS::DebuggerCallFrame::dynamicGlobalObject): Added a new accessor for
+ the dynamic global object, since the debugger doesn't want the lexical
+ global object.
+
+2008-05-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 19116: SquirrelFish shouldn't regress on variable lookups
+ <https://bugs.webkit.org/show_bug.cgi?id=19116>
+
+ Optimise cross scope assignment, 0.4% progression in sunspider.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPutScopedVar):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::AssignResolveNode::emitCode):
+
+2008-05-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - check property map before symbol table in JSGlobalObject::getOwnPropertySlot
+ 0.5% speedup on SunSpider
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::getOwnPropertySlot): Check property map before symbol table
+ because symbol table access is likely to have been optimized.
+
+2008-05-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 19116: SquirrelFish shouldn't regress on variable lookups
+ <https://bugs.webkit.org/show_bug.cgi?id=19116>
+
+ Optimise multiscope lookup of statically resolvable function calls.
+ SunSpider reports a 1.5% improvement, including 37% on
+ controlflow-recursive for some reason :D
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitResolve):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::emitCode):
+
+2008-05-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - give JSGlobalObject a special version of getOwnPropertySlot that tells you if the slot is directly writable
+ (WebCore change using this is a 2.6% speedup on in-browser SunSpider).
+
+ * JavaScriptCore.exp:
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::getOwnPropertySlot):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet):
+ * kjs/object.h:
+ (KJS::JSObject::getDirectLocation):
+ (KJS::JSObject::getOwnPropertySlotForWrite):
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::getLocation):
+ * kjs/property_map.h:
+ * kjs/property_slot.h:
+ (KJS::PropertySlot::putValue):
+
+2008-05-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 19116: SquirrelFish shouldn't regress on variable lookups
+ <https://bugs.webkit.org/show_bug.cgi?id=19116>
+
+ This restores multiscope optimisation to simple resolve, producing
+ a 2.6% progression in SunSpider. Have verified that none of the
+ sites broken by the multiscope optimisation in trunk were effected
+ by this change.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeBlock.h:
+ (KJS::CodeBlock::CodeBlock):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::findScopedProperty):
+ (KJS::CodeGenerator::emitResolve):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::resolve_n):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/JSVariableObject.h:
+
+2008-05-20 Oliver Hunt <oliver@apple.com>
+
+ Fixerate the windows build.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * VM/CodeGenerator.cpp:
+ * VM/RegisterFile.h:
+ * kjs/JSGlobalObject.h:
+ * kjs/Parser.cpp:
+ * kjs/interpreter.h:
+
+2008-05-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 19110: SquirrelFish: Google Maps - no maps
+ <https://bugs.webkit.org/show_bug.cgi?id=19110>
+
+ Correct a comedy of errors present in my original patch to "fix"
+ exceptions occurring midway through pre and post increment. This
+ solution is cleaner than the original, doesn't need the additional
+ opcodes, and as an added benefit does not break Google Maps.
+
+ Sunspider reports a 0.4% progression.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+
+2008-05-20 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - inline JSGlobalObject::getOwnPropertySlot
+ 1% improvement on in-browser SunSpider (a wash command-line)
+
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::getOwnPropertySlot):
+
+2008-05-18 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
+ <https://bugs.webkit.org/show_bug.cgi?id=18752>
+
+ Handle exceptions thrown by toString conversion in subscript operators,
+ this should basically complete exception handling in SquirrelFish.
+
+ Sunspider reports no regression.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-05-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ [Reapplying patch with previously missing files from r33553 -- Oliver]
+
+ Behold: debugging.
+
+ SunSpider reports no change.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Added DebuggerCallFrame.h/.cpp,
+ and created a debugger folder.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::generate): If the debugger is attached, always
+ generate full scope chains for its sake.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame): Notify the debugger when unwinding
+ due to an exception, so it doesn't keep stale call frames around.
+
+ (KJS::Machine::execute): Set Callee to 0 in eval frames, so the
+ debugger can distinguish them from function call frames.
+
+ (KJS::Machine::debug): Simplified this function, since the debugger
+ doesn't actually need all the information we used to provide.
+
+ (KJS::Machine::privateExecute): Treat debugging hooks like other function
+ calls, so the code we hook into (the debugger UI) can be optimized.
+
+ * kjs/debugger.cpp: Nixed these default callback implementations and
+ made the callbacks pure virtual instead, so the compiler could tell me
+ if I made a mistake in one of the subclasses.
+
+ * kjs/debugger.h: Removed a bunch of irrelevent data from the debugger
+ callbacks. Changed from passing an ExecState* to passing a
+ DebuggerCallFrame*, since an ExecState* doesn't contain sufficient
+ information anymore.
+
+ * kjs/function.cpp:
+ (KJS::globalFuncEval): Easiest bug fix evar!
+
+ [Previously missing files from r33553]
+ * kjs/DebuggerCallFrame.cpp: Copied from JavaScriptCore/profiler/FunctionCallProfile.h.
+ (KJS::DebuggerCallFrame::functionName):
+ (KJS::DebuggerCallFrame::thisObject):
+ (KJS::DebuggerCallFrame::evaluateScript):
+ * kjs/DebuggerCallFrame.h: Copied from JavaScriptCore/VM/Register.h.
+ (KJS::DebuggerCallFrame::DebuggerCallFrame):
+ (KJS::DebuggerCallFrame::scopeChain):
+ (KJS::DebuggerCallFrame::exception):
+
+2008-05-17 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18991: SquirrelFish: Major codegen issue in a.b=expr, a[b]=expr
+ <https://bugs.webkit.org/show_bug.cgi?id=18991>
+
+ Fix the last remaining blocking cases of this bug.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ReadModifyResolveNode::emitCode):
+
+2008-05-17 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Partial fix for:
+
+ Bug 18991: SquirrelFish: Major codegen issue in a.b=expr, a[b]=expr
+ <https://bugs.webkit.org/show_bug.cgi?id=18991>
+
+ Ensure that the code generated for assignments uses temporaries whenever
+ necessary. This patch covers the vast majority of situations, but there
+ are still a few left.
+
+ This patch also adds some missing cases to CodeBlock::dump().
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::destinationForAssignResult):
+ (KJS::CodeGenerator::leftHandSideNeedsCopy):
+ (KJS::CodeGenerator::emitNodeForLeftHandSide):
+ * kjs/NodeInfo.h:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ (KJS::ForInNode::ForInNode):
+ * kjs/nodes.h:
+ (KJS::ReadModifyResolveNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::ReadModifyBracketNode::):
+ (KJS::AssignBracketNode::):
+ (KJS::AssignDotNode::):
+ (KJS::ReadModifyDotNode::):
+
+2008-05-17 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 19106: SquirrelFish: Activation is not marked correctly
+ <https://bugs.webkit.org/show_bug.cgi?id=19106>
+
+ We can't rely on the symbol table for a count of the number of globals
+ we need to mark as that misses duplicate parameters and 'this'. Now we
+ use the actual local register count from the codeBlock.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::mark):
+
+2008-05-16 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 19076: SquirrelFish: RegisterFile can be corrupted if implictly reenter global scope with no declared vars
+ <https://bugs.webkit.org/show_bug.cgi?id=19076>
+
+ Don't delay allocation of initial global RegisterFile, as we can't guarantee we will be able
+ to allocate the global 'this' register safely at any point after initialisation of the Global
+ Object.
+
+ Unfortunately this initial allocation caused a regression of 0.2-0.3%, however this patch adds
+ support for the static slot optimisation for the global Math object which brings it to a 0.3%
+ progression.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::programCodeThis):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::addParameter):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * kjs/ExecState.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::GlobalPropertyInfo::GlobalPropertyInfo):
+ (KJS::JSGlobalObject::addStaticGlobals):
+ * kjs/nodes.cpp:
+
+2008-05-16 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver Hunt.
+
+ Bug 19098: SquirrelFish: Ref'd temporaries can be clobbered
+ <https://bugs.webkit.org/show_bug.cgi?id=19098>
+
+ When doing code generation for a statement list, increase the reference
+ count on a register that might eventually be returned, so that it doesn't
+ get clobbered by a request for a new temporary.
+
+ * kjs/nodes.cpp:
+ (KJS::statementListEmitCode):
+
+2008-05-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fixed Bug 19044: SquirrelFish: Bogus values enter evaluation when closing over scope with parameter and var with same name
+ https://bugs.webkit.org/show_bug.cgi?id=19044
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::copyRegisters): Use numLocals from the code
+ block rather than the size of the symbol table for the number of
+ registers to copy, to account for duplicate parameters and vars
+ with the same name as parameters (we still have potentially
+ suboptimal codegen in that we allocate a local register for the
+ var in the latter case but it is never used).
+
+2008-05-15 Geoffrey Garen <ggaren@apple.com>
+
+ Not reviewed.
+
+ We regret to inform you that your program is crashing because you were
+ stupid.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Math is hard.
+
+2008-05-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more debugger action: filled in op_debug. All debugger control
+ flow works now, but variable inspection and backtraces still don't.
+
+ SunSpider reports no change.
+
+ * VM/CodeGenerator.cpp: Changed op_debug to accept line number parameters.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::getFunctionAndArguments): Moved op_debug into a
+ NEVER_INLINE function to avoid a stunning 10% performance regression.
+ Also factored out a common function for retrieving the function and
+ arguments from a call frame.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject): Use the new factored out
+ function mentioned above.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse): Increment m_sourceId before assigning it, so the
+ sourceId we send to the debugger matches the sourceId recorded in the
+ node.
+
+ * kjs/nodes.cpp: Emit debugging hooks.
+
+2008-05-14 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 19024: SQUIRRELFISH: ASSERTION FAILED: activation->isActivationObject() in Machine::unwindCallFrame
+ <https://bugs.webkit.org/show_bug.cgi?id=19024>
+
+ This fixes a number of issues. The most important is that we now check every register
+ file for tainting rather than just looking for function register files as that was
+ insufficient. Additionally guarded against implicit re-entry into Eval code.
+
+ Also added a few additional assertions to reduce the amout of time between something
+ going wrong and us seeing the error.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::growBuffer):
+ (KJS::RegisterFile::addGlobalSlots):
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushGlobalRegisterFile):
+ (KJS::RegisterFileStack::pushFunctionRegisterFile):
+ * VM/RegisterFileStack.h:
+ (KJS::RegisterFileStack::inImplicitCall):
+
+2008-05-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more debugger action: emit opcodes for debugger hooks. Right
+ now, the opcode implementation is just a stub.
+
+ SunSpider reports no change.
+
+ Some example codegen for "function f() { 1; }":
+
+ [ 0] dbg DidEnterCallFrame
+ [ 2] dbg WillExecuteStatement
+ [ 4] load tr0, 1(@k0)
+ [ 7] load tr0, undefined(@k1)
+ [ 10] dbg WillLeaveCallFrame
+ [ 12] ret tr0
+
+2008-05-14 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 19025: SQUIRRELFISH: malformed syntax in onload handler causes crash
+ <https://bugs.webkit.org/show_bug.cgi?id=19025>
+
+ Simple fix -- move the use of functionBodyNode to after the null check.
+
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed a codegen crash with run-time parse errors.
+
+ SunSpider reports no change.
+
+ emitThrowError needs to return the temporary holding the error, not dst,
+ since dst may be NULL. In fact, emitThrowError shouldn't take a dst
+ parameter at all, since exceptions should not modify the destination
+ register.
+
+2008-05-13 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 19027: SquirrelFish: Incorrect codegen for pre-increment
+ <https://bugs.webkit.org/show_bug.cgi?id=19027>
+
+ This fixes the codegen issues for the pre-inc/decrement operators
+ to prevent incorrectly clobbering the destination in the event of
+ an exception.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPreInc):
+ (KJS::CodeGenerator::emitPreDec):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more debugger action: supply a real line number, sourceId,
+ and sourceURL in op_new_error.
+
+ SunSpider reports a .2% speedup. Not sure what that's about.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Use the new good stuff in op_new_error.
+
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::emitCode): Use the shared emitThrowError instead of
+ rolling our own.
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more debugger action: implemented the exception callback.
+
+ SunSpider reports a .2% speedup. Not sure what that's about.
+
+ * VM/CodeBlock.h: A little refactoring here. Store a pointer to our
+ owner ScopeNode so we can retrieve data from it. This allows us to
+ stop storing copies of the data ourselves. Also, store a "this" register
+ instead of a code type, since we were only using the code type to
+ calculate the "this" register.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::generate): Calculate the "this" register mentioned
+ above. Also, take care of removing "this" from the symbol table after
+ codegen is done, since relying on the timing of a destructor for correct
+ behavior is not so good.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::throwException): Invoke the debugger's exception callback.
+ (KJS::Machine::privateExecute): Use the "this" register mentioned above.
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed some unused exception machinery.
+
+ SunSpider reports a .3% speedup.
+
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/internal.cpp:
+ * kjs/object.cpp:
+ * kjs/object.h:
+ * kjs/value.h:
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more debugger action.
+
+ * kjs/debugger.cpp:
+ * kjs/debugger.h: Removed debuggersPresent because it was unused.
+ Replaced AttachedGlobalObject linked list with a HashSet because HashSet
+ is faster and simpler. Changed all functions to return void instead of
+ bool, because no clients ever return false, and we don't want to support
+ it.
+
+ * kjs/nodes.cpp: Did some up-keep to avoid build bustage.
+ (KJS::Node::handleException):
+ (KJS::BreakpointCheckStatement::execute):
+ (KJS::FunctionBodyNodeWithDebuggerHooks::execute):
+
+2008-05-13 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
+ <https://bugs.webkit.org/show_bug.cgi?id=18752>
+
+ Replace old attempt at "branchless" exceptions as the extra information
+ being passed made gcc an unhappy compiler, replacing these custom toNumber
+ calls with ordinary toNumber logic (by relying on toNumber now preventing
+ side effects after an exception has been thrown) provided sufficient leeway
+ to add the additional checks for the remaining unchecked cases.
+
+ This leaves only toString conversions in certain contexts as possibly
+ misbehaving.
+
+ * VM/Machine.cpp:
+ (KJS::jsAdd):
+ (KJS::resolve):
+ (KJS::resolveBaseAndProperty):
+ (KJS::resolveBaseAndFunc):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/value.h:
+ (KJS::JSValue::safeGetNumber):
+
+2008-05-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ First steps toward supporting the debugger API: support the sourceParsed
+ callback; plus some minor fixups.
+
+ SunSpider reports no regression.
+
+ * VM/CodeGenerator.h: Removed a misleading comment.
+
+ * kjs/Parser.h: Changed the parser to take an ExecState*, so it can
+ implement the sourceParsed callback -- that way, we only have to
+ implement the callback in one place.
+
+ * kjs/debugger.cpp: Nixed DebuggerImp, because its sole purpose in life
+ was to demonstrate the misapplication of design patterns.
+
+ * kjs/debugger.h: Changed sourceParsed to take a SourceProvider, to
+ reduce copying, and not to return a value, because pausing execution
+ after parsing is complicated, and no clients needed that ability, anyway.
+
+ * kjs/grammar.y: Make sure never to pass a NULL SourceElements* to
+ didFinishParsing -- that simplifies some code down the road.
+
+ * kjs/nodes.cpp: Don't generate special AST nodes just because the
+ debugger is attached -- that's a relic of the old AST execution model,
+ and those nodes haven't been maintained.
+
+2008-05-13 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18752: SQUIRRELFISH: exceptions are not always handled by the vm
+ <https://bugs.webkit.org/show_bug.cgi?id=18752>
+
+ First step: prevent incorrect evaluation of valueOf/toString conversion
+ in right hand side of expression after earlier conversion throws.
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::toNumber):
+ * kjs/object.cpp:
+ (KJS::JSObject::defaultValue):
+
+2008-05-12 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18934: SQUIRRELFISH: ASSERT @ nytimes.com due to RegisterFile being clobbered
+ <https://bugs.webkit.org/show_bug.cgi?id=18934>
+
+ Unfortunately we cannot create new statically optimised globals if there are any
+ tainted RegisterFiles on the RegisterFileStack. To handle this we re-introduce
+ (in a slightly cleaner form) the inImplicitCall concept to the RegisterFileStack.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushFunctionRegisterFile):
+ * VM/RegisterFileStack.h:
+
+2008-05-12 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Introduced support for function.caller.
+
+ Improved support for walking interesting scopes for function introspection.
+
+ This fixes all remaining layout tests not blocked by rebasing to trunk.
+
+ SunSpider reports no change.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters): Fixed a spacing issue.
+
+2008-05-11 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18961: SQUIRRELFISH: Gmail doesn't load
+ <https://bugs.webkit.org/show_bug.cgi?id=18961>
+
+ Fix codegen for logical nodes so that they don't use their destination
+ as a temporary.
+
+ * kjs/nodes.cpp:
+ (KJS::LogicalAndNode::emitCode):
+ (KJS::LogicalOrNode::emitCode):
+
+2008-05-10 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - JavaScriptCore part of fix for: "SQUIRRELFISH: function toString broken after calling"
+ https://bugs.webkit.org/show_bug.cgi?id=18869
+
+ Three layout tests are fixed:
+ fast/js/toString-elision-trailing-comma.html
+ fast/js/toString-prefix-postfix-preserve-parens.html
+ fast/js/kde/lval-exceptions.html
+
+ Functions now save a shared subrange of the original source used
+ to make them (so in the common case this adds no storage above the
+ memory cache).
+
+ * kjs/SourceProvider.h: Added.
+ (KJS::SourceProvider): New abstract base class for classes that provide on-demand access
+ to the source for a JavaScript program. This allows function objects to have access to their
+ original source without copying.
+ (KJS::UStringSourceProvider): SourceProvider subclass backed by a KJS::UString.
+ (KJS::UStringSourceProvider::create):
+ (KJS::UStringSourceProvider::getRange):
+ (KJS::UStringSourceProvider::data):
+ (KJS::UStringSourceProvider::length):
+ (KJS::UStringSourceProvider::UStringSourceProvider):
+ * kjs/SourceRange.h: Added.
+ (KJS::SourceRange::SourceRange): Class that holds a SourceProvider and a character range into
+ the source, to encapsulate on-demand access to the source of a function.
+ (KJS::SourceRange::toString):
+ * VM/Machine.cpp:
+ (KJS::eval): Pass a UStringSourceProvider to the parser.
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse): Take a SourceProvider and pass it on to the lexer.
+ * kjs/Parser.h:
+ (KJS::Parser::parse): Take a SourceProvider.
+ * kjs/lexer.cpp:
+ (KJS::Lexer::setCode): Take a SourceProvider; keep it around, and
+ use it to get the raw buffer and length.
+ * kjs/lexer.h:
+ (KJS::Lexer::sourceRange): Convenience function to get a source
+ range based on the lexer's source provieder, and char offsets
+ right before and after the desired range.
+ * kjs/function.cpp:
+ (KJS::globalFuncEval): Pass a UStringSourceProvider to the parser.
+ * kjs/function_object.cpp:
+ (KJS::functionProtoFuncToString): Use toSourceString to get the source.
+ (KJS::FunctionObjectImp::construct): Give the parser a UStringSourceProvider.
+ * kjs/grammar.y: When parsing a function declaration, function
+ expression, or getter or setter, tell the function body about its
+ SourceRange.
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::checkSyntax): Pass a SourceProvider to the parser.
+ (KJS::Interpreter::evaluate): Pass a SourceProvider to the parser.
+ * kjs/interpreter.h:
+ * kjs/nodes.h:
+ (KJS::FunctionBodyNode::setSource): Establish a SourceRange for this function.
+ (KJS::FunctionBodyNode::toSourceString): Get the source string out
+ of the SourceRange.
+ (KJS::FuncExprNode::): Take a SourceRange and set it on the body.
+ (KJS::FuncDeclNode::): ditto
+ * kjs/testkjs.cpp:
+ (prettyPrintScript): Use a SourceProvider appropriately.
+ * JavaScriptCore.exp: Export new symbols.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add new files.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Add new files.
+
+2008-05-09 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bring back RegisterFile tainting in order to correctly handle
+ natively implemented getters and setters that re-enter JavaScript
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ * kjs/object.cpp:
+ (KJS::JSObject::put):
+ (KJS::tryGetAndCallProperty):
+ * kjs/property_slot.cpp:
+ (KJS::PropertySlot::functionGetter):
+
+2008-05-09 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - track character offsets of open and close braces, in preparation for saving function source
+
+ I verified that there is no performance regression from this change.
+
+ * kjs/grammar.y:
+ * kjs/lexer.cpp:
+ (KJS::Lexer::lex):
+ (KJS::Lexer::matchPunctuator):
+ * kjs/lexer.h:
+
+2008-05-09 Oliver Hunt <oliver@apple.com>
+
+ Debug build fix
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::restoreLocalStorage):
+
+2008-05-09 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Build fixes for SquirrelFish on windows.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+ * VM/Register.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::restoreLocalStorage):
+ * kjs/collector.cpp:
+ (KJS::Collector::allocate):
+ (KJS::Collector::allocateNumber):
+ * kjs/collector.h:
+ (KJS::Collector::allocate):
+ (KJS::Collector::allocateNumber):
+ * kjs/property_slot.cpp:
+
+2008-05-08 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix activation tearoff in the case where functions are called with too many arguments
+
+ Fixes:
+ fast/canvas/patternfill-repeat.html
+ fast/dom/SelectorAPI/bug-17313.html
+
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::scopeChainForCall):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+
+2008-05-08 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed failure in fast/canvas/canvas-pattern-behaviour.html.
+
+ SunSpider reports a small speedup. Not sure what that's about.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump): Fixed op_call_eval to dump as "op_call_eval".
+ This helped me while debugging.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame): When looking for an activation to tear
+ off, don't use the scope chain. Inside eval, the scope chain doesn't
+ belong to us; it belongs to our calling function.
+
+ Also, don't use the needsFullScopeChain flag to decide whether to tear
+ off the activation. "function.arguments" can create an activation
+ for a function whose needsFullScopeChain flag is set to false.
+
+2008-05-08 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix function.call for calls of more than 8 arguments
+
+ Fixes svg/carto.net/button.svg
+
+ * kjs/list.cpp:
+ (KJS::List::getSlice): properly set up the m_buffer of the target list.
+
+2008-05-08 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - don't return a null RegisterID from RegExpNode in the exception case, since the caller may need a real register
+
+ Fixes:
+ - fast/regex/early-acid3-86.html
+ - http/tests/misc/acid3.html
+
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::emitCode):
+
+2008-05-07 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Fix a performance regression caused by the introduction of property
+ attributes to SymbolTable in r32859 by encoding the attributes and the
+ register index into a single field of SymbolTableEntry.
+
+ This leaves Node::optimizeVariableAccess() definitely broken, although
+ it was probably not entirely correct in SquirrelFish before this change.
+
+ * VM/CodeBlock.h:
+ (KJS::missingThisObjectMarker):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::registerForLocal):
+ (KJS::CodeGenerator::registerForLocalConstInit):
+ (KJS::CodeGenerator::isLocalConstant):
+ (KJS::CodeGenerator::addConstant):
+ (KJS::CodeGenerator::emitCall):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::IdentifierMapIndexHashTraits::emptyValue):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::saveLocalStorage):
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames):
+ (KJS::JSVariableObject::getPropertyAttributes):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet):
+ (KJS::JSVariableObject::symbolTablePut):
+ (KJS::JSVariableObject::symbolTablePutWithAttributes):
+ * kjs/SymbolTable.h:
+ (KJS::SymbolTableEntry::SymbolTableEntry):
+ (KJS::SymbolTableEntry::isEmpty):
+ (KJS::SymbolTableEntry::getIndex):
+ (KJS::SymbolTableEntry::getAttributes):
+ (KJS::SymbolTableEntry::setAttributes):
+ (KJS::SymbolTableEntry::isReadOnly):
+ * kjs/nodes.cpp:
+ (KJS::getSymbolTableEntry):
+ (KJS::PostIncResolveNode::optimizeVariableAccess):
+ (KJS::PostDecResolveNode::optimizeVariableAccess):
+ (KJS::DeleteResolveNode::optimizeVariableAccess):
+ (KJS::TypeOfResolveNode::optimizeVariableAccess):
+ (KJS::PreIncResolveNode::optimizeVariableAccess):
+ (KJS::PreDecResolveNode::optimizeVariableAccess):
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::ProgramNode::initializeSymbolTable):
+
+2008-05-06 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Oliver.
+
+ - add missing ! in an assert that I failed to reverse
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+
+2008-05-06 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fixed "SQUIRRELFISH: window.this shows up as a property, but it shouldn't"
+ https://bugs.webkit.org/show_bug.cgi?id=18868
+
+ The basic approach is to have "this" only be present in the symbol
+ table at compile time, not runtime.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::~CodeGenerator): Remove "this" from symbol table.
+ (KJS::CodeGenerator::CodeGenerator): Add "this" back when re-using
+ a symbol table.
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute): Don't assert that "this" is in the symbol table.
+
+2008-05-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Trivial support for function.arguments: Currently, we only support
+ function.arguments from within the scope of function.
+
+ This fixes the remaining Mozilla JS test failures.
+
+ SunSpider reports no change.
+
+ * JavaScriptCore.exp:
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Separated scope chain deref from
+ activation register copying: since it is now possible for client code
+ to create an activation on behalf of a function that otherwise wouldn't
+ need one, having an activation no longer necessarily means that you need
+ to deref the scope chain.
+
+ (KJS::Machine::getCallFrame): For now, this function only examines the
+ current scope. Walking parent scopes requires some refactoring in the
+ way we track execution stacks.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState): We use a negative call frame offset to
+ indicate that a given scope is not a function call scope.
+
+2008-05-05 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Fix call frame set up for native -> JS function calls.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+
+2008-05-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed ecma_3/Object/8.6.2.6-001.js, and similar bugs.
+
+ SunSpider reports a .4% speedup. Not sure what that's about.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Check for exception return from equal,
+ since toPrimitive can throw.
+
+ * kjs/operations.cpp:
+ (KJS::strictEqual): In response to an error I made in an earlier version
+ of this patch, I changed strictEqual to make clear the fact that it
+ performs no conversions and can't throw, making it slightly more efficient
+ in the process.
+
+2008-05-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix some dumb mistakes in my last patch
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPushScope):
+ (KJS::CodeGenerator::emitGetPropertyNames):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-05-05 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - document opcodes relating to jumps, scopes, and property name iteration
+
+ Documented jmp, jtrue, false, push_scope, pop_scope, get_pnames,
+ next_pname and jmp_scopes.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJump):
+ (KJS::CodeGenerator::emitJumpIfTrue):
+ (KJS::CodeGenerator::emitJumpIfFalse):
+ (KJS::CodeGenerator::emitPushScope):
+ (KJS::CodeGenerator::emitNextPropertyName):
+ (KJS::CodeGenerator::emitGetPropertyNames):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.cpp:
+ (KJS::LogicalAndNode::emitCode):
+ (KJS::LogicalOrNode::emitCode):
+ (KJS::ConditionalNode::emitCode):
+ (KJS::IfNode::emitCode):
+ (KJS::IfElseNode::emitCode):
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::ForInNode::emitCode):
+ (KJS::WithNode::emitCode):
+
+2008-05-05 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18749: SQUIRRELFISH: const support is broken
+ <https://bugs.webkit.org/show_bug.cgi?id=18749>
+
+ Adds support for const during code generation.
+
+ Fixes 2 layout tests.
+
+ * ChangeLog:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::isLocalConstant):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::addVar):
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+
+2008-05-04 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - document some more opcodes (and fix argument names)
+
+ Added docs for eq, neq, stricteq, nstriceq, less and lesseq.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitEqual):
+ (KJS::CodeGenerator::emitNotEqual):
+ (KJS::CodeGenerator::emitStrictEqual):
+ (KJS::CodeGenerator::emitNotStrictEqual):
+ (KJS::CodeGenerator::emitLess):
+ (KJS::CodeGenerator::emitLessEq):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.cpp:
+ (KJS::LessNode::emitCode):
+ (KJS::GreaterNode::emitCode):
+ (KJS::LessEqNode::emitCode):
+ (KJS::GreaterEqNode::emitCode):
+ (KJS::EqualNode::emitCode):
+ (KJS::NotEqualNode::emitCode):
+ (KJS::StrictEqualNode::emitCode):
+ (KJS::NotStrictEqualNode::emitCode):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-05-04 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ More scaffolding for f.arguments.
+
+ Track the offset of the last call frame in the ExecState, so we can
+ produce a backtrace at any time.
+
+ Also, record numLocals, the sum of numVars + numParameters, in each code
+ block, to make updates to the ExecState a little cheaper than they
+ would be otherwise.
+
+ We now use numLocals in a bunch of places where we used to calculate
+ numVars + numParameters or -numVars - numParameters.
+
+ Reports are mixed, but all in all, this seems to be a wash on SunSpider.
+
+2008-05-04 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Whoops, correctly handle properties that don't exist in the
+ symbol table.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTablePutWithAttributes):
+
+2008-05-04 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Add attribute information to SymbolTable as ground work for
+ various DontEnum and ReadOnly issues.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::registerForLocal):
+ (KJS::CodeGenerator::registerForLocalConstInit):
+ (KJS::CodeGenerator::addConstant):
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::saveLocalStorage):
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames):
+ (KJS::JSVariableObject::getPropertyAttributes):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTablePut):
+ (KJS::JSVariableObject::symbolTablePutWithAttributes):
+ * kjs/SymbolTable.h:
+ (KJS::SymbolTableEntry::SymbolTableEntry):
+ (KJS::SymbolTableIndexHashTraits::emptyValue):
+ * kjs/nodes.cpp:
+ (KJS::getSymbolTableEntry):
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::ProgramNode::initializeSymbolTable):
+
+2008-05-04 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ More scaffolding for f.arguments.
+
+ Store the register file associated with an ExecState in the ExecState.
+
+ SunSpider reports no change.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): Moved
+ registerFileStack above globalExec, so it gets initialized first.
+ Removed remnants of old activation scheme.
+
+2008-05-04 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Oliver.
+
+ - renamed a few opcodes and fixed assembly formatting to accomodate the longest opcode
+
+ equal --> eq
+ nequal --> neq
+ resolve_base_and_property --> resolve_with_base
+ resolve_base_and_func --> resolve_func
+ get_prop_id --> get_by_id
+ put_prop_id --> put_by_id
+ delete_prop_id --> del_by_id
+ get_prop_val --> get_by_val
+ put_prop_val --> put_by_val
+ delete_prop_val --> del_by_val
+ put_prop_index --> put_by_index
+
+ * VM/CodeBlock.cpp:
+ (KJS::printUnaryOp):
+ (KJS::printBinaryOp):
+ (KJS::printConditionalJump):
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitEqual):
+ (KJS::CodeGenerator::emitNotEqual):
+ (KJS::CodeGenerator::emitResolveWithBase):
+ (KJS::CodeGenerator::emitResolveFunction):
+ (KJS::CodeGenerator::emitGetById):
+ (KJS::CodeGenerator::emitPutById):
+ (KJS::CodeGenerator::emitDeleteById):
+ (KJS::CodeGenerator::emitGetByVal):
+ (KJS::CodeGenerator::emitPutByVal):
+ (KJS::CodeGenerator::emitDeleteByVal):
+ (KJS::CodeGenerator::emitPutByIndex):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::ArrayNode::emitCode):
+ (KJS::PropertyListNode::emitCode):
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::EvalFunctionCallNode::emitCode):
+ (KJS::FunctionCallResolveNode::emitCode):
+ (KJS::FunctionCallBracketNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PostIncBracketNode::emitCode):
+ (KJS::PostDecBracketNode::emitCode):
+ (KJS::PostIncDotNode::emitCode):
+ (KJS::PostDecDotNode::emitCode):
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::DeleteBracketNode::emitCode):
+ (KJS::DeleteDotNode::emitCode):
+ (KJS::TypeOfResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ (KJS::ConstDeclNode::emitCodeSingle):
+ (KJS::ForInNode::emitCode):
+ (KJS::TryNode::emitCode):
+
+2008-05-04 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Fix assertion when accessing arguments object with too many arguments provided
+
+ The arguments constructor was assuming that the register offset given for argv
+ was an absolute offset into the registerfile, rather than the offset from the
+ frame. This patches corrects that issue.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject):
+
+2008-05-04 Geoffrey Garen <ggaren@apple.com>
+
+ Rubber stamped by Sam Weinig.
+
+ Cleaned up Machine.cpp according to our style guidelines: moved static
+ data to the top of the file; moved stand-alone functions below that;
+ moved the Machine constructor above other Machine member functions.
+
+2008-05-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - fix accidental breakage from last patch
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-05-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - a bunch more opcode documentation and corresponding parameter name fixes
+
+ I renamed a few opcodes:
+
+ type_of --> typeof (that's what the JS operator is named)
+ instance_of --> instanceof (ditto)
+ create_error --> new_error (for consistency with other new_* opcodes)
+
+ I documented the following opcodes:
+
+ - load
+ - new_object
+ - new_array
+ - new_regexp
+ - mov
+ - pre_inc
+ - pre_dec
+ - post_inc
+ - post_dec
+ - to_jsnumber
+ - negate
+ - bitnot
+ - not
+ - instanceof
+ - typeof
+ - in
+ - new_func
+ - new_funcexp
+ - new_error
+
+ I also fixed formatting on some existing opcode docs.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitMove):
+ (KJS::CodeGenerator::emitNot):
+ (KJS::CodeGenerator::emitPreInc):
+ (KJS::CodeGenerator::emitPreDec):
+ (KJS::CodeGenerator::emitPostInc):
+ (KJS::CodeGenerator::emitPostDec):
+ (KJS::CodeGenerator::emitToJSNumber):
+ (KJS::CodeGenerator::emitNegate):
+ (KJS::CodeGenerator::emitBitNot):
+ (KJS::CodeGenerator::emitInstanceOf):
+ (KJS::CodeGenerator::emitTypeOf):
+ (KJS::CodeGenerator::emitIn):
+ (KJS::CodeGenerator::emitLoad):
+ (KJS::CodeGenerator::emitNewObject):
+ (KJS::CodeGenerator::emitNewArray):
+ (KJS::CodeGenerator::emitNewRegExp):
+ (KJS::CodeGenerator::emitNewError):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::scopeDepth):
+ (KJS::CodeGenerator::addVar):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::Node::emitThrowError):
+ (KJS::RegExpNode::emitCode):
+ (KJS::TypeOfValueNode::emitCode):
+ (KJS::UnaryPlusNode::emitCode):
+ (KJS::NegateNode::emitCode):
+ (KJS::BitwiseNotNode::emitCode):
+ (KJS::LogicalNotNode::emitCode):
+ (KJS::InstanceOfNode::emitCode):
+ (KJS::InNode::emitCode):
+
+2008-05-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff and Sam.
+
+ - generate HTML bytecode docs at build time
+
+ * DerivedSources.make:
+ * docs: Added.
+ * docs/make-bytecode-docs.pl: Added.
+
+2008-05-03 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Update ExecState::m_scopeChain when switching scope chains inside the
+ machine.
+
+ This fixes uses of lexicalGlobalObject, such as, in a subframe
+
+ alert(top.makeArray() instanceof Array ? "FAIL" : "PASS");
+
+ and a bunch of the security failures listed in
+ https://bugs.webkit.org/show_bug.cgi?id=18870. (Those tests still fail,
+ seemingly because of regressions in exception messages).
+
+ SunSpider reports no change.
+
+ * VM/Machine.cpp: Factored out scope chain updating into a common
+ function that takes care to update ExecState::m_scopeChain, too.
+
+ * kjs/ExecState.h: I made Machine a friend of ExecState so that Machine
+ could update ExecState::m_scopeChain, even though that value is
+ read-only for everyone else.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): Changed
+ this client to be a little friendlier to ExecState's internal
+ storage type for scope chain data.
+
+2008-05-03 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed https://bugs.webkit.org/show_bug.cgi?id=18876
+ Squirrelfish: ScopeChainNode leak in op_jmp_scopes.
+
+ SunSpider reports no change.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Don't construct a ScopeChain object,
+ since the direct threaded interpreter will goto across its destructor.
+
+2008-05-03 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A bit more efficient fix than r32832: Don't copy globals into function
+ register files; instead, have the RegisterFileStack track only the base
+ of the last *global* register file, so the global object's register
+ references stay good.
+
+ SunSpider reports a .3% speedup. Not sure what that's about.
+
+2008-05-03 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18864: SquirrelFish: Support getter and setter definition in object literals
+ <https://bugs.webkit.org/show_bug.cgi?id=18864>
+
+ Add new opcodes to allow us to add getters and setters to an object. These are
+ only used by the codegen for object literals.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPutGetter):
+ (KJS::CodeGenerator::emitPutSetter):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PropertyListNode::emitCode):
+
+2008-05-02 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - properly copy globals into and out of implicit call register
+ files, otherwise they will fail at global lookup
+
+ Fixes fast/js/array-tostring-and-join.html layout test.
+
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushGlobalRegisterFile):
+ (KJS::RegisterFileStack::popGlobalRegisterFile):
+ (KJS::RegisterFileStack::pushFunctionRegisterFile):
+ (KJS::RegisterFileStack::popFunctionRegisterFile):
+
+2008-05-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed https://bugs.webkit.org/show_bug.cgi?id=18822
+ SQUIRRELFISH: incorrect eval used in some cases
+
+ Changed all code inside the machine to fetch the lexical global object
+ directly from the scope chain, instead of from the ExecState.
+
+ Clients who fetch the lexical global object through the ExecState
+ still don't work.
+
+ SunSpider reports no change.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Fetch the lexical global object from
+ the scope chain.
+
+ * kjs/ExecState.h:
+ (KJS::ExecState::ExecState::lexicalGlobalObject): Moved the logic for
+ this function into ScopeChainNode, but kept this function around to
+ support existing clients.
+
+2008-05-02 Geoffrey Garen <ggaren@apple.com>
+
+ Rubber stamped by Oliver Hunt.
+
+ Removed ExecState.cpp from AllInOneFile.cpp, for a .2% speedup.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/AllInOneFile.cpp:
+
+2008-05-01 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff and Maciej.
+
+ Bug 18827: SquirrelFish: Prevent getters and setters from destroying the current RegisterFile
+ <https://bugs.webkit.org/show_bug.cgi?id=18827>
+
+ Remove safe/unsafe RegisterFile concept, and instead just add additional
+ logic to ensure we always push/pop RegisterFiles when executing getters
+ and setters, similar to the logic for valueOf and toString.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ * kjs/object.cpp:
+ (KJS::JSObject::put):
+ * kjs/property_slot.cpp:
+ (KJS::PropertySlot::functionGetter):
+
+2008-05-01 Oliver Hunt <oliver@apple.com>
+
+ RS=Geoff
+
+ Rename unsafeForReentry to safeForReentry to avoid double negatives.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+
+2008-05-01 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18827: SquirrelFish: Prevent getters and setters from destroying the current RegisterFile
+ <https://bugs.webkit.org/show_bug.cgi?id=18827>
+
+ This patch makes getters and setters work. It does this by
+ tracking whether the RegisterFile is "safe", that is whether
+ the interpreter is in a state that in which it can handle
+ the RegisterFile being reallocated.
+
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Release build fix: Always compile in "isGlobalObject", since it's
+ listed in our .exp file.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::isGlobalObject):
+ * kjs/ExecState.h:
+
+2008-04-30 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Minor code restructuring to prepare for getters and setters,
+ also helps exception semantics a bit.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Fixed tyop.
+
+ * kjs/ExecState.h:
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Debug build fix: export a missing symbol.
+
+ * JavaScriptCore.exp:
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A little more ExecState refactoring: Now, only the global object creates
+ an ExecState.
+
+ Also inlined ExecState::lexicalGlobalObject().
+
+ SunSpider reports no change.
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ WebCore build fix: forward-declare ScopeChain.
+
+ * kjs/interpreter.h:
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix for JavaScriptGlue: export a missing symbol.
+
+ * JavaScriptCore.exp:
+
+2008-04-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed a lot of unused bits from ExecState, moving them into
+ OldInterpreterExecState, the fake scaffolding class.
+
+ The clutter was making it hard to see the forest from the trees.
+
+ .4% SunSpider speedup, probably because ExecState::lexicalGlobalObject()
+ is faster now.
+
+2008-04-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18643: SQUIRRELFISH: need to support implicit function calls (valueOf, toString, getters/setters)
+ <https://bugs.webkit.org/show_bug.cgi?id=18643>
+
+ Prevent static slot optimisation for new variables and functions in
+ globally re-entrant code called from an an implicit function call.
+
+ This is necessary to prevent us from needing to resize the global
+ slot portion of the root RegisterFile during an implicit (and hence
+ unguarded) function call.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFile.h:
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushGlobalRegisterFile):
+ (KJS::RegisterFileStack::popGlobalRegisterFile):
+ (KJS::RegisterFileStack::pushFunctionRegisterFile):
+ (KJS::RegisterFileStack::popFunctionRegisterFile):
+ * VM/RegisterFileStack.h:
+ (KJS::RegisterFileStack::inImplicitFunctionCall):
+ (KJS::RegisterFileStack::lastGlobal):
+ * kjs/nodes.cpp:
+ (KJS::ProgramNode::generateCode):
+ * kjs/nodes.h:
+ (KJS::ProgramNode::):
+
+2008-04-29 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ In nested program code, don't propogate "this" back to the parent
+ register file. ("this" should remain constant in the parent register
+ file, regardless of the scripts it invokes.)
+
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::copyGlobals):
+
+2008-04-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Restore base pointer when popping a global RegisterFile
+
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::popGlobalRegisterFile):
+
+2008-04-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18643: SQUIRRELFISH: need to support implicit function calls (valueOf, toString, getters/setters)
+ <https://bugs.webkit.org/show_bug.cgi?id=18643>
+
+ Partial fix. This results in all implicit calls to toString or valueOf
+ executing in a separate RegisterFile, so ensuring that the the pointers
+ in the triggering interpreter don't get trashed. This still leaves the
+ task of preventing new global re-entry from toString and valueOf from
+ clobbering the RegisterFile.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushFunctionRegisterFile):
+ (KJS::RegisterFileStack::popFunctionRegisterFile):
+ * VM/RegisterFileStack.h:
+ * kjs/object.cpp:
+ (KJS::tryGetAndCallProperty):
+
+2008-04-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Simplified activation object a bit: No need to store the callee
+ in the activation object -- we can pull it out of the call frame
+ when needed, instead.
+
+ SunSpider reports no change.
+
+2008-04-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ RS by Oliver Hunt on moving JSArguments.cpp out of AllInOneFile.cpp.
+
+ Substantially more handling of "arguments": "arguments" works fully
+ now, but "f.arguments" still doesn't work.
+
+ Fixes 10 regression tests.
+
+ SunSpider reports no regression.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::createArgumentsObject): Reconstruct an arguments
+ List to pass to the arguments object constructor.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/AllInOneFile.cpp: Removed JSActivation.cpp from AllInOneFile.cpp
+ because that seems to make GCC happy. (Previously, I had added
+ JSActivation.cpp to AllInOneFile.cpp because *that* seemed to make GCC
+ happy. So it goes.)
+
+2008-04-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Groundwork for more handling of "arguments". I'm not checking in the
+ actual handling of "arguments" yet, because it still needs a little
+ fiddling to avoid a performance regression.
+
+ SunSpider reports no change.
+
+ * VM/Machine.cpp:
+ (KJS::initializeCallFrame): Put argc in the register file, so the
+ arguments object can find it later, to determine arguments.length.
+
+ * kjs/nodes.h:
+ (KJS::FunctionBodyNode::): Added a special code accessor for when you
+ know the code has already been generated, and you don't have a scopeChain
+ to supply for potential code generation. (This is the case when the
+ activation object creates the arguments object.)
+
+2008-04-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Replace unsafe use of auto_ptr in Vector with manual memory
+ management.
+
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::~RegisterFileStack):
+ (KJS::RegisterFileStack::popRegisterFile):
+ * VM/RegisterFileStack.h:
+
+2008-04-27 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18746: SQUIRRELFISH: indirect eval used when direct eval should be used
+ <https://bugs.webkit.org/show_bug.cgi?id=18746>
+
+ Change the base to the correct value of the 'this' object after the direct
+ eval test instead of before.
+
+ Fixes 5 layout tests.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.cpp:
+ (KJS::EvalFunctionCallNode::emitCode):
+
+2008-04-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - document all property getting, setting and deleting opcodes
+
+ (And fix function parameter names to match corresponding opcode parameter names.)
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitResolve):
+ (KJS::CodeGenerator::emitResolveBase):
+ (KJS::CodeGenerator::emitResolveBaseAndProperty):
+ (KJS::CodeGenerator::emitResolveBaseAndFunc):
+ (KJS::CodeGenerator::emitGetPropId):
+ (KJS::CodeGenerator::emitPutPropId):
+ (KJS::CodeGenerator::emitDeletePropId):
+ (KJS::CodeGenerator::emitPutPropVal):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ (KJS::resolveBase):
+ (KJS::resolveBaseAndProperty):
+ (KJS::resolveBaseAndFunc):
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.cpp:
+ (KJS::ResolveNode::emitCode):
+ (KJS::ArrayNode::emitCode):
+ (KJS::PropertyListNode::emitCode):
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::EvalFunctionCallNode::emitCode):
+ (KJS::FunctionCallResolveNode::emitCode):
+ (KJS::FunctionCallBracketNode::emitCode):
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PostIncBracketNode::emitCode):
+ (KJS::PostDecBracketNode::emitCode):
+ (KJS::PostIncDotNode::emitCode):
+ (KJS::PostDecDotNode::emitCode):
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::TypeOfResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ (KJS::ConstDeclNode::emitCodeSingle):
+
+2008-04-26 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18628: SQUIRRELFISH: need to support recursion limit
+ <https://bugs.webkit.org/show_bug.cgi?id=18628>
+
+ Basically completes recursion limiting. There is still some
+ tuning we may want to do to make things better in the face of
+ very bad code, but certainly nothing worse than anything already
+ possible in trunk.
+
+ Also fixes a WebKit test by fixing the exception text :D
+
+ * JavaScriptCore.exp:
+ * VM/ExceptionHelpers.cpp:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::growBuffer):
+ (KJS::RegisterFile::addGlobalSlots):
+ * VM/RegisterFile.h:
+ (KJS::RegisterFile::grow):
+ (KJS::RegisterFile::uncheckedGrow):
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::pushRegisterFile):
+ * VM/RegisterFileStack.h:
+
+2008-04-25 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18628: SQUIRRELFISH: need to support recursion limit
+ <https://bugs.webkit.org/show_bug.cgi?id=18628>
+
+ Put a limit on the level of reentry recursion. 128 levels of re-entrant recursion
+ seems reasonable as it is greater than the old eval limit, and a long way short of
+ the reentry depth needed to overflow the stack.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/Machine.h:
+
+2008-04-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ A tiny bit of cleanup to the regexp code.
+
+ Removed some static_cast.
+
+ Removed createRegExpImp because it's no longer used.
+
+2008-04-25 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18736: SQUIRRELFISH: switch statements with no default have incorrect codegen
+ <https://bugs.webkit.org/show_bug.cgi?id=18736>
+
+ Ensure the "default" target is correct in the absence of an explicit default handler.
+
+ * kjs/nodes.cpp:
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-04-25 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18628: SQUIRRELFISH: need to support recursion limit
+ <https://bugs.webkit.org/show_bug.cgi?id=18628>
+
+ More bounds checking.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::growBuffer):
+ * VM/RegisterFile.h:
+
+2008-04-25 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix signal catching magic
+
+ The signal handlers are restored to _exit but are only set when
+ running under run-javascriptcore-tests. fprintf from a signal
+ handler is not safe.
+
+ * kjs/testkjs.cpp:
+ (main):
+ (parseArguments):
+ * tests/mozilla/jsDriver.pl:
+
+2008-04-25 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18732: SQUIRRELFISH: exceptions thrown by native constructors are ignored
+ <https://bugs.webkit.org/show_bug.cgi?id=18732>
+
+ Fixes another regression test.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-25 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18728: SQUIRRELFISH: invalid regular expression constants should throw exceptions
+ <https://bugs.webkit.org/show_bug.cgi?id=18728>
+
+ Fixes another regression test.
+
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::emitCode):
+
+2008-04-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoffrey Garen.
+
+ Bug 18735: SQUIRRELFISH: closures are sometimes given an incorrect 'this' value when called
+ <https://bugs.webkit.org/show_bug.cgi?id=18735>
+
+ The overloaded toThisObject method was not copied over to JSActivation.
+
+ Fixes two regression tests.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::toThisObject):
+ * kjs/JSActivation.h:
+
+2008-04-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Added support for arguments.callee.
+
+2008-04-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18628: SQUIRRELFISH: need to support recursion limit
+ <https://bugs.webkit.org/show_bug.cgi?id=18628>
+
+ Partial fix -- this gets us some of the required bounds checking, but not
+ complete coverage. But it does manage to do them without regressing :D
+
+ * VM/ExceptionHelpers.cpp:
+ (KJS::createError):
+ (KJS::createStackOverflowError):
+ * VM/ExceptionHelpers.h:
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.cpp:
+ * VM/RegisterFile.h:
+ (KJS::RegisterFile::):
+ (KJS::RegisterFile::RegisterFile):
+ (KJS::RegisterFile::grow):
+
+2008-04-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ A tiny bit more handling of "arguments": create a real, but mostly
+ hollow, arguments object.
+
+ Fixes 2 regression tests.
+
+2008-04-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18717: SQUIRRELFISH: eval returns the wrong value for a variable declaration statement
+ <https://bugs.webkit.org/show_bug.cgi?id=18717>
+
+ Fixes a regression test, but exposes the failure of another due to the
+ lack of getters and setters.
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::emitCodeSingle):
+ (KJS::ConstDeclNode::emitCode):
+ (KJS::ConstStatementNode::emitCode):
+ (KJS::VarStatementNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Print a CRASH statement when crashing, so test failures are not a
+ mystery.
+
+ * kjs/testkjs.cpp:
+ (handleCrash):
+ (main):
+
+2008-04-24 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoffrey Garen.
+
+ Bug 18716: SQUIRRELFISH: typeof should return undefined for an undefined variable reference
+ <https://bugs.webkit.org/show_bug.cgi?id=18716>
+
+ This fixes 2 more regression tests.
+
+ * kjs/nodes.cpp:
+ (KJS::TypeOfResolveNode::emitCode):
+
+2008-04-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Put the callee in the call frame.
+
+ Necessary in order to support "arguments" and "arguments.callee".
+
+ Also fixes a latent GC bug, where an executing function could be
+ subject to GC if the register holding it were overwritten. Here's
+ an example that would have caused problems:
+
+ function f()
+ {
+ // Flood the machine stack to eliminate any old pointers to f.
+ g.call({});
+
+ // Overwrite f in the register file.
+ f = 1;
+
+ // Force a GC.
+ for (var i = 0; i < 5000; ++i) {
+ ({});
+ }
+
+ // Welcome to crash-ville.
+ }
+
+ function g()
+ {
+ }
+
+ f();
+
+ * VM/Machine.h: Changed the order of arguments to
+ execute(FunctionBodyNode*...) to match the other execute functions.
+ * kjs/function.cpp: Updated to match new argument requirements from
+ execute(FunctionBodyNode*...). Renamed newObj to thisObj to match the
+ rest of JavaScriptCore.
+
+ SunSpider reports no change.
+
+2008-04-23 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18707: SQUIRRELFISH: eval always performs toString() on its argument
+ <https://bugs.webkit.org/show_bug.cgi?id=18707>
+
+ This fixes 4 more regression tests.
+
+ * VM/Machine.cpp:
+ (KJS::eval):
+
+2008-04-23 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix logic bug in SegmentedVector::grow which would sometimes fail to resize a segment when needed
+
+ Fixes 3 JSC tests.
+
+ * VM/SegmentedVector.h:
+ (KJS::SegmentedVector::grow):
+
+2008-04-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Degenerate handling of "arguments" as a property of the activation
+ object. Currently, we just return a vanilla object.
+
+ SunSpider reports no change.
+
+ Fixes:
+
+ ecma_3/Function/regress-94506.js.
+
+ Reveals to have been secretly broken:
+
+ ecma_3/Function/15.3.4.3-1.js
+ ecma_3/Function/15.3.4.4-1.js
+
+ These tests were passing incorrectly. testkjs creates a global array
+ named "arguments" to hold command-line arguments. That array was
+ tricking these tests into thinking that an arguments object with length
+ 0 had been created. Since our new vanilla object shadows the global
+ property named arguments, that object no longer fools these tests into
+ passing.
+
+ Net change: +1 failing test.
+
+ * kjs/AllInOneFile.cpp: Had to put JSActivation.cpp into AllInOneFile.cpp
+ to solve a surprising 8.6% regression in bitops-3bit-bits-in-byte.
+
+2008-04-23 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - save and restore callFrame
+
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * kjs/testkjs.cpp:
+ (main):
+
+2008-04-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed scopes for named function expressions.
+
+ Fixes one regression test.
+
+ Two changes here:
+
+ (1) The function's name is supposed to have attributes DontDelete,
+ ReadOnly, regardless of the type of code executing.
+
+ (2) Push the name object on the function's scope chain, rather than
+ the ExecState's scope chain because, well, that's where it belongs.
+
+2008-04-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Inlined JSObject::putDirect, for a .4% SunSpider speedup.
+
+ I did this as a first step toward removing nodes.cpp from
+ AllInOneFile.cpp, but I'm putting that larger project aside for now.
+
+2008-04-23 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Geoff.
+
+ - add OldInterpreterExecState class and use it in dead code
+
+ This will allow removing things from the real ExecState class
+ without having to figure out how to remove all this code without
+ getting a perf regression.
+
+ * kjs/nodes.cpp:
+ (KJS::ExpressionNode::evaluateToNumber):
+ (KJS::ExpressionNode::evaluateToBoolean):
+ (KJS::ExpressionNode::evaluateToInt32):
+ (KJS::ExpressionNode::evaluateToUInt32):
+ (KJS::Node::setErrorCompletion):
+ (KJS::Node::throwError):
+ (KJS::Node::throwUndefinedVariableError):
+ (KJS::Node::handleException):
+ (KJS::Node::rethrowException):
+ (KJS::BreakpointCheckStatement::execute):
+ (KJS::BreakpointCheckStatement::optimizeVariableAccess):
+ (KJS::NullNode::evaluate):
+ (KJS::FalseNode::evaluate):
+ (KJS::TrueNode::evaluate):
+ (KJS::NumberNode::evaluate):
+ (KJS::NumberNode::evaluateToNumber):
+ (KJS::NumberNode::evaluateToBoolean):
+ (KJS::NumberNode::evaluateToInt32):
+ (KJS::NumberNode::evaluateToUInt32):
+ (KJS::ImmediateNumberNode::evaluate):
+ (KJS::ImmediateNumberNode::evaluateToInt32):
+ (KJS::ImmediateNumberNode::evaluateToUInt32):
+ (KJS::StringNode::evaluate):
+ (KJS::StringNode::evaluateToNumber):
+ (KJS::StringNode::evaluateToBoolean):
+ (KJS::RegExpNode::evaluate):
+ (KJS::ThisNode::evaluate):
+ (KJS::ResolveNode::inlineEvaluate):
+ (KJS::ResolveNode::evaluate):
+ (KJS::ResolveNode::evaluateToNumber):
+ (KJS::ResolveNode::evaluateToBoolean):
+ (KJS::ResolveNode::evaluateToInt32):
+ (KJS::ResolveNode::evaluateToUInt32):
+ (KJS::getSymbolTableEntry):
+ (KJS::ResolveNode::optimizeVariableAccess):
+ (KJS::LocalVarAccessNode::inlineEvaluate):
+ (KJS::LocalVarAccessNode::evaluate):
+ (KJS::LocalVarAccessNode::evaluateToNumber):
+ (KJS::LocalVarAccessNode::evaluateToBoolean):
+ (KJS::LocalVarAccessNode::evaluateToInt32):
+ (KJS::LocalVarAccessNode::evaluateToUInt32):
+ (KJS::getNonLocalSymbol):
+ (KJS::ScopedVarAccessNode::inlineEvaluate):
+ (KJS::ScopedVarAccessNode::evaluate):
+ (KJS::ScopedVarAccessNode::evaluateToNumber):
+ (KJS::ScopedVarAccessNode::evaluateToBoolean):
+ (KJS::ScopedVarAccessNode::evaluateToInt32):
+ (KJS::ScopedVarAccessNode::evaluateToUInt32):
+ (KJS::NonLocalVarAccessNode::inlineEvaluate):
+ (KJS::NonLocalVarAccessNode::evaluate):
+ (KJS::NonLocalVarAccessNode::evaluateToNumber):
+ (KJS::NonLocalVarAccessNode::evaluateToBoolean):
+ (KJS::NonLocalVarAccessNode::evaluateToInt32):
+ (KJS::NonLocalVarAccessNode::evaluateToUInt32):
+ (KJS::ElementNode::optimizeVariableAccess):
+ (KJS::ElementNode::evaluate):
+ (KJS::ArrayNode::optimizeVariableAccess):
+ (KJS::ArrayNode::evaluate):
+ (KJS::ObjectLiteralNode::optimizeVariableAccess):
+ (KJS::ObjectLiteralNode::evaluate):
+ (KJS::PropertyListNode::optimizeVariableAccess):
+ (KJS::PropertyListNode::evaluate):
+ (KJS::PropertyNode::optimizeVariableAccess):
+ (KJS::PropertyNode::evaluate):
+ (KJS::BracketAccessorNode::optimizeVariableAccess):
+ (KJS::BracketAccessorNode::inlineEvaluate):
+ (KJS::BracketAccessorNode::evaluate):
+ (KJS::BracketAccessorNode::evaluateToNumber):
+ (KJS::BracketAccessorNode::evaluateToBoolean):
+ (KJS::BracketAccessorNode::evaluateToInt32):
+ (KJS::BracketAccessorNode::evaluateToUInt32):
+ (KJS::DotAccessorNode::optimizeVariableAccess):
+ (KJS::DotAccessorNode::inlineEvaluate):
+ (KJS::DotAccessorNode::evaluate):
+ (KJS::DotAccessorNode::evaluateToNumber):
+ (KJS::DotAccessorNode::evaluateToBoolean):
+ (KJS::DotAccessorNode::evaluateToInt32):
+ (KJS::DotAccessorNode::evaluateToUInt32):
+ (KJS::ArgumentListNode::optimizeVariableAccess):
+ (KJS::ArgumentListNode::evaluateList):
+ (KJS::ArgumentsNode::optimizeVariableAccess):
+ (KJS::NewExprNode::optimizeVariableAccess):
+ (KJS::NewExprNode::inlineEvaluate):
+ (KJS::NewExprNode::evaluate):
+ (KJS::NewExprNode::evaluateToNumber):
+ (KJS::NewExprNode::evaluateToBoolean):
+ (KJS::NewExprNode::evaluateToInt32):
+ (KJS::NewExprNode::evaluateToUInt32):
+ (KJS::ExpressionNode::resolveAndCall):
+ (KJS::EvalFunctionCallNode::optimizeVariableAccess):
+ (KJS::EvalFunctionCallNode::evaluate):
+ (KJS::FunctionCallValueNode::optimizeVariableAccess):
+ (KJS::FunctionCallValueNode::evaluate):
+ (KJS::FunctionCallResolveNode::optimizeVariableAccess):
+ (KJS::FunctionCallResolveNode::inlineEvaluate):
+ (KJS::FunctionCallResolveNode::evaluate):
+ (KJS::FunctionCallResolveNode::evaluateToNumber):
+ (KJS::FunctionCallResolveNode::evaluateToBoolean):
+ (KJS::FunctionCallResolveNode::evaluateToInt32):
+ (KJS::FunctionCallResolveNode::evaluateToUInt32):
+ (KJS::LocalVarFunctionCallNode::inlineEvaluate):
+ (KJS::LocalVarFunctionCallNode::evaluate):
+ (KJS::LocalVarFunctionCallNode::evaluateToNumber):
+ (KJS::LocalVarFunctionCallNode::evaluateToBoolean):
+ (KJS::LocalVarFunctionCallNode::evaluateToInt32):
+ (KJS::LocalVarFunctionCallNode::evaluateToUInt32):
+ (KJS::ScopedVarFunctionCallNode::inlineEvaluate):
+ (KJS::ScopedVarFunctionCallNode::evaluate):
+ (KJS::ScopedVarFunctionCallNode::evaluateToNumber):
+ (KJS::ScopedVarFunctionCallNode::evaluateToBoolean):
+ (KJS::ScopedVarFunctionCallNode::evaluateToInt32):
+ (KJS::ScopedVarFunctionCallNode::evaluateToUInt32):
+ (KJS::NonLocalVarFunctionCallNode::inlineEvaluate):
+ (KJS::NonLocalVarFunctionCallNode::evaluate):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToNumber):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToBoolean):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToInt32):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToUInt32):
+ (KJS::FunctionCallBracketNode::optimizeVariableAccess):
+ (KJS::FunctionCallBracketNode::evaluate):
+ (KJS::FunctionCallDotNode::optimizeVariableAccess):
+ (KJS::FunctionCallDotNode::inlineEvaluate):
+ (KJS::FunctionCallDotNode::evaluate):
+ (KJS::FunctionCallDotNode::evaluateToNumber):
+ (KJS::FunctionCallDotNode::evaluateToBoolean):
+ (KJS::FunctionCallDotNode::evaluateToInt32):
+ (KJS::FunctionCallDotNode::evaluateToUInt32):
+ (KJS::PostIncResolveNode::optimizeVariableAccess):
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::optimizeVariableAccess):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostDecLocalVarNode::inlineEvaluateToNumber):
+ (KJS::PostDecLocalVarNode::evaluateToNumber):
+ (KJS::PostDecLocalVarNode::evaluateToBoolean):
+ (KJS::PostDecLocalVarNode::evaluateToInt32):
+ (KJS::PostDecLocalVarNode::evaluateToUInt32):
+ (KJS::PostfixBracketNode::optimizeVariableAccess):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostfixDotNode::optimizeVariableAccess):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::PostfixErrorNode::evaluate):
+ (KJS::DeleteResolveNode::optimizeVariableAccess):
+ (KJS::DeleteResolveNode::evaluate):
+ (KJS::LocalVarDeleteNode::evaluate):
+ (KJS::DeleteBracketNode::optimizeVariableAccess):
+ (KJS::DeleteBracketNode::evaluate):
+ (KJS::DeleteDotNode::optimizeVariableAccess):
+ (KJS::DeleteDotNode::evaluate):
+ (KJS::DeleteValueNode::optimizeVariableAccess):
+ (KJS::DeleteValueNode::evaluate):
+ (KJS::VoidNode::optimizeVariableAccess):
+ (KJS::VoidNode::evaluate):
+ (KJS::TypeOfValueNode::optimizeVariableAccess):
+ (KJS::TypeOfResolveNode::optimizeVariableAccess):
+ (KJS::LocalVarTypeOfNode::evaluate):
+ (KJS::TypeOfResolveNode::evaluate):
+ (KJS::TypeOfValueNode::evaluate):
+ (KJS::PreIncResolveNode::optimizeVariableAccess):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecResolveNode::optimizeVariableAccess):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::PreIncConstNode::evaluate):
+ (KJS::PreDecConstNode::evaluate):
+ (KJS::PostIncConstNode::evaluate):
+ (KJS::PostDecConstNode::evaluate):
+ (KJS::PrefixBracketNode::optimizeVariableAccess):
+ (KJS::PreIncBracketNode::evaluate):
+ (KJS::PreDecBracketNode::evaluate):
+ (KJS::PrefixDotNode::optimizeVariableAccess):
+ (KJS::PreIncDotNode::evaluate):
+ (KJS::PreDecDotNode::evaluate):
+ (KJS::PrefixErrorNode::evaluate):
+ (KJS::UnaryPlusNode::optimizeVariableAccess):
+ (KJS::UnaryPlusNode::evaluate):
+ (KJS::UnaryPlusNode::evaluateToBoolean):
+ (KJS::UnaryPlusNode::evaluateToNumber):
+ (KJS::UnaryPlusNode::evaluateToInt32):
+ (KJS::UnaryPlusNode::evaluateToUInt32):
+ (KJS::NegateNode::optimizeVariableAccess):
+ (KJS::NegateNode::evaluate):
+ (KJS::NegateNode::evaluateToNumber):
+ (KJS::BitwiseNotNode::optimizeVariableAccess):
+ (KJS::BitwiseNotNode::inlineEvaluateToInt32):
+ (KJS::BitwiseNotNode::evaluate):
+ (KJS::BitwiseNotNode::evaluateToNumber):
+ (KJS::BitwiseNotNode::evaluateToBoolean):
+ (KJS::BitwiseNotNode::evaluateToInt32):
+ (KJS::BitwiseNotNode::evaluateToUInt32):
+ (KJS::LogicalNotNode::optimizeVariableAccess):
+ (KJS::LogicalNotNode::evaluate):
+ (KJS::LogicalNotNode::evaluateToBoolean):
+ (KJS::MultNode::optimizeVariableAccess):
+ (KJS::MultNode::inlineEvaluateToNumber):
+ (KJS::MultNode::evaluate):
+ (KJS::MultNode::evaluateToNumber):
+ (KJS::MultNode::evaluateToBoolean):
+ (KJS::MultNode::evaluateToInt32):
+ (KJS::MultNode::evaluateToUInt32):
+ (KJS::DivNode::optimizeVariableAccess):
+ (KJS::DivNode::inlineEvaluateToNumber):
+ (KJS::DivNode::evaluate):
+ (KJS::DivNode::evaluateToNumber):
+ (KJS::DivNode::evaluateToInt32):
+ (KJS::DivNode::evaluateToUInt32):
+ (KJS::ModNode::optimizeVariableAccess):
+ (KJS::ModNode::inlineEvaluateToNumber):
+ (KJS::ModNode::evaluate):
+ (KJS::ModNode::evaluateToNumber):
+ (KJS::ModNode::evaluateToBoolean):
+ (KJS::ModNode::evaluateToInt32):
+ (KJS::ModNode::evaluateToUInt32):
+ (KJS::throwOutOfMemoryErrorToNumber):
+ (KJS::addSlowCase):
+ (KJS::addSlowCaseToNumber):
+ (KJS::add):
+ (KJS::addToNumber):
+ (KJS::AddNode::optimizeVariableAccess):
+ (KJS::AddNode::evaluate):
+ (KJS::AddNode::inlineEvaluateToNumber):
+ (KJS::AddNode::evaluateToNumber):
+ (KJS::AddNode::evaluateToInt32):
+ (KJS::AddNode::evaluateToUInt32):
+ (KJS::AddNumbersNode::inlineEvaluateToNumber):
+ (KJS::AddNumbersNode::evaluate):
+ (KJS::AddNumbersNode::evaluateToNumber):
+ (KJS::AddNumbersNode::evaluateToInt32):
+ (KJS::AddNumbersNode::evaluateToUInt32):
+ (KJS::AddStringsNode::evaluate):
+ (KJS::AddStringLeftNode::evaluate):
+ (KJS::AddStringRightNode::evaluate):
+ (KJS::SubNode::optimizeVariableAccess):
+ (KJS::SubNode::inlineEvaluateToNumber):
+ (KJS::SubNode::evaluate):
+ (KJS::SubNode::evaluateToNumber):
+ (KJS::SubNode::evaluateToInt32):
+ (KJS::SubNode::evaluateToUInt32):
+ (KJS::LeftShiftNode::optimizeVariableAccess):
+ (KJS::LeftShiftNode::inlineEvaluateToInt32):
+ (KJS::LeftShiftNode::evaluate):
+ (KJS::LeftShiftNode::evaluateToNumber):
+ (KJS::LeftShiftNode::evaluateToInt32):
+ (KJS::LeftShiftNode::evaluateToUInt32):
+ (KJS::RightShiftNode::optimizeVariableAccess):
+ (KJS::RightShiftNode::inlineEvaluateToInt32):
+ (KJS::RightShiftNode::evaluate):
+ (KJS::RightShiftNode::evaluateToNumber):
+ (KJS::RightShiftNode::evaluateToInt32):
+ (KJS::RightShiftNode::evaluateToUInt32):
+ (KJS::UnsignedRightShiftNode::optimizeVariableAccess):
+ (KJS::UnsignedRightShiftNode::inlineEvaluateToUInt32):
+ (KJS::UnsignedRightShiftNode::evaluate):
+ (KJS::UnsignedRightShiftNode::evaluateToNumber):
+ (KJS::UnsignedRightShiftNode::evaluateToInt32):
+ (KJS::UnsignedRightShiftNode::evaluateToUInt32):
+ (KJS::lessThan):
+ (KJS::lessThanEq):
+ (KJS::LessNode::optimizeVariableAccess):
+ (KJS::LessNode::inlineEvaluateToBoolean):
+ (KJS::LessNode::evaluate):
+ (KJS::LessNode::evaluateToBoolean):
+ (KJS::LessNumbersNode::inlineEvaluateToBoolean):
+ (KJS::LessNumbersNode::evaluate):
+ (KJS::LessNumbersNode::evaluateToBoolean):
+ (KJS::LessStringsNode::inlineEvaluateToBoolean):
+ (KJS::LessStringsNode::evaluate):
+ (KJS::LessStringsNode::evaluateToBoolean):
+ (KJS::GreaterNode::optimizeVariableAccess):
+ (KJS::GreaterNode::inlineEvaluateToBoolean):
+ (KJS::GreaterNode::evaluate):
+ (KJS::GreaterNode::evaluateToBoolean):
+ (KJS::LessEqNode::optimizeVariableAccess):
+ (KJS::LessEqNode::inlineEvaluateToBoolean):
+ (KJS::LessEqNode::evaluate):
+ (KJS::LessEqNode::evaluateToBoolean):
+ (KJS::GreaterEqNode::optimizeVariableAccess):
+ (KJS::GreaterEqNode::inlineEvaluateToBoolean):
+ (KJS::GreaterEqNode::evaluate):
+ (KJS::GreaterEqNode::evaluateToBoolean):
+ (KJS::InstanceOfNode::optimizeVariableAccess):
+ (KJS::InstanceOfNode::evaluate):
+ (KJS::InstanceOfNode::evaluateToBoolean):
+ (KJS::InNode::optimizeVariableAccess):
+ (KJS::InNode::evaluate):
+ (KJS::InNode::evaluateToBoolean):
+ (KJS::EqualNode::optimizeVariableAccess):
+ (KJS::EqualNode::inlineEvaluateToBoolean):
+ (KJS::EqualNode::evaluate):
+ (KJS::EqualNode::evaluateToBoolean):
+ (KJS::NotEqualNode::optimizeVariableAccess):
+ (KJS::NotEqualNode::inlineEvaluateToBoolean):
+ (KJS::NotEqualNode::evaluate):
+ (KJS::NotEqualNode::evaluateToBoolean):
+ (KJS::StrictEqualNode::optimizeVariableAccess):
+ (KJS::StrictEqualNode::inlineEvaluateToBoolean):
+ (KJS::StrictEqualNode::evaluate):
+ (KJS::StrictEqualNode::evaluateToBoolean):
+ (KJS::NotStrictEqualNode::optimizeVariableAccess):
+ (KJS::NotStrictEqualNode::inlineEvaluateToBoolean):
+ (KJS::NotStrictEqualNode::evaluate):
+ (KJS::NotStrictEqualNode::evaluateToBoolean):
+ (KJS::BitAndNode::optimizeVariableAccess):
+ (KJS::BitAndNode::evaluate):
+ (KJS::BitAndNode::inlineEvaluateToInt32):
+ (KJS::BitAndNode::evaluateToNumber):
+ (KJS::BitAndNode::evaluateToBoolean):
+ (KJS::BitAndNode::evaluateToInt32):
+ (KJS::BitAndNode::evaluateToUInt32):
+ (KJS::BitXOrNode::optimizeVariableAccess):
+ (KJS::BitXOrNode::inlineEvaluateToInt32):
+ (KJS::BitXOrNode::evaluate):
+ (KJS::BitXOrNode::evaluateToNumber):
+ (KJS::BitXOrNode::evaluateToBoolean):
+ (KJS::BitXOrNode::evaluateToInt32):
+ (KJS::BitXOrNode::evaluateToUInt32):
+ (KJS::BitOrNode::optimizeVariableAccess):
+ (KJS::BitOrNode::inlineEvaluateToInt32):
+ (KJS::BitOrNode::evaluate):
+ (KJS::BitOrNode::evaluateToNumber):
+ (KJS::BitOrNode::evaluateToBoolean):
+ (KJS::BitOrNode::evaluateToInt32):
+ (KJS::BitOrNode::evaluateToUInt32):
+ (KJS::LogicalAndNode::optimizeVariableAccess):
+ (KJS::LogicalAndNode::evaluate):
+ (KJS::LogicalAndNode::evaluateToBoolean):
+ (KJS::LogicalOrNode::optimizeVariableAccess):
+ (KJS::LogicalOrNode::evaluate):
+ (KJS::LogicalOrNode::evaluateToBoolean):
+ (KJS::ConditionalNode::optimizeVariableAccess):
+ (KJS::ConditionalNode::evaluate):
+ (KJS::ConditionalNode::evaluateToBoolean):
+ (KJS::ConditionalNode::evaluateToNumber):
+ (KJS::ConditionalNode::evaluateToInt32):
+ (KJS::ConditionalNode::evaluateToUInt32):
+ (KJS::valueForReadModifyAssignment):
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::ReadModifyLocalVarNode::evaluate):
+ (KJS::AssignLocalVarNode::evaluate):
+ (KJS::ReadModifyConstNode::evaluate):
+ (KJS::AssignConstNode::evaluate):
+ (KJS::ReadModifyResolveNode::evaluate):
+ (KJS::AssignResolveNode::evaluate):
+ (KJS::AssignDotNode::optimizeVariableAccess):
+ (KJS::AssignDotNode::evaluate):
+ (KJS::ReadModifyDotNode::optimizeVariableAccess):
+ (KJS::ReadModifyDotNode::evaluate):
+ (KJS::AssignErrorNode::evaluate):
+ (KJS::AssignBracketNode::optimizeVariableAccess):
+ (KJS::AssignBracketNode::evaluate):
+ (KJS::ReadModifyBracketNode::optimizeVariableAccess):
+ (KJS::ReadModifyBracketNode::evaluate):
+ (KJS::CommaNode::optimizeVariableAccess):
+ (KJS::CommaNode::evaluate):
+ (KJS::ConstDeclNode::optimizeVariableAccess):
+ (KJS::ConstDeclNode::handleSlowCase):
+ (KJS::ConstDeclNode::evaluateSingle):
+ (KJS::ConstDeclNode::evaluate):
+ (KJS::ConstStatementNode::optimizeVariableAccess):
+ (KJS::ConstStatementNode::execute):
+ (KJS::statementListExecute):
+ (KJS::BlockNode::optimizeVariableAccess):
+ (KJS::BlockNode::execute):
+ (KJS::EmptyStatementNode::execute):
+ (KJS::ExprStatementNode::optimizeVariableAccess):
+ (KJS::ExprStatementNode::execute):
+ (KJS::VarStatementNode::optimizeVariableAccess):
+ (KJS::VarStatementNode::execute):
+ (KJS::IfNode::optimizeVariableAccess):
+ (KJS::IfNode::execute):
+ (KJS::IfElseNode::optimizeVariableAccess):
+ (KJS::IfElseNode::execute):
+ (KJS::DoWhileNode::optimizeVariableAccess):
+ (KJS::DoWhileNode::execute):
+ (KJS::WhileNode::optimizeVariableAccess):
+ (KJS::WhileNode::execute):
+ (KJS::ForNode::optimizeVariableAccess):
+ (KJS::ForNode::execute):
+ (KJS::ForInNode::optimizeVariableAccess):
+ (KJS::ForInNode::execute):
+ (KJS::ContinueNode::execute):
+ (KJS::BreakNode::execute):
+ (KJS::ReturnNode::optimizeVariableAccess):
+ (KJS::ReturnNode::execute):
+ (KJS::WithNode::optimizeVariableAccess):
+ (KJS::WithNode::execute):
+ (KJS::CaseClauseNode::optimizeVariableAccess):
+ (KJS::CaseClauseNode::evaluate):
+ (KJS::CaseClauseNode::executeStatements):
+ (KJS::ClauseListNode::optimizeVariableAccess):
+ (KJS::CaseBlockNode::optimizeVariableAccess):
+ (KJS::CaseBlockNode::executeBlock):
+ (KJS::SwitchNode::optimizeVariableAccess):
+ (KJS::SwitchNode::execute):
+ (KJS::LabelNode::optimizeVariableAccess):
+ (KJS::LabelNode::execute):
+ (KJS::ThrowNode::optimizeVariableAccess):
+ (KJS::ThrowNode::execute):
+ (KJS::TryNode::optimizeVariableAccess):
+ (KJS::TryNode::execute):
+ (KJS::ProgramNode::initializeSymbolTable):
+ (KJS::ScopeNode::optimizeVariableAccess):
+ (KJS::ProgramNode::processDeclarations):
+ (KJS::EvalNode::processDeclarations):
+ (KJS::ProgramNode::execute):
+ (KJS::EvalNode::execute):
+ (KJS::FunctionBodyNodeWithDebuggerHooks::execute):
+ (KJS::FuncDeclNode::execute):
+ (KJS::FuncExprNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::Node::):
+ (KJS::FalseNode::):
+ (KJS::TrueNode::):
+ (KJS::ArgumentsNode::):
+
+2008-04-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18672: SQUIRRELFISH: codegen fails with a large number of temporaries
+ <https://bugs.webkit.org/show_bug.cgi?id=18672>
+
+ Add a SegmentedVector type, which provides a Vector<T> which maintains
+ existing memory locations during resize. This allows dynamically sizing
+ local, temporary and label "vectors" in CodeGenerator.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::newTemporary):
+ (KJS::CodeGenerator::newLabel):
+ * VM/CodeGenerator.h:
+ * VM/SegmentedVector.h: Added.
+ (KJS::SegmentedVector::SegmentedVector):
+ (KJS::SegmentedVector::~SegmentedVector):
+ (KJS::SegmentedVector::last):
+ (KJS::SegmentedVector::append):
+ (KJS::SegmentedVector::removeLast):
+ (KJS::SegmentedVector::size):
+ (KJS::SegmentedVector::operator[]):
+ (KJS::SegmentedVector::resize):
+ (KJS::SegmentedVector::shrink):
+ (KJS::SegmentedVector::grow):
+
+2008-04-23 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ A little refactoring in preparation for supporting 'arguments'.
+
+ Fixes 2 regression tests.
+
+ SunSpider reports no change.
+
+ We now check the activation register, instead of the codeBlock, to
+ determine whether we need to tear off the activation. This is to support
+ "f.arguments", which will create an activation/arguments pair for f,
+ even though the needsFullScopeChain flag is false for f's codeBlock.
+
+ The test fixes resulted from calling initializeCallFrame for re-entrant
+ function code, instead of initializing (not enough) parts of the call
+ frame by hand.
+
+2008-04-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - propagate the "this" value properly to local eval
+
+ (fixes a measly one regression test)
+
+ * VM/CodeBlock.h:
+ (KJS::CodeBlock::CodeBlock):
+ (KJS::ProgramCodeBlock::ProgramCodeBlock):
+ (KJS::EvalCodeBlock::EvalCodeBlock):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-22 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Add support for function declarations in eval code.
+
+ (this fixes 12 more regression tests)
+
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::generateCode):
+
+2008-04-22 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Implement LabelNode.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::pushJumpContext):
+ (KJS::CodeGenerator::jumpContextForContinue):
+ (KJS::CodeGenerator::jumpContextForBreak):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::ForInNode::emitCode):
+ (KJS::ContinueNode::emitCode):
+ (KJS::BreakNode::emitCode):
+ (KJS::SwitchNode::emitCode):
+ (KJS::LabelNode::emitCode):
+
+2008-04-22 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed crash when unwinding from exceptions inside eval.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame): Don't assume that the top of the
+ current call frame's scope chain is an activation: it can be the global
+ object, instead.
+
+2008-04-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ * kjs/testkjs.cpp:
+ (main): Convert signals to exit codes, so that crashing tests are
+ detected as regression test failures.
+
+2008-04-22 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt and Maciej Stachowiak.
+
+ Renamed "needsActivation" to "needsFullScopeChain" because lying will
+ make hair grow on the backs of your hands.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed ScopeChainNode lifetime problems:
+
+ (1) In "with" and "catch" scopes, we would construct a ScopeChain
+ object and then jump across its destructor, leaking the ScopeChainNode
+ we had pushed.
+
+ (2) In global and eval scopes, we would fail to initially ref
+ "scopeChain", causing us to overrelease it later. Now that we ref
+ "scopeChain" properly, we also need to deref it when the script
+ terminates.
+
+ SunSpider reports a .2% regression, but an earlier round of ScopeChain
+ refactoring was a .4% speedup, so there.
+
+2008-04-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Alexey.
+
+ - use global object instead of null for "this" on unqualified calls
+
+ This fixes 10 more JSC test regressions.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - throw proper exceptions for objects that don't implement call or construct
+
+ This fixes 21 more JSC test regressions. It is also seemingly an
+ 0.5% progression.
+
+ * VM/ExceptionHelpers.cpp:
+ (KJS::createNotAnObjectError):
+ (KJS::createNotAConstructorError):
+ (KJS::createNotAFunctionError):
+ * VM/ExceptionHelpers.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Implement emitCode for ConstDeclNode.
+
+ This fixes the crash (assertion) in js1_5/Scope/scope-001.js
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::registerForLocalConstInit):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::ConstDeclNode::emitCodeSingle):
+ (KJS::ConstDeclNode::emitCode):
+ (KJS::ConstStatementNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - add some support for the split window object
+
+ This fixes many layout tests.
+
+ * VM/Machine.cpp:
+ (KJS::resolveBaseAndFunc): Use toThisObject() to ensure we get the
+ wrapper global, if one exists, as the "this" object.
+ * kjs/function.cpp:
+ (KJS::globalFuncEval): Use toGlobalObject() to handle the wrapper
+ case properly.
+
+2008-04-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - restore ScopeChain::operator= to avoid crash on many layout tests
+
+ Otherwise, FunctionImp::setScope would cause a reference
+ underflow. I implemented using the copy construct and swap idiom.
+
+ * kjs/scope_chain.h:
+ (KJS::ScopeChain::swap):
+ (KJS::ScopeChain::operator=):
+
+2008-04-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18649: SQUIRRELFISH: correctly handle exceptions in eval code
+ <https://bugs.webkit.org/show_bug.cgi?id=18649>
+
+ Allocate a callframe for eval() and initialise with a null codeBlock to
+ indicate native code. This prevents the unwinder from clobbering the
+ register stack.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Removed ScopeChain::push(ScopeChain&) because it was unused. Moved
+ ScopeChain::print to ScopeChainNode.
+
+ ScopeChain is now nothing more than a resource-handling wrapper around
+ ScopeChainNode.
+
+2008-04-21 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18671: SquirrelFish: continue inside switch fails
+ <https://bugs.webkit.org/show_bug.cgi?id=18671>
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::jumpContextForLabel):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::ContinueNode::emitCode):
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Moved push(JSObject*) and pop() from ScopeChain to ScopeChainNode,
+ rearranging scope_chain.h a bit.
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Moved bottom() from ScopeChain to ScopeChainNode, simplifying it based
+ on the knowledge that the ScopeChain is never empty.
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Moved begin() and end() from ScopeChain to ScopeChainNode.
+
+ Also marked a few methods "const".
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Turned ScopeChain::depth into a stand-alone function, and simplified it
+ a bit.
+
+ I also moved ScopeChain::depth to Machine.cpp because it doesn't report
+ the true depth of the ScopeChain -- just the Machine's perspective of
+ its depth within a given call frame.
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Removed indirection in ScopeChain::ref / ScopeChain::deref.
+
+ SunSpider reports no change.
+
+ * kjs/scope_chain.h:
+ (KJS::ScopeChain::ScopeChain):
+ (KJS::ScopeChain::~ScopeChain):
+ (KJS::ScopeChain::clear):
+
+2008-04-21 Oliver Hunt <oliver@apple.com>
+
+ Fix debug build
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::evaluateSingle):
+
+2008-04-21 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18664: SQUIRRELFISH: correctly throw a SyntaxError when parsing of eval code fails
+ <https://bugs.webkit.org/show_bug.cgi?id=18664>
+
+ Correctly throw a SyntaxError when parsing of eval code fails.
+
+ * VM/Machine.cpp:
+ (KJS::eval):
+
+2008-04-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Partial fix for Bug 18649: SQUIRRELFISH: correctly handle exceptions in eval code
+
+ Make sure we correct the register state before jumping to vm_throw.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Simplified ScopeChain ref/deref.
+
+ SunSpider reports a .4% speedup.
+
+ * kjs/scope_chain.h:
+ (KJS::ScopeChainNode::ref): Removed this function because it was nonsense.
+ ScopeChainNodes are initialized with a refCount of 1, so the loop was
+ guaranteed to iterate exactly once.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Removed support for empty ScopeChains.
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Removed some completely unused ScopeChain member functions.
+
+ SunSpider reports no change.
+
+2008-04-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Avoid creating unnecessary ScopeChain objects, to reduce refcount churn.
+
+ SunSpider reports no change.
+
+2008-04-21 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Alexey.
+
+ Add some braces.x
+
+ * kjs/testkjs.cpp:
+ (runWithScripts):
+
+2008-04-21 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - only print "End:" output when -d flag is passed.
+
+ This fixes half of our failing JSC regression tests.
+
+ * kjs/testkjs.cpp:
+ (runWithScripts):
+
+2008-04-21 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Add support for variable declarations in eval code.
+
+ * VM/CodeBlock.h:
+ (KJS::EvalCodeBlock::EvalCodeBlock):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/Machine.h:
+ * kjs/function.cpp:
+ (KJS::globalFuncEval):
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::generateCode):
+ * kjs/nodes.h:
+ (KJS::EvalNode::):
+
+2008-04-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Throw exceptions for invalid continue, break, and return statements.
+
+ Simple refactoring and extension of Cameron's AssignErrorNode, etc patch
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::pushJumpContext):
+ (KJS::CodeGenerator::popJumpContext):
+ (KJS::CodeGenerator::jumpContextForLabel):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::Node::emitThrowError):
+ (KJS::ContinueNode::emitCode):
+ (KJS::BreakNode::emitCode):
+ (KJS::ReturnNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-20 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed Machine.cpp from AllInOneFile.cpp, and manually inlined a few
+ things that used to be inlined automatically.
+
+ 1.9% speedup on SunSpider.
+
+ My hope is that we'll face fewer surprises in Machine.cpp codegen, now
+ that GCC is making fewer decisions. The speedup seems to confirm that.
+
+2008-04-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18642: Iterator context may get placed into the return register, leading to much badness
+ <https://bugs.webkit.org/show_bug.cgi?id=18642>
+
+ To prevent incorrectly reusing what will become the result register for
+ eval and global code execution, we need to request and ref the destination
+ in advance of codegen. Unfortunately this may lead to unnecessary copying,
+ although in future we can probably limit this. Curiously SunSpider shows
+ a progression in a number of tests, although it comes out as a wash overall.
+
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::emitCode):
+ (KJS::ProgramNode::emitCode):
+
+2008-04-20 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Add support for AssignErrorNode, PrefixErrorNode, and PostfixErrorNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCreateError):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PostfixErrorNode::emitCode):
+ (KJS::PrefixErrorNode::emitCode):
+ (KJS::AssignErrorNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff and Mark.
+
+ Provide line number information in exceptions
+
+ Simple patch, adds line number information metadata to CodeBlock
+ and a simple method to get the line number responsible for a given
+ Instruction*.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::lineNumberForVPC):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::emitNode):
+ * VM/Machine.cpp:
+ (KJS::Machine::throwException):
+
+2008-04-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Provide "sourceURL" in exceptions
+
+ * VM/CodeBlock.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::throwException):
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::generateCode):
+ (KJS::ProgramNode::generateCode):
+
+2008-04-19 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Don't call emitCode directly on subnodes, instead use CodeGenerator::emitNode
+
+ This patch just a preparation for tracking line numbers.
+
+ * kjs/nodes.cpp:
+ (KJS::ObjectLiteralNode::emitCode):
+ (KJS::PropertyListNode::emitCode):
+ (KJS::ArgumentListNode::emitCode):
+ (KJS::TryNode::emitCode):
+
+2008-04-19 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18619: Support continue, break, and return in try .. finally blocks
+ <https://bugs.webkit.org/show_bug.cgi?id=18619>
+
+ This patch replaces the current partial finally support (which uses code
+ duplication to achieve what it does) with a subroutine based approach.
+ This has a number of advantages over code duplication:
+ * Reduced code size
+ * Simplified exception handling as the finaliser code only exists in
+ one place, so no "magic" is needed to get the correct handler for a
+ finaliser.
+ * When we support instruction to line number mapping we won't need to
+ worry about the dramatic code movement caused by duplication
+
+ On the downside it is necessary to add two new opcodes, op_jsr and op_sret
+ to enter and exit the finaliser subroutines, happily SunSpider reports
+ a performance progression (gcc amazes me) and ubench reports a wash.
+
+ While jsr and sret provide a mechanism that allows us to enter and exit
+ any arbitrary finaliser we need to, it was still necessary to increase
+ the amount of information tracked when entering and exiting both finaliser
+ scopes and dynamic scopes ("with"). This means "scopeDepth" is now
+ the combination of "finaliserDepth" and "dynamicScopeDepth". We also
+ now use a scopeContextStack to ensure that we pop scopes and execute
+ finalisers in the correct order. This increases the cost of "with" nodes
+ during codegen, but it should not be significant enough to effect real
+ world performance and greatly simplifies codegen for return, break and
+ continue when interacting with finalisers.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ Pretty printing of jsr/sret opcodes
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::emitPushScope):
+ (KJS::CodeGenerator::emitPopScope):
+ Dynamic scopes need to be tracked on the scopeContextStack now
+
+ (KJS::CodeGenerator::pushFinallyContext):
+ (KJS::CodeGenerator::popFinallyContext):
+ Handle entry and exit from code regions with finalisers. This is
+ needed solely to support return, continue and break inside finaliser
+ regions.
+
+ (KJS::CodeGenerator::emitComplexJumpScopes):
+ Helper function for emitJumpScopes to handle the complex codegen
+ needed to handle return, continue and break inside a finaliser region
+
+ (KJS::CodeGenerator::emitJumpScopes):
+ Updated to be aware of finalisers, if a cross-scope jump occurs inside
+ a finaliser we hand off codegen to emitComplexJumpScopes, otherwise
+ we can handle the normal (trivial) case with a single instruction.
+
+ (KJS::CodeGenerator::emitJumpSubroutine):
+ (KJS::CodeGenerator::emitSubroutineReturn):
+ Trivial opcode emitter functions.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::scopeDepth):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ Implement op_jsr and op_sret.
+
+ * VM/Opcode.h:
+ Ad op_jsr and op_sret
+
+ * kjs/nodes.cpp:
+ (KJS::TryNode::emitCode):
+ Fix codegen for new finaliser model.
+
+2008-04-17 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Oliver Hunt.
+
+ Remove unnecessary files from testkjs, testapi and minidom targets.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-04-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed ASSERT seen during run-sunspider of a debug build.
+
+ * VM/CodeGenerator.h: Made the default codegen buffers bigger. SunSpider
+ runs all tests in one global environment, so you end up with more than
+ 128 locals. This is just a stop-gap until we code up a real
+ solution to arbitrary symbol and label limits.
+
+2008-04-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed a bug in exception unwinding, where we wouldn't deref the scope
+ chain in global scope, so we would leak ScopeChainNodes when exceptions
+ were thrown inside "with" and "catch" scopes.
+
+ Also did some cleanup of the unwinding code along the way.
+
+ Scope chain reference counting is still wrong in a few ways. I thought
+ I would fix this portion of it first.
+
+ run-sunspider shows no change.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::throwException):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+
+2008-04-17 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Add more exception checking to toNumber conversions
+
+ This corrects op_pre_dec, op_negate, op_mod and op_sub.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-17 Geoffrey Garen <ggaren@apple.com> and Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver Hunt.
+
+ Behold: eval.
+
+ Introduced a new opcode: op_call_eval. In the normal case, it performs
+ an eval. In the case where eval has been overridden in some way, it
+ performs a function call.
+
+ * VM/CodeGenerator.h: Added a feature so the code generator knows not
+ to optimized locals in eval code.
+
+2008-04-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Added some ASSERTs to document codegen failures in
+ run-javascriptcore-tests.
+
+ For all tests, program-level codegen now either succeeds, or fails with
+ an ASSERT.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar):
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::newTemporary):
+ (KJS::CodeGenerator::newLabel):
+
+2008-04-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed another case of a dst register being an unreferenced temporary
+ (caused an ASSERT when running the full sunspider suite).
+
+ * kjs/nodes.cpp:
+ (KJS::CaseBlockNode::emitCodeForBlock):
+
+2008-04-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - add documentation (and meaningful parameter names) for arithmetic and bitwise binary ops
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitMul):
+ (KJS::CodeGenerator::emitDiv):
+ (KJS::CodeGenerator::emitMod):
+ (KJS::CodeGenerator::emitSub):
+ (KJS::CodeGenerator::emitLeftShift):
+ (KJS::CodeGenerator::emitRightShift):
+ (KJS::CodeGenerator::emitUnsignedRightShift):
+ (KJS::CodeGenerator::emitBitAnd):
+ (KJS::CodeGenerator::emitBitXOr):
+ (KJS::CodeGenerator::emitBitOr):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::MultNode::emitCode):
+ (KJS::DivNode::emitCode):
+ (KJS::ModNode::emitCode):
+ (KJS::SubNode::emitCode):
+ (KJS::LeftShiftNode::emitCode):
+ (KJS::RightShiftNode::emitCode):
+ (KJS::UnsignedRightShiftNode::emitCode):
+ (KJS::BitAndNode::emitCode):
+ (KJS::BitXOrNode::emitCode):
+ (KJS::BitOrNode::emitCode):
+ (KJS::emitReadModifyAssignment):
+ (KJS::ReadModifyResolveNode::emitCode):
+
+2008-04-16 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Exception checks for toNumber in op_pre_inc
+
+ This is somewhat more convoluted than the simple hadException checks
+ we currently use. Instead we use special toNumber conversions that
+ select between the exception and ordinary vPC. This allows us to
+ remove any branches in the common case (incrementing a number).
+
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::toNumber):
+ * ChangeLog:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/JSPropertyNameIterator.cpp:
+ (KJS::JSPropertyNameIterator::toNumber):
+ * VM/JSPropertyNameIterator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/ExecState.h:
+ * kjs/JSNotAnObject.cpp:
+ (KJS::JSNotAnObject::toNumber):
+ * kjs/JSNotAnObject.h:
+ * kjs/internal.cpp:
+ (KJS::StringImp::toNumber):
+ (KJS::NumberImp::toNumber):
+ (KJS::GetterSetterImp::toNumber):
+ * kjs/internal.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::toNumber):
+ * kjs/object.h:
+ * kjs/value.h:
+ (KJS::JSValue::toNumber):
+
+2008-04-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - ensure that activations are kept in a register to protect them from GC
+
+ Also renamed OptionalCalleeScopeChain constant to OptionalCalleeActivation, since
+ that is what is now kept there, and there is no more need to keep the scope chain in
+ the register file.
+
+ * VM/Machine.cpp:
+ (KJS::initializeCallFrame):
+ (KJS::scopeChainForCall):
+ * VM/Machine.h:
+ (KJS::Machine::):
+
+2008-04-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Made "this" work in program code / global scope.
+
+ The machine can initialize "this" prior to execution because it knows
+ that, for program code, "this" is always stored in lr1.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ * VM/Machine.h:
+ (KJS::Machine::):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-04-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed a codegen bug when returning from inside a dynamic scope (a with
+ or catch block): we need to pop any dynamic scope(s) that have been
+ added so op_ret can find the activation object at the top of the scope
+ chain.
+
+ * kjs/nodes.cpp:
+ (KJS::ReturnNode::emitCode): If we're returning from inside a dynamic
+ scope, emit a jmp_scopes to take care of popping any dynamic scope(s)
+ and then branching to the return instruction.
+
+2008-04-16 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - document the add and get_prop_id opcodes
+
+ In addition to adding documentation in comments, I changed
+ references to register IDs or indices relating to these opcodes to
+ have meaningful names instead of r0 r1 r2.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitAdd):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.cpp:
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+ (KJS::PostIncDotNode::emitCode):
+ (KJS::PostDecDotNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+ (KJS::AddNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+
+2008-04-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt and Maciej Stachowiak.
+
+ Fixed a codegen bug in with and switch, and added an ASSERT to
+ make sure it doesn't happen again.
+
+ emitCode() assumes that dst, if non-zero, is either referenced or
+ non-temporary (i.e., it assumes that newTemporary() will return a
+ register not equal to dst). Certain callers to emitCode() weren't
+ guaranteeing that to be so, so temporary register values were being
+ overwritten.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::emitNode): ASSERT that dst is referenced or non-temporary.
+
+ * kjs/nodes.cpp:
+ (KJS::CommaNode::emitCode): Reference the dst we pass.
+
+ (KJS::WithNode::emitCode): No need to pass an explicit dst register.
+
+ (KJS::CaseBlockNode::emitCodeForBlock): No need to pass an explicit dst register.
+ (KJS::SwitchNode::emitCode): No need to pass an explicit dst register.
+
+ * kjs/nodes.h: Made dst the last parameter to emitCodeForBlock, to match
+ emitCode.
+
+2008-04-15 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18526: Throw exceptions when resolve fails for op_resolve_base_and_func.
+ <https://bugs.webkit.org/show_bug.cgi?id=18526>
+
+ Very simple fix, sunspider shows a 0.7% progression, ubench shows a 0.4% regression.
+
+ * VM/Machine.cpp:
+ (KJS::resolveBaseAndFunc):
+ (KJS::Machine::privateExecute):
+
+2008-04-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix incorrect result on 3d-raytrace test
+
+ Oliver found and tracked down this bug, I just typed in the fix.
+
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall): When setting omitted parameters to undefined,
+ account for the space for local variables.
+
+2008-04-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix codegen handling of dst registers
+
+ 1.006x speedup (not sure why).
+
+ Most emitCode functions take an optional "dst" parameter that says
+ where the output of the instruction should be written. I made some
+ functions for convenient handling of the dst register:
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::tempDestination): Takes the dst register. Returns it if
+ it is not null and is a temporary, otherwise allocates a new temporary. This is
+ intended for cases where an intermediate value might be written into the dst
+
+ (KJS::CodeGenerator::finalDestination): Takes the dst register and an optional
+ register that was used as a temp destination. Picks the right thing for the final
+ output. Intended to be used as the output register for the instruction that generates
+ the final value of a particular node.
+
+ (KJS::CodeGenerator::moveToDestinationIfNeeded): Takes dst and a
+ RegisterID; moves from the register to dst if dst is defined and
+ different from the register. This is intended for cases where the
+ result of a node is already in a specific register (likely a
+ local), and so no code needs to be generated unless a specific
+ destination has been requested, in which case a move is needed.
+
+ I also applied these methods throughout emitCode functions. In
+ some cases this was just cleanup, in other cases I fixed actual
+ codegen bugs. Below I have given specific comments for the cases
+ where I believe I fixed a codegen bug, or improved quality of codegen.
+
+ * kjs/nodes.cpp:
+ (KJS::NullNode::emitCode):
+ (KJS::FalseNode::emitCode):
+ (KJS::TrueNode::emitCode):
+ (KJS::NumberNode::emitCode):
+ (KJS::StringNode::emitCode):
+ (KJS::RegExpNode::emitCode):
+ (KJS::ThisNode::emitCode): Now avoids emitting a mov when dst is
+ the same as the this register (the unlikely case of "this = this");
+ (KJS::ResolveNode::emitCode): Now avoids emitting a mov when dst
+ is the same as the local regiester, in the local var case (the
+ unlikely case of "x = x");
+ (KJS::ArrayNode::emitCode): Fixed a codegen bug where array
+ literal element expressions may have observed an intermediate
+ value of constructing the array.
+ (KJS::ObjectLiteralNode::emitCode):
+ (KJS::PropertyListNode::emitCode): Fixed a codegen bug where object literal
+ property definition expressions may have obesrved an intermediate value of
+ constructing the object.
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::NewExprNode::emitCode):
+ (KJS::FunctionCallValueNode::emitCode):
+ (KJS::FunctionCallBracketNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PostIncBracketNode::emitCode):
+ (KJS::PostDecBracketNode::emitCode):
+ (KJS::PostIncDotNode::emitCode):
+ (KJS::PostDecDotNode::emitCode):
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::DeleteBracketNode::emitCode):
+ (KJS::DeleteDotNode::emitCode):
+ (KJS::DeleteValueNode::emitCode):
+ (KJS::VoidNode::emitCode):
+ (KJS::TypeOfResolveNode::emitCode):
+ (KJS::TypeOfValueNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode): Fixed a codegen bug where the final
+ value would not be output to the dst register in the local var case.
+ (KJS::PreDecResolveNode::emitCode): Fixed a codegen bug where the final
+ value would not be output to the dst register in the local var case.
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+ (KJS::UnaryPlusNode::emitCode):
+ (KJS::NegateNode::emitCode):
+ (KJS::BitwiseNotNode::emitCode):
+ (KJS::LogicalNotNode::emitCode):
+ (KJS::MultNode::emitCode):
+ (KJS::DivNode::emitCode):
+ (KJS::ModNode::emitCode):
+ (KJS::AddNode::emitCode):
+ (KJS::SubNode::emitCode):
+ (KJS::LeftShiftNode::emitCode):
+ (KJS::RightShiftNode::emitCode):
+ (KJS::UnsignedRightShiftNode::emitCode):
+ (KJS::LessNode::emitCode):
+ (KJS::GreaterNode::emitCode):
+ (KJS::LessEqNode::emitCode):
+ (KJS::GreaterEqNode::emitCode):
+ (KJS::InstanceOfNode::emitCode):
+ (KJS::InNode::emitCode):
+ (KJS::EqualNode::emitCode):
+ (KJS::NotEqualNode::emitCode):
+ (KJS::StrictEqualNode::emitCode):
+ (KJS::NotStrictEqualNode::emitCode):
+ (KJS::BitAndNode::emitCode):
+ (KJS::BitXOrNode::emitCode):
+ (KJS::BitOrNode::emitCode):
+ (KJS::LogicalAndNode::emitCode):
+ (KJS::LogicalOrNode::emitCode):
+ (KJS::ConditionalNode::emitCode):
+ (KJS::emitReadModifyAssignment): Allow an out argument separate from the operands,
+ needed for fixes below.
+ (KJS::ReadModifyResolveNode::emitCode): Fixed a codegen bug where the right side of
+ the expression may observe an intermediate value.
+ (KJS::AssignResolveNode::emitCode): Fixed a codegen bug where the right side of the
+ expression may observe an intermediate value.
+ (KJS::ReadModifyDotNode::emitCode): Fixed a codegen bug where the right side of the
+ expression may observe an intermediate value.
+ (KJS::ReadModifyBracketNode::emitCode): Fixed a codegen bug where the right side of the
+ expression may observe an intermediate value.
+ (KJS::CommaNode::emitCode): Avoid writing temporary value to dst register.
+ (KJS::ReturnNode::emitCode): Void return should return undefined, not null.
+ (KJS::FuncExprNode::emitCode):
+
+2008-04-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix huge performance regression (from trunk) in string-unpack-code
+
+ This restores string-unpack-code performance to parity with
+ trunk (2.27x speedup relative to previous SquirrelFish)
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute): Shrink register file after call to avoid
+ growing repeatedly.
+
+2008-04-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed dumpCallFrame to match our new convention of passing around a
+ ScopeChainNode* instead of a ScopeChain*.
+
+ * JavaScriptCore.exp:
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpCallFrame):
+ * VM/Machine.h:
+
+2008-04-15 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18436: Need to throw exception on read/modify/write or similar resolve for nonexistent property
+ <https://bugs.webkit.org/show_bug.cgi?id=18436>
+
+ Add op_resolve_base_and_property for read/modify/write operations,
+ this adds a "superinstruction" to resolve the base and value of a
+ property simultaneously. Just using resolveBase and resolve results
+ in an 5% regression in ubench, 30% in loop-empty-resolve (which is
+ expected). 1.3% progression in sunspider, 2.1% in ubench, with a
+ 21% gain in loop-empty-resolve. The only outlier is function-missing-args
+ which gets a 3% regression that I could never resolve.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitResolveBaseAndProperty):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::resolveBaseAndProperty):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PostDecResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+
+2008-04-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fixed "SquirrelFish crashes due to bad scope chain on some SunSpider tests"
+ https://bugs.webkit.org/show_bug.cgi?id=18508
+
+ 3d-raytrace and string-unpack-code now run.
+
+ The basic approach is to pass around ScopeChainNode* instead of
+ ScopeChain*, which in addition to not becoming suddenly an invalid
+ pointer also saves an indirection.
+
+ This is an 0.4% speedup on SunSpider --squirrelfish (1.8% on --ubench)
+
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ (KJS::resolveBase):
+ (KJS::resolveBaseAndFunc):
+ (KJS::initializeCallFrame):
+ (KJS::scopeChainForCall):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::throwException):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * VM/Register.h:
+ (KJS::Register::):
+ * kjs/nodes.cpp:
+ (KJS::EvalNode::generateCode):
+ (KJS::FunctionBodyNode::generateCode):
+ (KJS::ProgramNode::generateCode):
+ (KJS::ProgramNode::processDeclarations):
+ (KJS::EvalNode::processDeclarations):
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::makeFunction):
+ * kjs/nodes.h:
+ (KJS::ProgramNode::):
+ (KJS::EvalNode::):
+ (KJS::FunctionBodyNode::):
+ * kjs/object.h:
+ * kjs/scope_chain.h:
+ (KJS::ScopeChainNode::ScopeChainNode):
+ (KJS::ScopeChainNode::deref):
+ (KJS::ScopeChainIterator::ScopeChainIterator):
+ (KJS::ScopeChainIterator::operator*):
+ (KJS::ScopeChainIterator::operator->):
+ (KJS::ScopeChain::ScopeChain):
+ (KJS::ScopeChain::node):
+ (KJS::ScopeChain::deref):
+ (KJS::ScopeChain::ref):
+ (KJS::ScopeChainNode::ref):
+ (KJS::ScopeChainNode::release):
+ (KJS::ScopeChainNode::begin):
+ (KJS::ScopeChainNode::end):
+
+2008-04-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed crash when accessing registers in a torn-off activation object.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::copyRegisters): Update our registerOffset after
+ copying our registers, since our offset should now be relative to
+ our private register array, not the shared register file.
+
+2008-04-14 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix a codegen flaw that makes some tests run way too fast or way too slow
+
+ The basic problem was that FunctionCallResolveNode results in
+ codegen which can incorrectly write an intermediate value into the
+ dst register even when that is a local. I added convenience
+ functions to CodeGenerator for getting this right, but for now I
+ only fixed FunctionCallResolve.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::tempDestination):
+ (KJS::CodeGenerator::):
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::emitCode):
+
+2008-04-14 Gabor Loki <loki@inf.u-szeged.hu>
+
+ Reviewed and slightly tweaked by Geoffrey Garen.
+
+ Bug 18489: Squirrelfish doesn't build on linux
+ <https://bugs.webkit.org/show_bug.cgi?id=18489>
+
+ * JavaScriptCore.pri: Add VM into include path and its files into
+ source set
+ * VM/JSPropertyNameIterator.cpp: Fix include name
+ * VM/Machine.cpp: Add UNLIKELY macro for GCC
+ * VM/Machine.h: Add missing includes
+ * VM/RegisterFile.cpp: Add missing include
+ * kjs/testkjs.pro: Add VM into include path
+
+2008-04-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Restored OwnPtr in some places where I had removed it previously. We
+ can have an OwnPtr to an undefined class in a header as long as the
+ class's destructor isn't in the header.
+
+2008-04-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed access to "this" inside dynamic scopes.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::registerForLocal): Always return a register for
+ "this", even if we're not optimizing access to other locals. Because
+ "this" is a keyword, it's always in a register and always accessible.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::shouldOptimizeLocals): Factored out a function
+ for determining whether we should optimize access to locals, since
+ eval will need to make this test a little more complicated.
+
+2008-04-14 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Adam.
+
+ - fix crash when running SunSpider full harness
+
+ When growing the register file's buffer to make space for new globals,
+ make sure to copy accounting for the fact that the new space is logically
+ at the beginning of the buffer in this case, instead of at the end as when
+ growing for a new call frame.
+
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::newBuffer):
+ (KJS::RegisterFile::growBuffer):
+ (KJS::RegisterFile::addGlobalSlots):
+ * VM/RegisterFile.h:
+
+2008-04-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Mark constant pools for global and eval code (collectively known as
+ "program code"). (Constant pools for function code are already marked by
+ their functions.)
+
+ The global object is responsible for marking program code constant
+ pools. Code blocks add themselves to the mark set at creation time, and
+ remove themselves from the mark set at destruction time.
+
+ sunspider --squirrelfish reports a 1% speedup, perhaps because
+ generateCode() is now non-virtual.
+
+ * kjs/nodes.cpp: I had to use manual init and delete in this file
+ because putting an OwnPtr into the header would have created a circular
+ header dependency.
+
+2008-04-10 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Bug 18231: Improve support for function call nodes in SquirrelFish
+ <https://bugs.webkit.org/show_bug.cgi?id=18231>
+
+ Use correct value of 'this' for function calls.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitResolveBaseAndFunc):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::resolveBaseAndFunc):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::emitCode):
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ This time for sure.
+
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed Interpreter::execute to honor the new model for returning non-NULL
+ values when an exception is thrown.
+
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-04-10 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Fix SquirrelFish interpreter to pass internal exceptions back to
+ native code correctly.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-10 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Replace the use of getCallData in op_construct with the new
+ getConstructData function that replaces implementsConstruct.
+
+ * API/JSCallbackConstructor.cpp:
+ (KJS::JSCallbackConstructor::getConstructData):
+ * API/JSCallbackConstructor.h:
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::getConstructData):
+ (KJS::::construct):
+ * API/JSObjectRef.cpp:
+ (JSObjectIsConstructor):
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/CallData.h:
+ * kjs/ConstructData.h: Copied from JavaScriptCore/kjs/CallData.h.
+ * kjs/array_object.cpp:
+ (KJS::ArrayObjectImp::getConstructData):
+ * kjs/array_object.h:
+ * kjs/bool_object.cpp:
+ (KJS::BooleanObjectImp::getConstructData):
+ * kjs/bool_object.h:
+ * kjs/date_object.cpp:
+ (KJS::DateObjectImp::getConstructData):
+ * kjs/date_object.h:
+ * kjs/error_object.cpp:
+ (KJS::ErrorObjectImp::getConstructData):
+ (KJS::NativeErrorImp::getConstructData):
+ * kjs/error_object.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::getCallData):
+ (KJS::FunctionImp::getConstructData):
+ (KJS::FunctionImp::construct):
+ * kjs/function.h:
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::getConstructData):
+ * kjs/function_object.h:
+ * kjs/nodes.cpp:
+ (KJS::NewExprNode::inlineEvaluate):
+ * kjs/number_object.cpp:
+ (KJS::NumberObjectImp::getConstructData):
+ * kjs/number_object.h:
+ * kjs/object.cpp:
+ * kjs/object.h:
+ * kjs/object_object.cpp:
+ (KJS::ObjectObjectImp::getConstructData):
+ * kjs/object_object.h:
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpObjectImp::getConstructData):
+ * kjs/regexp_object.h:
+ * kjs/string_object.cpp:
+ (KJS::StringObjectImp::getConstructData):
+ * kjs/string_object.h:
+ * kjs/value.cpp:
+ (KJS::JSCell::getConstructData):
+ * kjs/value.h:
+ (KJS::JSValue::getConstructData):
+
+2008-04-10 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18420: SquirrelFish: need to throw Reference and Type errors
+ when attempting invalid operations on JSValues
+
+ Add validation and exception checks to SquirrelFish so that the
+ correct exceptions are thrown for undefined variables, type errors
+ and toObject failure. Also handle exceptions thrown by native
+ function calls.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/ExceptionHelpers.cpp: Added.
+ (KJS::substitute):
+ (KJS::createError):
+ (KJS::createUndefinedVariableError):
+ * VM/ExceptionHelpers.h: Added.
+ Helper functions
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ Modified to signal failure
+ (KJS::isNotObject):
+ Wrapper for JSValue::isObject and exception creation (these need
+ to be merged, lest GCC go off the deep end)
+ (KJS::Machine::privateExecute):
+ Adding the many exception and validity checks.
+
+ * kjs/JSNotAnObject.cpp: Added.
+ Stub object used to reduce the need for multiple exception checks
+ when toObject fails.
+ (KJS::JSNotAnObject::toPrimitive):
+ (KJS::JSNotAnObject::getPrimitiveNumber):
+ (KJS::JSNotAnObject::toBoolean):
+ (KJS::JSNotAnObject::toNumber):
+ (KJS::JSNotAnObject::toString):
+ (KJS::JSNotAnObject::toObject):
+ (KJS::JSNotAnObject::mark):
+ (KJS::JSNotAnObject::getOwnPropertySlot):
+ (KJS::JSNotAnObject::put):
+ (KJS::JSNotAnObject::deleteProperty):
+ (KJS::JSNotAnObject::defaultValue):
+ (KJS::JSNotAnObject::construct):
+ (KJS::JSNotAnObject::callAsFunction):
+ (KJS::JSNotAnObject::getPropertyNames):
+ * kjs/JSNotAnObject.h: Added.
+ (KJS::JSNotAnObject::JSNotAnObject):
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toObject):
+ modified to create an JSNotAnObject rather than throwing an exception
+ directly.
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Pass a function body node its function's scope chain, rather than the
+ current execution context's scope chain, when compiling it.
+
+ This doesn't matter yet, but it will once we start using the scope
+ chain during compilation.
+
+ sunspider --squirrelfish notes a tiny speedup.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix two bugs when throwing exceptions from re-entrant JS calls:
+
+ (1) Don't shrink the register file to 0, since our caller may still
+ be using it.
+
+ (2) In case of exception, return jsNull() instead of 0 because,
+ surprisingly, some JavaScriptCore clients rely on a function's return
+ value being safe to operate on even if the function threw an exception.
+
+ Also:
+
+ - Changed FunctionImp::callAsFunction to honor the new semantics of
+ exceptions not returning 0.
+
+ - Renamed "handlerPC" to "handlerVPC" to match other uses of "VPC".
+
+ - Renamed "exceptionData" to "exceptionValue", because "data" seemed to
+ imply something more than just a JSValue.
+
+ - Merged prepareException into throwException, since throwException was
+ its only caller, and it seemed weird that throwException didn't take
+ an exception as an argument.
+
+ sunspider --squirrelfish does not seem to complain on my machine, but it
+ complains a little (.6%) on Oliver's.
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed op_construct for CallTypeNative to reacquire "r" before setting
+ its return value, since registerBase can theoretically change during the
+ execution of arbitrary code. (Not sure if any native constructors
+ actually make this possible.)
+
+ sunspider --squirrelfish does not seem to complain.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt and Sam Weinig.
+
+ Re-entrant execution of function code (global code -> built-in function
+ -> JS function):
+
+ Miraculously, sunspider --squirrelfish does not seem to complain.
+
+ A re-entrant function call is the same as a normal function call with
+ one exception: the re-entrant call leaves everything except for
+ CallerCodeBlock in the call frame header uninitialized, since the call
+ doesn't need to return to JS code. (It sets CallerCodeBlock to 0, to
+ indicate that the call shouldn't return to JS code.)
+
+ Also fixed a few issues along the way:
+
+ - Fixed two bugs in the read-write List implementation that caused
+ m_size and m_buffer to go stale.
+
+ - Changed native call code to update "r" *before* setting the return
+ value, since the call may in turn call JS code, which changes the value
+ of "r".
+
+ - Migrated initialization of "r" outside of Machine::privateExecute,
+ because global code and function code initialize "r" differently.
+
+ - Migrated a codegen warning from Machine::privateExecute to the wiki.
+
+ - Removed unnecessary "r" parameter from slideRegisterWindowForCall
+
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::scopeChainForCall):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ * kjs/list.cpp:
+ (KJS::List::getSlice):
+ * kjs/list.h:
+ (KJS::List::clear):
+
+2008-04-10 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix problem with code generation for return with no argument
+
+ 3d-cube now runs
+
+ * kjs/nodes.cpp:
+ (KJS::ReturnNode::emitCode):
+
+2008-04-10 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - Implement support for JS constructors
+
+ access-binary-trees and access-nbody now run.
+
+ Inexplicably a 1% speedup.
+
+ * VM/Machine.cpp:
+ (KJS::initializeCallFrame):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ (KJS::Machine::):
+
+2008-04-10 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - More code cleanup in preparation for JS constructors
+
+ Factor the remaining interesting parts of JS function calls into
+ slideRegisterWindowForCall and scopeChainForCall.
+
+ * VM/Machine.cpp:
+ (KJS::slideRegisterWindowForCall):
+ (KJS::scopeChainForCall):
+ (KJS::Machine::privateExecute):
+
+2008-04-10 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - Code cleanup in preparation for JS constructors
+
+ - Renamed returnInfo to callFrame.
+ - Made an enum which defines what goes where in the call frame.
+ - Factored out initializeCallFrame function from op_call
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall):
+ (KJS::CodeGenerator::emitConstruct):
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters):
+ (KJS::initializeCallFrame):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ (KJS::Machine::):
+
+2008-04-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed two bugs in register allocation for function calls:
+
+ (1) op_call used to allocate codeBlock->numVars too many registers for
+ each call frame, due to duplicated math. Fixing this revealed...
+
+ (2) By unconditionally calling resize(), op_call used to truncate the
+ register file when calling a function whose registers fit wholly within
+ the register file already allocated by its caller.
+
+ sunspider --squirrelfish reports no regression.
+
+ I also threw in a little extra formatting to dumpCallFrame, because it
+ helped me debug these issues.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/RegisterFile.h:
+ (KJS::RegisterFile::shrink):
+ (KJS::RegisterFile::grow):
+ * VM/RegisterFileStack.cpp:
+ (KJS::RegisterFileStack::popRegisterFile):
+
+2008-04-09 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Next step toward re-entrant execution of function code (global code ->
+ built-in function -> JS function):
+
+ Made op_ret return from Machine::privateExecute if its calling codeBlock
+ is NULL.
+
+ I'm checking this in by itself to demonstrate that a more clever
+ mechanism is not necessary for performance.
+
+ sunspider --squirrelfish reports no regression.
+
+ * ChangeLog:
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+
+2008-04-09 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Next step toward re-entrant execution of function code (global code ->
+ built-in function -> JS function):
+
+ Made Machine::execute return a value.
+
+ Sketched out some code for Machine::execute for functions -- still
+ doesn't work yet, though.
+
+ sunspider --squirrelfish reports no regression.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+ * kjs/testkjs.cpp:
+ (runWithScripts):
+
+2008-04-09 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ First step toward re-entrant execution of function code (global code ->
+ built-in function -> JS function):
+
+ Tiny bit of refactoring in the Machine class.
+
+ sunspider --squirrelfish reports no regression.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::execute):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ (KJS::Machine::isGlobalCallFrame):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+
+2008-04-08 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Support for re-entrant execution of global code (global code -> built-in
+ function -> global code).
+
+ Keep a stack of register files instead of just one. Globals propogate
+ between register files as the register files enter and exit the stack.
+
+ An activation still uses its own register file's base as its
+ registerBase, but the global object uses the register file *stack*'s
+ registerBase, which updates dynamically to match the register file at
+ the top of the stack.
+
+ sunspider --squirrelfish reports no regression.
+
+2008-04-08 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - initial preparatory work for JS constructors
+
+ 1) Allocate registers for the returnInfo block and "this" value when generating code for
+ op_construct. These are not used yet, but the JS branch of op_construct will use them.
+
+ 2) Adjust argc and argv appropriately for native constructor calls.
+
+ 3) Assign return value in a more straightforward way in op_ret since this is actually
+ a bit faster (and makes up for the allocation of extra registers above).
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitConstruct):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed crashing SunSpider tests.
+
+ Let's just pretend this never happened, bokay?
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/CodeGenerator.h:
+ * VM/RegisterFile.cpp:
+ (KJS::RegisterFile::addGlobals):
+
+2008-04-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Restored dumping of generated code as a command-line switch:
+ run-testkjs -d will do it.
+
+2008-04-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Next step toward supporting re-entrant evaluation: Moved register file
+ maintenance code into a proper "RegisterFile" class.
+
+ There's a subtle change to the register file's internal layout: for
+ global code / the global object, registerOffset is always 0 now. In
+ other words, all register counting starts at 0, not 0 + (number of
+ global variables). The helps simplify accounting when the number of
+ global variables changes.
+
+2008-04-07 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18338: Support exceptions in SquirrelFish <http://bugs.webkit.org/show_bug.cgi?id=18338>
+
+ Initial support for exceptions in SquirrelFish, only supports finalisers in the
+ simple cases (eg. exceptions and non-goto/return across finaliser boundaries).
+ This doesn't add the required exception checks to existing code, it merely adds
+ support for throw, catch, and the required stack unwinding.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ (KJS::CodeBlock::getHandlerForVPC):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCatch):
+ (KJS::CodeGenerator::emitThrow):
+ * VM/CodeGenerator.h:
+ * VM/JSPropertyNameIterator.cpp:
+ (KJS::JSPropertyNameIterator::create):
+ * VM/Machine.cpp:
+ (KJS::prepareException):
+ (KJS::Machine::unwindCallFrame):
+ (KJS::Machine::throwException):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::ThrowNode::emitCode):
+ (KJS::TryNode::emitCode):
+ * kjs/nodes.h:
+ * kjs/scope_chain.cpp:
+ (KJS::ScopeChain::depth):
+ * kjs/scope_chain.h:
+
+2008-04-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ First step toward supporting re-entrant evaluation: Switch register
+ clients from using "registers", a pointer to a register vector, to
+ "registerBase", an indirect pointer to the logical first entry in the
+ register file. (The logical first entry is the first entry that is not
+ a global variable).
+
+ With a vector, offsets into the register file remain good when the
+ underlying buffer reallocates, but they go bad when the logical
+ first entry moves. (The logical first entry moves when new global
+ variables get added to the beginning of the register file.) With an
+ indirect pointer to the logical first entry, offsets will remain good
+ regardless.
+
+ 1.4% speedup on sunspider --squirrelfish. I suspect this is due to
+ reduced allocation when creating closures, and reduced indirection
+ through the register vector.
+
+ * wtf/Vector.h: Added an accessor for an indirect pointer to the vector's
+ buffer, which we currently use (incorrectly) for registerBase. This is
+ temporary scaffolding to allow us to change client code without
+ changing behavior.
+
+2008-04-06 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Implement codegen for ReadModifyDotNode.
+
+ * kjs/nodes.cpp:
+ (KJS::ReadModifyDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-06 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Fix codegen for PostIncDotNode and implement codegen for PostIncBracketNode,
+ PostDecBracketNode and PostDecDotNode.
+
+ * kjs/nodes.cpp:
+ (KJS::PostIncBracketNode::emitCode):
+ (KJS::PostDecBracketNode::emitCode):
+ (KJS::PostIncDotNode::emitCode):
+ (KJS::PostDecDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-06 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Implement codegen for PreDecResolveNode, PreIncBracketNode, PreDecBracketNode,
+ PreIncDotNode and PreDecDotNode. This required adding one new op code, op_pre_dec.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitPreDec):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::PreDecResolveNode::emitCode):
+ (KJS::PreIncBracketNode::emitCode):
+ (KJS::PreDecBracketNode::emitCode):
+ (KJS::PreIncDotNode::emitCode):
+ (KJS::PreDecDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Improved register dumping, plus a liberal smattering of "const". Here's
+ what the new format looks like:
+
+ (gdb) call (void)dumpCallFrame(codeBlock, scopeChain, registers->begin(), r)
+ 4 instructions; 48 bytes at 0x509210; 3 locals (2 parameters); 1 temporaries
+
+ [ 0] load lr1, undefined(@k0)
+ [ 3] load lr1, 2(@k1)
+ [ 6] add tr0, lr2, lr1
+ [ 10] ret tr0
+
+ Constants:
+ k0 = undefined
+ k1 = 2
+
+ Register frame:
+
+ ----------------------------------------
+ use | address | value
+ ----------------------------------------
+ [return info] | 0x80ac08 | 0x5081c0
+ [return info] | 0x80ac0c | 0x508e90
+ [return info] | 0x80ac10 | 0x504acc
+ [return info] | 0x80ac14 | 0x2
+ [return info] | 0x80ac18 | 0x0
+ [return info] | 0x80ac1c | 0x7
+ [return info] | 0x80ac20 | 0x0
+ ----------------------------------------
+ [param] | 0x80ac24 | 0x1
+ [param] | 0x80ac28 | 0x7
+ [var] | 0x80ac2c | 0xb
+ [temp] | 0x80ac30 | 0xf
+
+2008-04-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Support for evaluating multiple scripts in the same global environment.
+ (Still don't support re-entrant evaluation yet.)
+
+ The main changes here are:
+
+ (1) Obey the ECMA 10.1.3 rules regarding how to resolve collisions when
+ a given symbol is declared more than once. (This patch fixes the same
+ issue for function code, too.)
+
+ (2) In the case of var and/or function collisions, reuse the existing
+ storage slot. For global code, this is required for previously
+ generated instructions to continue to work. For function code, it's
+ more of a "nice to have": it makes register layout in the case of
+ collisions easier to understand, and has the added benefit of saving
+ memory.
+
+ (3) Allocate slots in the CodeGenerator's m_locals vector in parallel
+ to register indexes in the symbol table. This ensures that, given an
+ index in the symbol table, we can find the corresponding RegisterID
+ without hashing, which speeds up codegen.
+
+ I moved responsibility for emitting var and function initialization
+ instructions into the CodeGenerator, because bookkeeping in cases where
+ var, function, and/or parameter names collide requires a lot of
+ internal knowledge about the CodeGenerator.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addVar): Removed responsibility for checking whether
+ a var declaration overwrites "arguments", because the check is
+ inappropriate for global code, which may not have a pre-existing
+ "arguments" symbol in scope. Also changed this function to return a
+ boolean indicating whether addVar actually created a new RegisterID,
+ or just reused an old one.
+
+ (KJS::CodeGenerator::CodeGenerator): Split out the constructors for
+ function code and global code, since they're quite different now.
+
+ (KJS::CodeGenerator::registerForLocal): This function does its job
+ without any hashing now.
+
+ * VM/Machine.cpp: Move old globals and update "r" before executing a
+ new script. That way, old globals stay at a constant offset from "r",
+ and previously optimized code still works.
+
+ * VM/RegisterID.h: Added the ability to allocate a RegisterID before
+ initializing its index field. We use this for parameters now.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet): Changed the ungettable getter
+ ASSERT to account for the fact that symbol indexes are all negative.
+
+2008-04-05 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Implement codegen for InNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitIn):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::InNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-05 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ - Implement codegen for DeleteResolveNode, DeleteBracketNode, DeleteDotNode and DeleteValueNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitGetPropId):
+ (KJS::CodeGenerator::emitPutPropId):
+ (KJS::CodeGenerator::emitDeletePropId):
+ (KJS::CodeGenerator::emitDeletePropVal):
+ (KJS::CodeGenerator::emitPutPropIndex):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::DeleteResolveNode::emitCode):
+ (KJS::DeleteBracketNode::emitCode):
+ (KJS::DeleteDotNode::emitCode):
+ (KJS::DeleteValueNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-04 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ - Implement codegen for Switch statements.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::pushJumpContext):
+ (KJS::CodeGenerator::popJumpContext):
+ (KJS::CodeGenerator::jumpContextForLabel):
+ * VM/CodeGenerator.h:
+ Rename LoopContext to JumpContext now that it used of Switch statements in addition
+ to loops.
+
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::ForInNode::emitCode):
+ (KJS::ContinueNode::emitCode):
+ (KJS::BreakNode::emitCode):
+ (KJS::CaseBlockNode::emitCodeForBlock):
+ (KJS::SwitchNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::CaseClauseNode::expr):
+ (KJS::CaseClauseNode::children):
+ (KJS::CaseBlockNode::):
+
+2008-04-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - fix crash in codegen from new nodes
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitConstruct):
+ * kjs/nodes.h:
+
+2008-04-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ * kjs/nodes.cpp:
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-02 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - take a shot at marking constant pools for global and eval code
+
+ Geoff says this won't really work in all cases but is an ok stopgap.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::mark):
+
+2008-04-02 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix 2x perf regression in 3d-morph
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): If we subbed in null for the global object,
+ don't toObject it, since that will throw an exception (very slowly).
+
+2008-04-02 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Geoff
+
+ - fix Release build
+
+ * kjs/nodes.cpp:
+ (KJS::getNonLocalSymbol):
+
+2008-04-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed the last vestiges of LocalStorage from JSVariableObject and
+ JSGlobalObject.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::saveLocalStorage): Save and restore from/to
+ registers. Use stub isReadOnly and isDontEnum methods for now, until
+ we really implement attributes in the symbol table.
+ (KJS::JSGlobalObject::restoreLocalStorage):
+ (KJS::JSGlobalObject::reset):
+
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames): Use stub isDontEnum method
+ for now, as above.
+ (KJS::JSVariableObject::getPropertyAttributes): ditto
+
+ * kjs/JSVariableObject.h: Removed LocalStorage from JSVariableObjectData.
+ Removed mark method, because subclasses implement different strategies for
+ marking registers.
+ (KJS::JSVariableObject::isReadOnly): Stub method
+ (KJS::JSVariableObject::isDontEnum): ditto
+
+ Changed the code below to ASSERT_NOT_REACHED() and return 0, since it
+ can no longer retrieve LocalStorage from the ExecState. (Eventually,
+ we'll just remove this code and all its friends, but that's a task for
+ later.)
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::markChildren):
+ * kjs/function.h:
+ * kjs/nodes.cpp:
+ (KJS::getNonLocalSymbol):
+ (KJS::ScopeNode::optimizeVariableAccess):
+ (KJS::ProgramNode::processDeclarations):
+
+2008-04-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Got globals?
+
+ To get things working, I had to roll out
+ http://trac.webkit.org/projects/webkit/changeset/31226 for the time
+ being.
+
+ * VM/CodeBlock.h: Removed obsolete function.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): For the sake of re-entrancy, we track
+ and restore the global object's old rOffset value. (No way to test this
+ yet, but I think it will work.)
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - mark the constant pool (at least for function code blocks)
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::mark):
+ * VM/CodeBlock.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::mark):
+ * kjs/nodes.cpp:
+ (KJS::ScopeNode::mark):
+ * kjs/nodes.h:
+ (KJS::FuncExprNode::body):
+ (KJS::FuncDeclNode::body):
+
+2008-04-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Cleaned up a few loose ends.
+
+ * JavaScriptCore.exp: Export dumpRegisters, so it's visible to gdb even
+ if we don't explicitly call it in the source text.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): No need to call dumpRegisters anymore,
+ since that was just a hack for gdb's sake.
+
+ * kjs/JSActivation.h: Removed obsolete comment.
+
+ * VM/CodeGenerator.cpp: Added ASSERTs to verify that the localCount
+ we're given matches the number of locals actually allocated.
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::CodeGenerator): Changed "localCount" to include
+ the parameter count, since we're using the word "local" to mean
+ parameter, var, function, or "this". Renamed "m_nextLocal" to
+ "m_nextVar", since "m_nextLocal" doesn't contrast well with
+ "m_nextParameter".
+
+ Also moved tracking of implicit "this" parameter from here...
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::generateCode): ... to here
+ (KJS::ProgramNode::generateCode): ... and here
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump): Added missing "\n".
+
+2008-04-01 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver.
+
+ Bug 18274: ResolveNode::emitCode() doesn't make a new temporary when dst
+ is 0, leading to incorrect codegen
+ <http://bugs.webkit.org/show_bug.cgi?id=18274>
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallBracketNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix bug in for..in codegen (gotta use ident, not m_ident)
+
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::emitCode):
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - Add suport for regexp literals
+
+ * VM/CodeBlock.cpp:
+ (KJS::regexpToSourceString):
+ (KJS::regexpName):
+ (KJS::CodeBlock::dump):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addRegExp):
+ (KJS::CodeGenerator::emitNewRegExp):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-01 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff
+
+ Add support for for..in nodes
+
+ Added two new opcodes to get_pnames and next_pname to handle iterating
+ over the set of properties on an object. This iterator is explicitly
+ invalidated and the property name array is released on standard exit
+ from the loop, otherwise we rely on GC to do the clean up for us.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitNextPropertyName):
+ (KJS::CodeGenerator::emitGetPropertyNames):
+ * VM/CodeGenerator.h:
+ * VM/JSPropertyNameIterator.cpp: Added.
+ (KJS::JSPropertyNameIterator::JSPropertyNameIterator):
+ (KJS::JSPropertyNameIterator::type):
+ (KJS::JSPropertyNameIterator::toPrimitive):
+ (KJS::JSPropertyNameIterator::getPrimitiveNumber):
+ (KJS::JSPropertyNameIterator::toBoolean):
+ (KJS::JSPropertyNameIterator::toNumber):
+ (KJS::JSPropertyNameIterator::toString):
+ (KJS::JSPropertyNameIterator::toObject):
+ (KJS::JSPropertyNameIterator::mark):
+ (KJS::JSPropertyNameIterator::next):
+ (KJS::JSPropertyNameIterator::invalidate):
+ (KJS::JSPropertyNameIterator::~JSPropertyNameIterator):
+ (KJS::JSPropertyNameIterator::create):
+ * VM/JSPropertyNameIterator.h: Added.
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * VM/Register.h:
+ (KJS::Register::):
+ * kjs/PropertyNameArray.h:
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::emitCode):
+ * kjs/nodes.h:
+ * kjs/value.h:
+
+2008-04-01 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Change CodeGenerator::emitCall() so it increments the reference count of
+ registers passed to it, and change its callers so they don't needlessly
+ increment the reference count of the registers they are passing.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall):
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::emitCode):
+ (KJS::FunctionCallDotNode::emitCode):
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - generate call for PostIncDotNode
+
+ * kjs/nodes.cpp:
+ (KJS::PostIncDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Build fix.
+
+ - fix build (not sure how this ever worked?)
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallBracketNode::emitCode):
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - generate code for FunctionCallBracketNode
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallBracketNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Geoff.
+
+ - Fix two crashing SunSpider tests
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): set up 'this' properly for native calls.
+ * kjs/list.h:
+ (KJS::List::List): Fix intialization of buffer and size from
+ vector, the initialization order was wrong.
+
+2008-04-01 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: marked ASSERT-only variables as UNUSED_PARAMs.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableInitializeVariable):
+
+2008-04-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Next step toward global code: Moved get, put, and initializeVariable
+ functionality up into JSVariableObject, and changed JSActivation to
+ rely on it.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::JSActivation):
+ (KJS::JSActivation::getOwnPropertySlot):
+ (KJS::JSActivation::put):
+ (KJS::JSActivation::initializeVariable):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::valueAt):
+ (KJS::JSVariableObject::isReadOnly):
+ (KJS::JSVariableObject::symbolTableGet):
+ (KJS::JSVariableObject::symbolTablePut):
+ (KJS::JSVariableObject::symbolTableInitializeVariable):
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - fix HashTable assertion on some SunSpider tests
+
+ Don't use -1 as the deleted value for JSValue*-keyed hashtables,
+ since it is a valid value (it's the immediate for -1).
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::JSValueHashTraits::emptyValue):
+ (KJS::CodeGenerator::JSValueHashTraits::deletedValue):
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::impossibleValue):
+
+2008-04-01 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Maciej Stachowiak.
+
+ Add support for calling Native constructors like new Array().
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitConstruct):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::NewExprNode::emitCode):
+ * kjs/nodes.h:
+
+2008-04-01 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - add some missing toOpbject calls to avoid crashing when calling methods on primitives
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-04-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Changed Machine::dumpRegisters to take a pointer instead of a reference,
+ so gdb understands how to call it.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::dumpRegisters):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+
+2008-03-31 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Fix CodeGenerator::addConstant() so it uses the functionExpressions
+ counter for function expressions, not the functions counter.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addConstant):
+
+2008-03-31 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add emitCode support for TypeOfResolveNode and TypeOfValueNode.
+ Added new opcode op_type_of to handle them.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitNot):
+ (KJS::CodeGenerator::emitInstanceOf):
+ (KJS::CodeGenerator::emitTypeOf):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::jsTypeStringForValue):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::TypeOfResolveNode::emitCode):
+ (KJS::TypeOfValueNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-31 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Fix non-computed goto version of isOpcode. op_end is a valid opcode.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::isOpcode):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Added op_post_dec.
+
+2008-03-31 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoffrey Garen.
+
+ Add support for FunctionCallDotNode.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Next step toward global code: Removed more obsolete API, moved
+ saveLocalStorage and restoreLocalStorage to JSGlobalObject subclass,
+ since it's only intended for use there.
+
+ * ChangeLog:
+ * JavaScriptCore.exp:
+ * kjs/Activation.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::saveLocalStorage):
+ (KJS::JSGlobalObject::restoreLocalStorage):
+ * kjs/JSGlobalObject.h:
+ * kjs/JSVariableObject.cpp:
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::ActivationImp):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Next step toward global code: subclass JSActivation + JSActivationData
+ from JSVariableObject + JSVariableObjectData.
+
+ JSActivation now relies on JSVariableObject for access to registers and
+ symbol table, and for some delete functionality, but not for anything
+ else yet.
+
+ (KJS::JSActivation::mark): Cleaned up the style here a little bit.
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Next step toward global code: store "rOffset" in JSVariableObjectData.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Next steps toward global code:
+
+ * Moved access to the register file into JSVariableObject.
+
+ * Added more ASSERTs to indicate obsolete APIs there are just hanging
+ around to stave off build failures.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::registers):
+ (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData):
+ (KJS::JSVariableObject::JSVariableObject):
+
+2008-03-31 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver. Tweaked somewhat by Maciej.
+
+ - implement codegen for ReadModifyResolveNode
+
+ * kjs/nodes.cpp:
+ (KJS::emitReadModifyAssignment):
+ (KJS::ReadModifyResolveNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-31 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoff.
+
+ Fix the build -- r31492 removed activation tear-off, but r31493 used it.
+
+ * kjs/nodes.cpp:
+ (KJS::FuncExprNode::makeFunction):
+
+2008-03-31 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Add support for FuncExprNode to SquirrelFish.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeBlock.h:
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::addConstant):
+ (KJS::CodeGenerator::emitNewFunctionExpression):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::FuncExprNode::emitCode):
+ (KJS::FuncExprNode::makeFunction):
+ * kjs/nodes.h:
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ First step toward global code: removed some obsolete JSGlobalObject
+ APIs, changing clients to ASSERT_NOT_REACHED.
+
+ Activation tear-off and scope chain pushing is obsolete because we
+ statically detect whether an activation + scope node is required.
+
+ The variableObject() and activationObject() accessors are obsolete
+ because they haven't been maintained, and they're mostly used by
+ node evaluation code, anyway.
+
+ The localStorage() accessor is obsolete because everything is in
+ registers now, and it's mostly used by node evaluation code, anyway.
+
+2008-03-31 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - implement codegen for bracket accessor and bracket assign
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitGetPropVal):
+ (KJS::CodeGenerator::emitPutPropVal):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Not reviewed.
+
+ Removed FIXME that I just fixed.
+
+ Added ASSERT to cover an error previously only covered by a FIXME.
+
+ * kjs/JSActivation.cpp:
+ (KJS::JSActivation::getOwnPropertySlot):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Not reviewed.
+
+ Fixed indentation inside op_call. (I had left this code badly indented
+ to make the behavior-changing diff clearer.)
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed up logging of jump instructions to follow the following style:
+
+ jump offset(->absoluteTarget)
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+
+2008-03-31 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Changed the SymbolTable API to use int instead of size_t. It has been
+ using int internally for a while now (since squirrelfish symbols can
+ have negative indices).
+
+2008-03-31 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Add support for FunctionCallValueNode.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallValueNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-31 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ 1) Implemented array literals
+
+ 2) Renamed op_object_get and op_object_put to op_get_prop_id and
+ op_put_prop_id in preparation for new variants.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitNewArray):
+ (KJS::CodeGenerator::emitGetPropId):
+ (KJS::CodeGenerator::emitPutPropId):
+ (KJS::CodeGenerator::emitPutPropIndex):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::CodeGenerator):
+ (KJS::CodeGenerator::propertyNames):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::ArrayNode::emitCode):
+ (KJS::PropertyListNode::emitCode):
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::PostIncResolveNode::emitCode):
+ (KJS::PreIncResolveNode::emitCode):
+ (KJS::AssignResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Implemented native function calls. (Re-entering from native code back
+ to JS doesn't work yet, though.)
+
+ 0.2% speedup overall, due to some inlining tweaks. 3.6% regression on
+ function-empty.js, since we're making a new virtual call and taking a
+ new branch inside every op_call.
+
+ I adjusted the JavaScriptCore calling convention to minimize overhead,
+ like so:
+
+ The machine calls a single virtual function, "getCallData", to get all
+ the data it needs for a function call. Native code still uses the old
+ "isObject()" check followed by an "implementsCall()" check, which
+ aliases to "getCallData". (We can optimize native code to use getCallData
+ at our leisure.)
+
+ To supply a list of arguments, the machine calls a new List constructor
+ that just takes a pointer and a length, without copying. Native code
+ still appends to the list one argument at a time. (We can optimize
+ native code to use the new List constructor at our leisure.)
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Changed resize() call to grow() call,
+ to encourage the compiler to inline the Vector code.
+
+ * kjs/CallData.h: Added.
+ (KJS::): CallData is a union because eventually native calls will stuff
+ a function pointer into it, to eliminate the callAsFunction virtual call.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction): Changed this to an ASSERT since
+ it's not implemented yet.
+
+ * kjs/list.h: Made the List class two-faced, to support the old way and
+ the new way during this transition phase: lists can be made read-only
+ with just a pointer and a legnth, or you can append to them one item
+ at a time.
+
+ * kjs/value.h:
+ (KJS::jsUndefined): Marked this function ALWAYS_INLINE for the benefit
+ of a certain compiler that doesn't know what's best for it.
+
+2008-03-30 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ Dump code that codegen can't handle yet, so it's easier to prioritize missing nodes.
+
+ * kjs/nodes.h:
+ (KJS::Node::emitCode):
+
+2008-03-30 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ Improve dumping of bytecode and fix coding style accordingly.
+
+ Registers are printed as lr1 for locals, tr1 for temp registers. Identifiers print as
+ foobar(@id0) and constants print as "foo"(@k1) or 312.4(@k2) or the like. Constant and
+ identifier tables are dumped for reference.
+
+ * VM/CodeBlock.cpp:
+ (KJS::escapeQuotes):
+ (KJS::valueToSourceString):
+ (KJS::registerName):
+ (KJS::constantName):
+ (KJS::idName):
+ (KJS::printUnaryOp):
+ (KJS::printBinaryOp):
+ (KJS::CodeBlock::dump):
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ (KJS::resolveBase):
+ (KJS::Machine::privateExecute):
+
+2008-03-30 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ Implement StringNode and VoidNode (both pretty trivial).
+
+ * kjs/nodes.cpp:
+ (KJS::StringNode::emitCode):
+ (KJS::VoidNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-30 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ Implement CommaNode.
+
+ * kjs/nodes.cpp:
+ (KJS::CommaNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-30 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Adds support for dot notation and object literals.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitNewObject):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::ObjectLiteralNode::emitCode):
+ (KJS::PropertyListNode::emitCode):
+ (KJS::DotAccessorNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-29 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Mark the register file.
+
+ It's a conservative mark for now, but once registers are typed, we can
+ do an exact mark.
+
+ 1.4% regression regardless of whether we actually do the marking.
+ GCC is is worth every penny.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Most of the changes here are just for
+ the fact that "registers" is a pointer now.
+
+ * kjs/JSGlobalObject.cpp: The global object owns the register file now.
+
+2008-03-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18204: SquirrelFish: continue/break do not correctly handle scope popping
+ <http://bugs.webkit.org/show_bug.cgi?id=18204>
+
+ We now track the scope depth as part of a loop context, and add an
+ extra instruction op_jump_scopes that is used to perform a jump across
+ dynamic scope boundaries.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpScopes):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::ContinueNode::emitCode):
+ (KJS::BreakNode::emitCode):
+
+2008-03-28 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add emitCode support for ConditionalNode.
+
+ * kjs/nodes.cpp:
+ (KJS::ConditionalNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Responding to feedback, added some comments, fixed up a few names, and
+ clarified that "locals" always means all local variables, functions,
+ and parameters.
+
+2008-03-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Added support for "this".
+
+ Supply an implicit "this" value as the first argument to every function.
+ Alias the "this" keyword to that argument.
+
+ 1% regression overall, 2.5% regression on empty function calls. Seems
+ like a reasonable cost for now, since we're doing more work.
+ (Eventually, we might decide to create a version of op_call specialized
+ for a known null "this" value.)
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitCall):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * kjs/CommonIdentifiers.cpp:
+ (KJS::CommonIdentifiers::CommonIdentifiers):
+ * kjs/CommonIdentifiers.h:
+ * kjs/nodes.cpp:
+ (KJS::ThisNode::emitCode):
+ (KJS::FunctionCallResolveNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 18192: Squirrelfish needs support for break and continue
+ <http://bugs.webkit.org/show_bug.cgi?id=18192>
+
+ Added a loop context stack to the code generator to provide the
+ correct jump labels for continue and goto. Added logic to the
+ currently implemented loop constructs to manage entry and exit
+ from the loop contexts. Finally, implemented codegen for break
+ and continue (and a pass through for LabelNode)
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::pushLoopContext):
+ (KJS::CodeGenerator::popLoopContext):
+ (KJS::CodeGenerator::loopContextForIdentifier):
+ (KJS::CodeGenerator::labelForContinue):
+ (KJS::CodeGenerator::labelForBreak):
+ * VM/CodeGenerator.h:
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::emitCode):
+ (KJS::WhileNode::emitCode):
+ (KJS::ForNode::emitCode):
+ (KJS::ContinueNode::emitCode):
+ (KJS::BreakNode::emitCode):
+ (KJS::LabelNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-27 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add emitCode support for UnaryPlusNode, NegateNode, BitwiseNotNode and LogicalNotNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::printUnaryOp):
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitToJSNumber):
+ (KJS::CodeGenerator::emitNegate):
+ (KJS::CodeGenerator::emitBitNot):
+ (KJS::CodeGenerator::emitNot):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::UnaryPlusNode::emitCode):
+ (KJS::NegateNode::emitCode):
+ (KJS::BitwiseNotNode::emitCode):
+ (KJS::LogicalNotNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-27 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej Stachowiak.
+
+ Add support for LogicalAndNode and LogicalOrNode.
+
+ * kjs/nodes.cpp:
+ (KJS::LogicalAndNode::emitCode):
+ (KJS::LogicalOrNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-27 Sam Weinig <sam@webkit.org>
+
+ Clean up code and debug output.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-03-27 Geoffrey Garen <ggaren@apple.com>
+
+ Moved an ASSERT to a more logical place.
+
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-03-27 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Add emitCode support for InstanceOfNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitInstanceOf):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::InstanceOfNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-27 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Bug 18142: squirrelfish needs to support dynamic scoping/with
+ <http://bugs.webkit.org/show_bug.cgi?id=18142>
+
+ Add support for dynamic scoping and add code to handle 'with'
+ statements.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeBlock.h:
+ (KJS::CodeBlock::CodeBlock):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::getRegister):
+ (KJS::CodeGenerator::emitPushScope):
+ (KJS::CodeGenerator::emitPopScope):
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::CodeGenerator):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::WithNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-27 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add emitCode support for NullNode, FalseNode, TrueNode, IfNode, IfElseNode, DoWhileNode and WhileNode
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump): Dump op_jfalse opcode.
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitJumpIfFalse): Identical to emitJumpIfTrue except it emits the op_jfalse opcode.
+ (KJS::CodeGenerator::emitLoad): Add and emitLoad override for booleans.
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute): Adds execution of op_jfalse. It is identical to op_jtrue, except the
+ the condition is reversed.
+ * VM/Opcode.h: Add op_jfalse.
+ * kjs/nodes.cpp:
+ (KJS::NullNode::emitCode): Added.
+ (KJS::FalseNode::emitCode): Added.
+ (KJS::TrueNode::emitCode): Added.
+ (KJS::IfNode::emitCode): Added.
+ (KJS::IfElseNode::emitCode): Added.
+ (KJS::DoWhileNode::emitCode): Added.
+ (KJS::WhileNode::emitCode): Added.
+ * kjs/nodes.h:
+
+2008-03-26 Geoffrey Garen <ggaren@apple.com>
+
+ Nixed an unused List.
+
+ The calm before my stormy war against the List class.
+
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+
+2008-03-26 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Geoffrey Garen.
+
+ Adds support for EqualNode, NotEqualNode, StrictEqualNode, NotStrictEqualNode,
+ LessEqNode, GreaterNode, GreaterEqNode, MultNode, DivNode, ModNode, SubNode,
+ LeftShiftNode, RightShiftNode, UnsignedRightShiftNode, BitAndNode, BitXOrNode,
+ and BitOrNode.
+
+ * VM/CodeBlock.cpp:
+ (KJS::CodeBlock::dump):
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::emitEqual):
+ (KJS::CodeGenerator::emitNotEqual):
+ (KJS::CodeGenerator::emitStrictEqual):
+ (KJS::CodeGenerator::emitNotStrictEqual):
+ (KJS::CodeGenerator::emitLessEq):
+ (KJS::CodeGenerator::emitMult):
+ (KJS::CodeGenerator::emitDiv):
+ (KJS::CodeGenerator::emitMod):
+ (KJS::CodeGenerator::emitSub):
+ (KJS::CodeGenerator::emitLeftShift):
+ (KJS::CodeGenerator::emitRightShift):
+ (KJS::CodeGenerator::emitUnsignedRightShift):
+ (KJS::CodeGenerator::emitBitAnd):
+ (KJS::CodeGenerator::emitBitXOr):
+ (KJS::CodeGenerator::emitBitOr):
+ * VM/CodeGenerator.h:
+ * VM/Machine.cpp:
+ (KJS::jsLessEq):
+ (KJS::Machine::privateExecute):
+ * VM/Opcode.h:
+ * kjs/nodes.cpp:
+ (KJS::MultNode::emitCode):
+ (KJS::DivNode::emitCode):
+ (KJS::ModNode::emitCode):
+ (KJS::SubNode::emitCode):
+ (KJS::LeftShiftNode::emitCode):
+ (KJS::RightShiftNode::emitCode):
+ (KJS::UnsignedRightShiftNode::emitCode):
+ (KJS::GreaterNode::emitCode):
+ (KJS::LessEqNode::emitCode):
+ (KJS::GreaterEqNode::emitCode):
+ (KJS::EqualNode::emitCode):
+ (KJS::NotEqualNode::emitCode):
+ (KJS::StrictEqualNode::emitCode):
+ (KJS::NotStrictEqualNode::emitCode):
+ (KJS::BitAndNode::emitCode):
+ (KJS::BitXOrNode::emitCode):
+ (KJS::BitOrNode::emitCode):
+ * kjs/nodes.h:
+
+2008-03-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Only print debug dumps in debug builds.
+
+ * VM/CodeGenerator.cpp:
+ (KJS::CodeGenerator::generate):
+ * VM/Machine.cpp:
+ (KJS::Machine::privateExecute):
+
+2008-03-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Moved a few files around in the XCode project.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-03-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Made closures work.
+
+ An activation object aliases to the register file until its associated
+ function returns, at which point it copies the registers for locals and
+ parameters into an independent storage buffer.
+
+2008-03-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed recent 25% regression on simple for loop test. GCC seems to be
+ very finicky about the code that gets inlined into
+ Machine::privateExecute.
+
+ Everything in this patch is simply the result of experiment.
+
+ The resolve and resolve_base opcodes do not seem to have gotten slower
+ from this change.
+
+ * VM/Machine.cpp:
+ (KJS::resolve):
+ (KJS::resolveBase):
+ (KJS::Machine::privateExecute):
+ * kjs/nodes.h:
+
+2008-03-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Bug 18059: squirrelfish needs to compile on platforms without computed goto
+ <http://bugs.webkit.org/show_bug.cgi?id=18059>
+
+ "Standard" macro style support for conditionalising the use of computed goto.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * VM/Machine.cpp:
+ (KJS::Machine::isOpcode):
+ (KJS::Machine::privateExecute):
+ * VM/Machine.h:
+ (KJS::Machine::getOpcode):
+ (KJS::Machine::getOpcodeID):
+ * VM/Opcode.h:
+ * wtf/Platform.h:
+
+2008-03-24 Geoffrey Garen <ggaren@apple.com>
+
+ Moved my notes from nodes.h to the wiki.
+
+ * kjs/nodes.h:
+
+2008-03-24 Geoffrey Garen <ggaren@apple.com>
+
+ SquirrelFish lives.
+
+ Initial check-in of the code I've been carrying around. Lots of stuff
+ doesn't work. Plus a bunch of empty files.
+
+=== Start merge of squirrelfish ===
+
+2008-05-21 Darin Adler <darin@apple.com>
+
+ - try to fix the Windows build
+
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::stopProfiling): Use ptrdiff_t instead of the less-common but incredibly
+ similar ssize_t type.
+ * wtf/AVLTree.h:
+ (KJS::AVLTree::search): Added a typename for a dependent name that's a type.
+
+2008-05-21 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - fix <rdar://problem/5952721> bug in JavaScript arguments object property lookup
+
+ Test: fast/js/arguments-bad-index.html
+
+ * kjs/function.cpp:
+ (KJS::IndexToNameMap::IndexToNameMap): Use unsigned instead of int.
+ (KJS::IndexToNameMap::isMapped): Use unsigned instead of int, and also use the
+ strict version of the numeric conversion function, since we don't want to allow
+ trailing junk.
+ (KJS::IndexToNameMap::unMap): Ditto.
+ (KJS::IndexToNameMap::operator[]): Ditto.
+ * kjs/function.h: Changed IndexToNameMap::size type from int to unsigned.
+
+2008-05-21 Timothy Hatcher <timothy@apple.com>
+
+ Change the Profiler to allow multiple profiles to be running at
+ the same time. This can happen when you have nested console.profile()
+ calls. This required two changes. First, the Profiler needed to keep a
+ Vector of current profiles, instead of one. Second, a Profile needs
+ to keep track of the global ExecState it started in and the page group
+ identifier it is tracking.
+
+ The stopProfiling call now takes the same arguments as startProfiling.
+ This makes sure the correct profile is stopped. Passing a null UString
+ as the title will stop the last profile for the matching ExecState.
+
+ <rdar://problem/5951559> Multiple pages profiling can interfere with each other
+
+ Reviewed by Kevin McCullough.
+
+ * JavaScriptCore.exp: Added new exports. Removed old symbols.
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile): New constructor arguments for the
+ originatingGlobalExec and pageGroupIdentifier.
+ (KJS::Profile::stopProfiling): Set the m_originatingGlobalExec to null.
+ * profiler/Profile.h:
+ (KJS::Profile::create): Additional arguments.
+ (KJS::Profile::originatingGlobalExec): Return m_originatingGlobalExec.
+ (KJS::Profile::pageGroupIdentifier): Return m_pageGroupIdentifier.
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::findProfile): Added. Finds a Profile that matches
+ the ExecState and title.
+ (KJS::Profiler::startProfiling): Return early if there is already
+ a Profile with the ExecState and title. If not, create a new profile
+ and append it to m_currentProfiles.
+ (KJS::Profiler::stopProfiling): Loops through m_currentProfiles
+ and find the one matching the ExecState and title. If one is found
+ call stopProfiling and return the Profile after removing it
+ from m_currentProfiles.
+ (KJS::dispatchFunctionToProfiles): Helper inline function to loop through
+ m_currentProfiles and call a Profile function.
+ (KJS::Profiler::willExecute): Call dispatchFunctionToProfiles.
+ (KJS::Profiler::didExecute): Ditto.
+ * profiler/Profiler.h:
+
+2008-05-21 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5908520> REGRESSION (3.1.1-r33033): Crash in WebKit when opening or
+ refreshing page on people.com
+
+ The problem was that STL algorithms do not work with non-conformant comparators, and the
+ site used sort(function() { return 0.5 - Math.random(); } to randomly shuffle an array.
+
+ https://bugs.webkit.org/show_bug.cgi?id=18687
+ REGRESSION(r32220): ecma/Array/15.4.4.5-3.js test now fails in GMT(BST)
+
+ Besides relying on sort stability, this test was just broken, and kept failing with the
+ new stable sort.
+
+ Tests: fast/js/sort-randomly.html
+ fast/js/sort-stability.html
+ fast/js/comparefn-sort-stability.html
+
+ * kjs/avl_tree.h: Added an AVL tree implementation.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * wtf/AVLTree.h: Added.
+ Added an AVL tree implementation.
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::increaseVectorLength):
+ (KJS::ArrayInstance::sort):
+ (KJS::AVLTreeAbstractorForArrayCompare::get_less):
+ (KJS::AVLTreeAbstractorForArrayCompare::set_less):
+ (KJS::AVLTreeAbstractorForArrayCompare::get_greater):
+ (KJS::AVLTreeAbstractorForArrayCompare::set_greater):
+ (KJS::AVLTreeAbstractorForArrayCompare::get_balance_factor):
+ (KJS::AVLTreeAbstractorForArrayCompare::set_balance_factor):
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key):
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_key_node):
+ (KJS::AVLTreeAbstractorForArrayCompare::compare_node_node):
+ (KJS::AVLTreeAbstractorForArrayCompare::null):
+ (KJS::ArrayInstance::compactForSorting):
+
+ * kjs/array_instance.h: increaseVectorLength() now returns a bool to indicate whether it was
+ successful.
+
+ * wtf/Vector.h:
+ (WTF::Vector::Vector):
+ (WTF::::operator=):
+ (WTF::::fill):
+ Make these methods fail instead of crash when allocation fails, matching resize() and
+ reserveCapacity(), which already had this behavior. Callers need to check for null buffer
+ after making any Vector call that can try to allocate.
+
+ * tests/mozilla/ecma/Array/15.4.4.5-3.js: Fixed the test to use a consistent sort function,
+ as suggested in comments to a Mozilla bug filed about it (I'll keep tracking the bug to see
+ what the final resolution is).
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5950867> JSProfiler: Allow the profiler to "Focus" a
+ profile node.
+ - Implements focus by adding the idea of a profileNode being visible and
+ adding the ability to reset all of the visible flags.
+
+ * profiler/Profile.h:
+ (KJS::Profile::focus):
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode): Initialize the visible flag.
+ (KJS::ProfileNode::setTreeVisible): Set the visibility of this node and
+ all of its descendents.
+ (KJS::ProfileNode::focus): Determine if this node should be visible when
+ focusing, if the functionName matches this node's function name or if any
+ of this node's children are visible.
+ (KJS::ProfileNode::restoreAll): Restore all nodes' visible flag.
+ (KJS::ProfileNode::debugPrintData):
+ * profiler/ProfileNode.h:
+ (KJS::ProfileNode::visible):
+ (KJS::ProfileNode::setVisible):
+
+2008-05-20 Timothy Hatcher <timothy@apple.com>
+
+ Fixes a couple performance issues with the profiler. Also fixes
+ a regression where some nodes wouldn't be added to the tree.
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::addChild): Compare callIdentifier instead
+ of functionName.
+ * profiler/ProfileNode.h:
+ (CallIdentifier.operator==): Compare the CallIdentifiers in
+ an order that fails sooner for non-matches.
+ (CallIdentifier.callIdentifier): Return the CallIdentifier by
+ reference to prevent making a new copy each time.
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5950796> JSProfiler: dump functions are in the code
+ Removed dump and logging functions from the Release version of the code
+ and renamed them to be obviously for debugging only.
+
+ * JavaScriptCore.exp:
+ * profiler/Profile.cpp:
+ (KJS::Profile::debugPrintData):
+ (KJS::Profile::debugPrintDataSampleStyle):
+ * profiler/Profile.h:
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::debugPrintData):
+ (KJS::ProfileNode::debugPrintDataSampleStyle):
+ * profiler/ProfileNode.h:
+ * profiler/Profiler.cpp:
+ * profiler/Profiler.h:
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ <rdar://problem/5950538> JSProfiler: Keep track of non-JS execution time
+ We now have an extra node that represents the excess non-JS time.
+ - Also changed "SCRIPT" and "anonymous function" to be more consistent
+ with the debugger.
+
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::stopProfiling): If this ProfileNode is the head node
+ create a new child that has the excess execution time.
+ (KJS::ProfileNode::calculatePercentages): Moved calculation of the
+ percentages into a function since it's called from multiple places.
+ * profiler/ProfileNode.h: Add the newly needed functions used above.
+ (KJS::ProfileNode::setTotalTime):
+ (KJS::ProfileNode::setSelfTime):
+ (KJS::ProfileNode::setNumberOfCalls):
+ * profiler/Profiler.cpp: renamed "SCRIPT" and "anonymous function" to be
+ consistent with the debugger and use constants that can be localized
+ more easily.
+ (KJS::getCallIdentifiers):
+ (KJS::getCallIdentifierFromFunctionImp):
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ Removed only profiler-internal use of currentProfile since that concept
+ is changing.
+
+ * profiler/Profile.h: Now stopProfiling takes a time and bool as
+ arguments. The time is used to calculate %s from and the bool tells
+ if this node is the head node and should be the one calculating the time.
+ (KJS::Profile::stopProfiling):
+ * profiler/ProfileNode.cpp: Ditto.
+ (KJS::ProfileNode::stopProfiling):
+ * profiler/ProfileNode.h: Ditto.
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Accidentally turned on the profiler.
+
+ * kjs/config.h:
+
+
+2008-05-20 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ Split function name into 3 parts so that the Web Inspector can link it to
+ the resource location from whence it came.
+
+ * kjs/ustring.cpp: Implemented operator> for UStrings
+ (KJS::operator>):
+ * kjs/ustring.h:
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile): Initialize all 3 values.
+ (KJS::Profile::willExecute): Use CallIdentifier struct.
+ (KJS::Profile::didExecute): Ditto.
+ * profiler/Profile.h: Ditto and remove unused function.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode): Use CallIdentifier struct.
+ (KJS::ProfileNode::willExecute): Ditto and fix an issue where we
+ restarted the m_startTime even though it was already started.
+ (KJS::ProfileNode::didExecute): Ditto.
+ (KJS::ProfileNode::findChild): Ditto.
+ (KJS::functionNameDescendingComparator): Ditto and use new comparator.
+ (KJS::functionNameAscendingComparator): Ditto.
+ (KJS::ProfileNode::printDataInspectorStyle): Use CallIdentifier struct.
+ (KJS::ProfileNode::printDataSampleStyle): Ditto.
+ * profiler/ProfileNode.h:
+ (KJS::CallIdentifier::CallIdentifier): Describe the CallIdentifier struct
+ (KJS::CallIdentifier::operator== ):
+ (KJS::ProfileNode::create): Use the CallIdentifier struct.
+ (KJS::ProfileNode::callIdentifier):
+ (KJS::ProfileNode::functionName): Now only return the function name, not
+ the url and line number too.
+ (KJS::ProfileNode::url):
+ (KJS::ProfileNode::lineNumber):
+ * profiler/Profiler.cpp: Use the CallIdentifier struct.
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+ (KJS::getCallIdentifiers):
+ (KJS::getCallIdentifierFromFunctionImp):
+
+2008-05-20 Timothy Hatcher <timothy@apple.com>
+
+ Rename sortFileName{Ascending,Descending} to
+ sortFunctionName{Ascending,Descending}.
+
+ Reviewed by Kevin McCullough.
+
+ * JavaScriptCore.exp:
+ * kjs/config.h:
+ * profiler/Profile.h:
+ * profiler/ProfileNode.cpp:
+ (KJS::functionNameDescendingComparator):
+ (KJS::ProfileNode::sortFunctionNameDescending):
+ (KJS::functionNameAscendingComparator):
+ (KJS::ProfileNode::sortFunctionNameAscending):
+ * profiler/ProfileNode.h:
+
+2008-05-19 Timothy Hatcher <timothy@apple.com>
+
+ Make the profiler use higher than millisecond resolution time-stamps.
+
+ Reviewed by Kevin McCullough.
+
+ * kjs/DateMath.cpp:
+ (KJS::getCurrentUTCTime): Call getCurrentUTCTimeWithMicroseconds and
+ floor the result.
+ (KJS::getCurrentUTCTimeWithMicroseconds): Copied from the previous
+ implementation of getCurrentUTCTime without the floor call.
+ * kjs/DateMath.h: Addded getCurrentUTCTimeWithMicroseconds.
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode): Use getCurrentUTCTimeWithMicroseconds.
+
+2008-05-19 Timothy Hatcher <timothy@apple.com>
+
+ Fixes a bug in the profiler where call and apply would show up
+ and double the time spent in a function. We don't want to show call
+ and apply at all in the profiles. This change excludes them.
+
+ Reviewed by Kevin McCullough.
+
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::stopProfiling): Remove a second for loop and
+ calculate self time in the existing loop.
+ * profiler/Profiler.cpp:
+ (KJS::shouldExcludeFunction): Helper inline function that returns
+ true in the current function in an InternalFunctionImp and it is
+ has the functionName call or apply.
+ (KJS::Profiler::willExecute): Call shouldExcludeFunction and return
+ early if if returns true.
+ (KJS::Profiler::didExecute): Ditto.
+
+2008-05-19 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Implement sorting by function name.
+
+ * JavaScriptCore.exp:
+ * profiler/Profile.h:
+ (KJS::Profile::sortFileNameDescending):
+ (KJS::Profile::sortFileNameAscending):
+ * profiler/ProfileNode.cpp:
+ (KJS::fileNameDescendingComparator):
+ (KJS::ProfileNode::sortFileNameDescending):
+ (KJS::fileNameAscendingComparator):
+ (KJS::ProfileNode::sortFileNameAscending):
+ * profiler/ProfileNode.h:
+
+2008-05-19 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Pass the exec state to profiler when calling startProfiling so that if
+ profiling is started within an execution context that location is
+ recorded correctly.
+
+ * JavaScriptCore.exp:
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::printDataInspectorStyle): Dump more info for debugging
+ purposes.
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::startProfiling):
+ * profiler/Profiler.h:
+
+2008-05-19 Kevin McCullough <kmccullough@apple.com>
+
+ Rubberstamped by Geoff.
+
+ Turn off the profiler because it is a performance regression.
+
+ * kjs/config.h:
+
+2008-05-19 Alp Toker <alp@nuanti.com>
+
+ Reviewed by Anders and Beth.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16495
+ [GTK] Accessibility support with ATK/AT-SPI
+
+ Initial ATK/AT-SPI accessibility support for the GTK+ port.
+
+ * wtf/Platform.h:
+
+2008-05-19 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ -In an effort to make the profiler as efficient as possible instead of
+ prepending to a vector we keep the vector in reverse order and operate
+ over it backwards.
+
+ * profiler/Profile.cpp:
+ (KJS::Profile::willExecute):
+ (KJS::Profile::didExecute):
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::didExecute):
+ (KJS::ProfileNode::endAndRecordCall):
+ * profiler/ProfileNode.h:
+ * profiler/Profiler.cpp:
+ (KJS::getStackNames):
+
+2008-05-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ Implement sorting for the profiler.
+ I chose to sort the profileNodes in place since there is no reason they
+ need to retain their original order.
+
+ * JavaScriptCore.exp: Export the symbols.
+ * profiler/Profile.h: Add the different ways a profile can be sorted.
+ (KJS::Profile::sortTotalTimeDescending):
+ (KJS::Profile::sortTotalTimeAscending):
+ (KJS::Profile::sortSelfTimeDescending):
+ (KJS::Profile::sortSelfTimeAscending):
+ (KJS::Profile::sortCallsDescending):
+ (KJS::Profile::sortCallsAscending):
+ * profiler/ProfileNode.cpp: Implement those ways.
+ (KJS::totalTimeDescendingComparator):
+ (KJS::ProfileNode::sortTotalTimeDescending):
+ (KJS::totalTimeAscendingComparator):
+ (KJS::ProfileNode::sortTotalTimeAscending):
+ (KJS::selfTimeDescendingComparator):
+ (KJS::ProfileNode::sortSelfTimeDescending):
+ (KJS::selfTimeAscendingComparator):
+ (KJS::ProfileNode::sortSelfTimeAscending):
+ (KJS::callsDescendingComparator):
+ (KJS::ProfileNode::sortCallsDescending):
+ (KJS::callsAscendingComparator):
+ (KJS::ProfileNode::sortCallsAscending):
+ * profiler/ProfileNode.h: No longer use a Deque since it cannot be
+ sorted by std::sort and there was no reason not to use a Vector. I
+ previously had though I would do prepending but am not.
+ (KJS::ProfileNode::selfTime):
+ (KJS::ProfileNode::totalPercent):
+ (KJS::ProfileNode::selfPercent):
+ (KJS::ProfileNode::children):
+ * profiler/Profiler.cpp: Removed these functions as they can be called
+ directoy on the Profile object after getting the Vector of them.
+ (KJS::getStackNames):
+ * profiler/Profiler.h:
+
+2008-05-15 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ Since WebKitGtk is fully using autotools now, clean-up the .pro/.pri files
+ from gtk-port.
+
+ * JavaScriptCore.pro:
+ * kjs/testkjs.pro:
+
+2008-05-15 Kevin McCullough <kmccullough@apple.com>
+
+ - Build fix.
+
+ * JavaScriptCore.exp:
+
+2008-05-15 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Cache some values to save on computing them repetitively. This will be
+ a big savings when we sort since we won't have to walk the tree for
+ every comparison!
+ - We cache these values when we end profiling because otherwise we won't
+ know which profile to get the totalTime for the whole profile from without
+ retaining a reference to the head profile or looking up the profile from
+ the list of all profiles.
+ - Also it's safe to assume we won't be asked for these values while we
+ are still profiling since the WebInspector only get's profileNodes from
+ profiles that are in the allProfiles() list and a profile is only added
+ to that list after it has finished and these values will no longer
+ change.
+
+ * JavaScriptCore.exp:
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::ProfileNode):
+ (KJS::ProfileNode::stopProfiling):
+ (KJS::ProfileNode::printDataInspectorStyle):
+ (KJS::ProfileNode::printDataSampleStyle):
+ (KJS::ProfileNode::endAndRecordCall):
+ * profiler/ProfileNode.h:
+ (KJS::ProfileNode::totalTime):
+ (KJS::ProfileNode::selfTime):
+ (KJS::ProfileNode::totalPercent):
+ (KJS::ProfileNode::selfPercent):
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::stopProfiling):
+
+2008-05-15 Simon Hausmann <shausman@trolltech.com>
+
+ Reviewed by Holger.
+
+ Fix compilation when compiling with MSVC and wchar_t support.
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::foldCase):
+ (WTF::Unicode::umemcasecmp):
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Turn on the profiler.
+
+ * kjs/config.h:
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Expose the new profiler functions to the WebInspector.
+
+ * JavaScriptCore.exp:
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Giving credit where credit is due.
+
+ * ChangeLog:
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff and Sam.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ Add the ability to get percentages of total and self time for displaying
+ in the WebInspector.
+
+ * profiler/Profile.h:
+ (KJS::Profile::totalProfileTime):
+ * profiler/ProfileNode.cpp:
+ (KJS::ProfileNode::totalPercent):
+ (KJS::ProfileNode::selfPercent):
+ * profiler/ProfileNode.h:
+ * profiler/Profiler.h:
+ (KJS::Profiler::currentProfile):
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Rename FunctionCallProfile to ProfileNode.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * profiler/FunctionCallProfile.cpp: Removed.
+ * profiler/FunctionCallProfile.h: Removed.
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile):
+ (KJS::Profile::willExecute):
+ * profiler/Profile.h:
+ (KJS::Profile::callTree):
+ * profiler/ProfileNode.cpp: Copied from profiler/FunctionCallProfile.cpp.
+ (KJS::ProfileNode::ProfileNode):
+ (KJS::ProfileNode::willExecute):
+ (KJS::ProfileNode::didExecute):
+ (KJS::ProfileNode::addChild):
+ (KJS::ProfileNode::findChild):
+ (KJS::ProfileNode::stopProfiling):
+ (KJS::ProfileNode::selfTime):
+ (KJS::ProfileNode::printDataInspectorStyle):
+ (KJS::ProfileNode::printDataSampleStyle):
+ (KJS::ProfileNode::endAndRecordCall):
+ * profiler/ProfileNode.h: Copied from profiler/FunctionCallProfile.h.
+ (KJS::ProfileNode::create):
+ (KJS::ProfileNode::children):
+ * profiler/Profiler.cpp:
+
+2008-05-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by John.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Have each FunctionCallProfile be able to return it's total and self time.
+
+ * JavaScriptCore.exp:
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::selfTime):
+ * profiler/FunctionCallProfile.h:
+ (KJS::FunctionCallProfile::totalTime):
+
+2008-05-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5934376> REGRESSION: A script fails because of a straw BOM character in it.
+
+ <https://bugs.webkit.org/show_bug.cgi?id=4931>
+ Unicode format characters (Cf) should be removed from JavaScript source
+
+ Of all Cf characters, we are only removing BOM, because this is what Firefox trunk has
+ settled upon, after extensive discussion and investigation.
+
+ Based on Darin's work on this bug.
+
+ Test: fast/js/removing-Cf-characters.html
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::setCode): Tweak formatting. Use a call to shift(4) to read in the
+ first characters, instead of having special case code here.
+ (KJS::Lexer::shift): Add a loop when reading a character to skip BOM characters.
+
+2008-05-13 Matt Lilek <webkit@mattlilek.com>
+
+ Not reviewed, build fix.
+
+ * kjs/date_object.cpp:
+ (KJS::DateObjectFuncImp::callAsFunction):
+
+2008-05-13 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5933644> Implement Date.now
+
+ Implement Date.now which returns the number of milliseconds since the epoch.
+
+ * kjs/CommonIdentifiers.h:
+ * kjs/date_object.cpp:
+ (KJS::DateObjectFuncImp::):
+ (KJS::DateObjectImp::DateObjectImp):
+ (KJS::DateObjectFuncImp::callAsFunction):
+
+2008-05-13 Kevin McCullough <kmccullough@apple.com>
+
+ Giving credit where credit is due.
+
+ * ChangeLog:
+
+2008-05-13 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam and Geoff.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ Use PassRefPtrs instead of RefPtrs when appropriate.
+
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::addChild):
+ * profiler/FunctionCallProfile.h:
+ * profiler/Profile.h:
+ (KJS::Profile::callTree):
+
+2008-05-13 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Made some functions static (as per Adam) and changed from using raw
+ pointers to RefPtr for making these JavaScript Objects.
+
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::addChild):
+ (KJS::FunctionCallProfile::findChild):
+ * profiler/FunctionCallProfile.h:
+ (KJS::FunctionCallProfile::create):
+ * profiler/Profile.cpp:
+ (KJS::Profile::Profile):
+ (KJS::Profile::willExecute):
+ (KJS::Profile::didExecute):
+ (KJS::functionNameCountPairComparator):
+ * profiler/Profile.h:
+ (KJS::Profile::create):
+ (KJS::Profile::title):
+ (KJS::Profile::callTree):
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::startProfiling):
+ * profiler/Profiler.h:
+ (KJS::Profiler::allProfiles):
+ (KJS::Profiler::clearProfiles):
+
+2008-05-13 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ <rdar://problem/4949018> JavaScriptCore API claims to work with UTF8 strings, but only works
+ with ASCII strings
+
+ * kjs/ustring.h:
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::createFromUTF8):
+ Added. Implementation adapted from JSStringCreateWithUTF8CString().
+
+ * API/JSStringRef.cpp:
+ (JSStringCreateWithUTF8CString):
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::OpaqueJSClass):
+ Use UString::Rep::createFromUTF8().
+
+2008-05-12 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ <rdar://problem/4859666> WebKit needs availability macros in order to deprecate APIs
+
+ Create WebKit availability macros that key off the Mac OS X version being targeted to
+ determine the WebKit version being targeted. Applications can define
+ WEBKIT_VERSION_MIN_REQUIRED before including WebKit headers in order to target a specific
+ version of WebKit.
+
+ The availability header is being added to JavaScriptCore rather than WebKit as JavaScriptCore
+ is the lowest-level portion of the public WebKit API.
+
+ * API/WebKitAvailability.h: Added.
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-05-12 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Maciej.
+
+ https://bugs.webkit.org/show_bug.cgi?id=18828
+ Reproducible crash with PAC file
+
+ Naively moving JavaScriptCore into thread-specific data was inappropriate in the face of
+ exiting JavaScriptCore API clients, which expect a different therading model. Temporarily
+ disabling ThreadSpecific implementation until this can be sorted out.
+
+ * wtf/ThreadSpecific.h:
+ (WTF::::ThreadSpecific):
+ (WTF::::~ThreadSpecific):
+ (WTF::::get):
+ (WTF::::set):
+
+2008-05-12 Alexey Proskuryakov <ap@webkit.org>
+
+ Roll out recent threading changes (r32807, r32810, r32819, r32822) to simplify
+ SquirrelFish merging.
+
+ * API/JSBase.cpp:
+ (JSGarbageCollect):
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::staticFunctionGetter):
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeConstructor):
+ (JSObjectMakeFunction):
+ * API/JSValueRef.cpp:
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ * JavaScriptCore.exp:
+ * kjs/ExecState.h:
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreadingOnce):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject):
+ (KJS::JSGlobalObject::init):
+ (KJS::JSGlobalObject::put):
+ (KJS::JSGlobalObject::reset):
+ (KJS::JSGlobalObject::tearOffActivation):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::head):
+ (KJS::JSGlobalObject::perThreadData):
+ * kjs/JSLock.cpp:
+ (KJS::JSLock::registerThread):
+ * kjs/JSLock.h:
+ (KJS::JSLock::JSLock):
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::ArrayInstance):
+ (KJS::ArrayInstance::lengthGetter):
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ (KJS::ArrayObjectImp::ArrayObjectImp):
+ (KJS::ArrayObjectImp::construct):
+ * kjs/bool_object.cpp:
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::BooleanObjectImp::BooleanObjectImp):
+ (KJS::BooleanObjectImp::construct):
+ * kjs/collector.cpp:
+ (KJS::allocateBlock):
+ (KJS::Collector::recordExtraCost):
+ (KJS::Collector::heapAllocate):
+ (KJS::Collector::allocate):
+ (KJS::Collector::allocateNumber):
+ (KJS::Collector::registerAsMainThread):
+ (KJS::onMainThread):
+ (KJS::PlatformThread::PlatformThread):
+ (KJS::getCurrentPlatformThread):
+ (KJS::Collector::Thread::Thread):
+ (KJS::destroyRegisteredThread):
+ (KJS::initializeRegisteredThreadKey):
+ (KJS::Collector::registerThread):
+ (KJS::Collector::markStackObjectsConservatively):
+ (KJS::Collector::markCurrentThreadConservativelyInternal):
+ (KJS::Collector::markCurrentThreadConservatively):
+ (KJS::suspendThread):
+ (KJS::resumeThread):
+ (KJS::getPlatformThreadRegisters):
+ (KJS::otherThreadStackPointer):
+ (KJS::Collector::markOtherThreadConservatively):
+ (KJS::protectedValues):
+ (KJS::Collector::protect):
+ (KJS::Collector::unprotect):
+ (KJS::Collector::collectOnMainThreadOnly):
+ (KJS::Collector::markProtectedObjects):
+ (KJS::Collector::markMainThreadOnlyObjects):
+ (KJS::Collector::sweep):
+ (KJS::Collector::collect):
+ (KJS::Collector::size):
+ (KJS::Collector::globalObjectCount):
+ (KJS::Collector::protectedGlobalObjectCount):
+ (KJS::Collector::protectedObjectCount):
+ (KJS::Collector::protectedObjectTypeCounts):
+ (KJS::Collector::isBusy):
+ (KJS::Collector::reportOutOfMemoryToAllExecStates):
+ * kjs/collector.h:
+ (KJS::Collector::cellBlock):
+ (KJS::Collector::cellOffset):
+ (KJS::Collector::isCellMarked):
+ (KJS::Collector::markCell):
+ (KJS::Collector::reportExtraMemoryCost):
+ * kjs/date_object.cpp:
+ (KJS::formatLocaleDate):
+ (KJS::DatePrototype::DatePrototype):
+ (KJS::DateObjectImp::DateObjectImp):
+ (KJS::DateObjectImp::construct):
+ (KJS::DateObjectImp::callAsFunction):
+ (KJS::DateObjectFuncImp::DateObjectFuncImp):
+ (KJS::DateObjectFuncImp::callAsFunction):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::errorProtoFuncToString):
+ (KJS::ErrorObjectImp::ErrorObjectImp):
+ (KJS::ErrorObjectImp::construct):
+ (KJS::NativeErrorPrototype::NativeErrorPrototype):
+ (KJS::NativeErrorImp::NativeErrorImp):
+ (KJS::NativeErrorImp::construct):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::lengthGetter):
+ (KJS::FunctionImp::construct):
+ (KJS::Arguments::Arguments):
+ (KJS::ActivationImp::createArgumentsObject):
+ (KJS::encode):
+ (KJS::decode):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ (KJS::functionProtoFuncToString):
+ (KJS::FunctionObjectImp::FunctionObjectImp):
+ (KJS::FunctionObjectImp::construct):
+ * kjs/internal.cpp:
+ (KJS::StringImp::toObject):
+ * kjs/internal.h:
+ (KJS::StringImp::StringImp):
+ (KJS::NumberImp::operator new):
+ * kjs/list.cpp:
+ (KJS::List::markSet):
+ (KJS::List::markProtectedListsSlowCase):
+ (KJS::List::expandAndAppend):
+ * kjs/list.h:
+ (KJS::List::List):
+ (KJS::List::~List):
+ (KJS::List::markProtectedLists):
+ * kjs/lookup.h:
+ (KJS::staticFunctionGetter):
+ (KJS::cacheGlobalObject):
+ * kjs/math_object.cpp:
+ (KJS::MathObjectImp::getValueProperty):
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/nodes.cpp:
+ (KJS::ParserRefCounted::ParserRefCounted):
+ (KJS::ParserRefCounted::ref):
+ (KJS::ParserRefCounted::deref):
+ (KJS::ParserRefCounted::refcount):
+ (KJS::ParserRefCounted::deleteNewObjects):
+ (KJS::Node::handleException):
+ (KJS::NumberNode::evaluate):
+ (KJS::StringNode::evaluate):
+ (KJS::ArrayNode::evaluate):
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostDecLocalVarNode::inlineEvaluateToNumber):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::typeStringForValue):
+ (KJS::LocalVarTypeOfNode::evaluate):
+ (KJS::TypeOfResolveNode::evaluate):
+ (KJS::TypeOfValueNode::evaluate):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::PreIncConstNode::evaluate):
+ (KJS::PreDecConstNode::evaluate):
+ (KJS::PostIncConstNode::evaluate):
+ (KJS::PostDecConstNode::evaluate):
+ (KJS::PreIncBracketNode::evaluate):
+ (KJS::PreDecBracketNode::evaluate):
+ (KJS::PreIncDotNode::evaluate):
+ (KJS::PreDecDotNode::evaluate):
+ (KJS::NegateNode::evaluate):
+ (KJS::BitwiseNotNode::evaluate):
+ (KJS::MultNode::evaluate):
+ (KJS::DivNode::evaluate):
+ (KJS::ModNode::evaluate):
+ (KJS::addSlowCase):
+ (KJS::add):
+ (KJS::AddNumbersNode::evaluate):
+ (KJS::AddStringsNode::evaluate):
+ (KJS::AddStringLeftNode::evaluate):
+ (KJS::AddStringRightNode::evaluate):
+ (KJS::SubNode::evaluate):
+ (KJS::LeftShiftNode::evaluate):
+ (KJS::RightShiftNode::evaluate):
+ (KJS::UnsignedRightShiftNode::evaluate):
+ (KJS::BitXOrNode::evaluate):
+ (KJS::BitOrNode::evaluate):
+ (KJS::valueForReadModifyAssignment):
+ (KJS::ForInNode::execute):
+ (KJS::TryNode::execute):
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::evaluate):
+ * kjs/nodes.h:
+ * kjs/number_object.cpp:
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberObjectImp::NumberObjectImp):
+ (KJS::NumberObjectImp::getValueProperty):
+ (KJS::NumberObjectImp::construct):
+ (KJS::NumberObjectImp::callAsFunction):
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+ (KJS::JSObject::get):
+ (KJS::JSObject::put):
+ (KJS::JSObject::defineGetter):
+ (KJS::JSObject::defineSetter):
+ (KJS::JSObject::putDirect):
+ (KJS::Error::create):
+ * kjs/object.h:
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ (KJS::ObjectObjectImp::ObjectObjectImp):
+ (KJS::ObjectObjectImp::construct):
+ * kjs/property_map.h:
+ (KJS::SavedProperty::SavedProperty):
+ (KJS::SavedProperty::init):
+ (KJS::SavedProperty::~SavedProperty):
+ (KJS::SavedProperty::name):
+ (KJS::SavedProperty::value):
+ (KJS::SavedProperty::attributes):
+ * kjs/protect.h:
+ (KJS::gcProtect):
+ (KJS::gcUnprotect):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::regExpProtoFuncToString):
+ (KJS::RegExpImp::getValueProperty):
+ (KJS::RegExpObjectImp::RegExpObjectImp):
+ (KJS::RegExpObjectImp::arrayOfMatches):
+ (KJS::RegExpObjectImp::getBackref):
+ (KJS::RegExpObjectImp::getLastParen):
+ (KJS::RegExpObjectImp::getLeftContext):
+ (KJS::RegExpObjectImp::getRightContext):
+ (KJS::RegExpObjectImp::getValueProperty):
+ (KJS::RegExpObjectImp::createRegExpImp):
+ * kjs/regexp_object.h:
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::StringInstance):
+ (KJS::StringInstance::lengthGetter):
+ (KJS::StringInstance::indexGetter):
+ (KJS::stringInstanceNumericPropertyGetter):
+ (KJS::StringPrototype::StringPrototype):
+ (KJS::replace):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::StringObjectImp::StringObjectImp):
+ (KJS::StringObjectImp::construct):
+ (KJS::StringObjectImp::callAsFunction):
+ (KJS::StringObjectFuncImp::StringObjectFuncImp):
+ (KJS::StringObjectFuncImp::callAsFunction):
+ * kjs/string_object.h:
+ (KJS::StringInstanceThatMasqueradesAsUndefined::StringInstanceThatMasqueradesAsUndefined):
+ * kjs/testkjs.cpp:
+ (GlobalObject::GlobalObject):
+ (functionGC):
+ (functionRun):
+ (functionReadline):
+ (kjsmain):
+ * kjs/ustring.h:
+ * kjs/value.cpp:
+ (KJS::JSCell::operator new):
+ (KJS::jsString):
+ (KJS::jsOwnedString):
+ (KJS::jsNumberCell):
+ * kjs/value.h:
+ (KJS::jsNaN):
+ (KJS::jsNumber):
+ (KJS::jsNumberFromAnd):
+ (KJS::JSCell::marked):
+ (KJS::JSCell::mark):
+ (KJS::JSValue::toJSNumber):
+ * wtf/ThreadSpecific.h:
+ (WTF::T):
+
+2008-05-10 Julien Chaffraix <jchaffraix@webkit.org>
+
+ Qt & wx build fix.
+
+ * JavaScriptCore.pri: Add profiler/Profile.cpp.
+ * JavaScriptCoreSources.bkl: Ditto.
+
+2008-05-10 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Reviewed by Maciej.
+
+ Gtk+ build fix
+
+ * GNUmakefile.am: Add Profile.cpp in _sources
+
+2008-05-09 Brady Eidson <beidson@apple.com>
+
+ Build Fix. Kevin is an idiot.
+ ("My name is Kevin McCullough and I approve this message.")
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-05-09 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Tim.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ -Add Profile class so that all profiles can be stored and retrieved by
+ the WebInspector when that time comes.
+
+ * JavaScriptCore.exp: Export the new function signatures.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Add the new files to the
+ project
+ * profiler/Profile.cpp: Added. This class represents a single run of the
+ profiler.
+ (KJS::Profile::Profile):
+ (KJS::Profile::willExecute):
+ (KJS::Profile::didExecute):
+ (KJS::Profile::printDataInspectorStyle):
+ (KJS::functionNameCountPairComparator):
+ (KJS::Profile::printDataSampleStyle):
+ * profiler/Profile.h: Added. Ditto
+ (KJS::Profile::stopProfiling):
+ * profiler/Profiler.cpp: Now the profiler keeps track of many profiles
+ but only runs one at a time.
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::stopProfiling):
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+ (KJS::Profiler::printDataInspectorStyle):
+ (KJS::Profiler::printDataSampleStyle):
+ * profiler/Profiler.h: Ditto.
+ (KJS::Profiler::~Profiler):
+ (KJS::Profiler::allProfiles):
+ (KJS::Profiler::clearProfiles):
+
+2008-05-08 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Mark.
+
+ Enable NPAPI plug-ins on 64-bit.
+
+ * wtf/Platform.h:
+
+2008-05-07 Julien Chaffraix <jchaffraix@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ wx & Gtk build fix.
+
+ Add SIZE_MAX definition for the wx port.
+
+ * os-win32/stdint.h:
+
+2008-05-07 Ariya Hidayat <ariya.hidayat@trolltech.com>
+
+ Reviewed by Simon.
+
+ Support for isMainThread in the Qt port.
+
+ * wtf/ThreadingQt.cpp:
+ (WTF::initializeThreading): Adjusted.
+ (WTF::isMainThread): Added.
+
+2008-05-05 Darin Adler <darin@apple.com>
+
+ Reviewed by John Sullivan.
+
+ - fix debug-only leak seen on buildbot
+
+ * wtf/HashTable.h:
+ (WTF::HashTable::checkKey): After writing an empty value in, but before constructing a
+ deleted value on top of it, call the destructor so the empty value doesn't leak.
+
+2008-05-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Get rid of static data in nodes.cpp (well, at least of non-debug one).
+
+ No measurable change on SunSpider.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreadingOnce):
+ * kjs/nodes.cpp:
+ (KJS::newTrackedObjects):
+ (KJS::trackedObjectExtraRefCounts):
+ (KJS::initializeNodesThreading):
+ (KJS::ParserRefCounted::ParserRefCounted):
+ (KJS::ParserRefCounted::ref):
+ (KJS::ParserRefCounted::deref):
+ (KJS::ParserRefCounted::refcount):
+ (KJS::ParserRefCounted::deleteNewObjects):
+ * kjs/nodes.h:
+ Made newTrackedObjects and trackedObjectExtraRefCounts per-thread.
+
+2008-05-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Move call stack depth counter to global object.
+
+ * kjs/ExecState.h: (KJS::ExecState::functionCallDepth): Added a recursion depth counter to
+ per-thread data.
+ * kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::init): Initialize PerThreadData.functionCallDepth.
+ * kjs/JSGlobalObject.h: (KJS::JSGlobalObject::perThreadData): Made the result non-const.
+
+ * kjs/object.cpp:
+ (KJS::throwStackSizeExceededError): Moved throwError to a separate function, since it is now
+ the only thing in JSObject::call that needs a PIC branch.
+ (KJS::JSObject::call): Use a per-thread variable instead of local static for recursion depth
+ tracking.
+
+2008-05-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Make JavaScriptGlue and JavaScriptCore API functions implicitly call initializeThreading
+ for the sake of non-WebKit clients.
+
+ * API/JSBase.cpp:
+ (JSGarbageCollect):
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreate):
+ These are the JavaScriptCore API bottlenecks. There are a few other JSStringRef
+ and JSClassRef functions that can be called earlier, but they do not do anything that
+ requires initializeThreading.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::doInitializeThreading):
+ (KJS::initializeThreading):
+ On Darwin, make the initialization happen under pthread_once, since there is no guarantee
+ that non-WebKit clients won't try to call this function re-entrantly.
+
+ * kjs/InitializeThreading.h:
+ * wtf/Threading.h:
+ Spell out initializeThreading contract.
+
+ * wtf/ThreadingPthreads.cpp: (WTF::isMainThread): Make sure that results are correct on
+ Darwin, even if threading was initialized from a secondary thread.
+
+2008-05-02 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ https://bugs.webkit.org/show_bug.cgi?id=18826
+ Make JavaScript heap per-thread
+
+ * wtf/ThreadSpecific.h: Make sure to initialize POD thread-specific varaibles, too
+ (replaced "new T" with "new T()").
+
+ * kjs/collector.h: Renamed Collector to Heap, made the heap per-thread. Removed support for
+ multithreaded access to a heap.
+ (KJS::CollectorBlock): Removed collectOnMainThreadOnly bitmap, added a reference to owner heap.
+ (KJS::SmallCellCollectorBlock): Ditto.
+ (KJS::Heap::markListSet): Moved from a static variable in List.cpp to a per-thread one here.
+ (KJS::Heap::heap): Added a method to find which heap a JSValue is allocated in.
+
+ * kjs/collector.cpp: Changed "const size_t" constants to #defines, to avoid a PIC branch
+ (gcc was using one to access a constant used in std::max(), because it takes a reference,
+ even though std::max() itself was inlined).
+ (KJS::Heap::threadHeap): JS heap is now per-thread.
+ (KJS::Heap::Heap): Zero-initialize the heap.
+ (KJS::allocateBlock): Added NEVER_INLINE, because this function uses a PIC branch, so
+ inlining it in Heap::heapAllocate() is bad for performance, now that the latter doesn't
+ use any global data.
+ (KJS::Heap::heapAllocate): Initialize Block::heap.
+ (KJS::Heap::markCurrentThreadConservatively): Moved into markStackObjectsConservatively(),
+ as GC only works with a current thread's heap now.
+ (KJS::Heap::sweep): Removed collectOnMainThreadOnly checks.
+ (KJS::Heap::collect): Ditto.
+
+ * kjs/JSLock.cpp:
+ * kjs/JSLock.h:
+ (KJS::JSLock::JSLock):
+ Removed registerThread(), as the heap no longer cares.
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreading): Initialize new per-thread
+ variables in Heap and JSGlobalObject.
+
+ * kjs/ExecState.h: (KJS::ExecState::heap): Added a heap pointer for faster access to
+ per-thread heap, and an accessor for it.
+
+ * kjs/JSGlobalObject.h: Made JSGlobalObject linked list per-thread.
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::~JSGlobalObject): Fixed a bug in linked list handling. It only worked
+ right if the removed object was the head one!
+ (KJS::JSGlobalObject::head): Return a per-thread list head.
+ (KJS::JSGlobalObject::init): Store a reference to per-thread heap.
+ (KJS::JSGlobalObject::reset): Pass ExecState to functions that need it.
+ (KJS::JSGlobalObject::tearOffActivation): Ditto.
+ (KJS::JSGlobalObject::operator new): JSGlobalObject allocation cannot use an ExecState,
+ so it needs a custom operator new that directly accesses per-thread heap.
+
+ * kjs/list.h:
+ (KJS::List::List): Replaced m_isInMarkSet boolean with an actual pointer to the set, since it
+ is no longer a single static object.
+ (KJS::List::~List): Ditto.
+ * kjs/list.cpp:
+ (KJS::List::markSet): Removed, this is now stored in Heap.
+ (KJS::List::markProtectedLists): Take a reference to the list.
+ (KJS::List::expandAndAppend): Ask the current thread heap for a mark set reference.
+
+ * kjs/protect.h:
+ (KJS::gcProtect):
+ (KJS::gcUnprotect):
+ Use the newly added Heap::heap() method to find out which heap the value to be (un)protected
+ belongs to.
+
+ * kjs/property_map.h: Removed unused SavedProperty class.
+
+ * JavaScriptCore.exp:
+ * API/JSBase.cpp:
+ (JSGarbageCollect):
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::staticFunctionGetter):
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectMakeFunctionWithCallback):
+ (JSObjectMakeConstructor):
+ (JSObjectMakeFunction):
+ * API/JSValueRef.cpp:
+ (JSValueMakeNumber):
+ (JSValueMakeString):
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::ArrayInstance):
+ (KJS::ArrayInstance::lengthGetter):
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ (KJS::ArrayObjectImp::ArrayObjectImp):
+ (KJS::ArrayObjectImp::construct):
+ * kjs/bool_object.cpp:
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::BooleanObjectImp::BooleanObjectImp):
+ (KJS::BooleanObjectImp::construct):
+ * kjs/date_object.cpp:
+ (KJS::formatLocaleDate):
+ (KJS::DatePrototype::DatePrototype):
+ (KJS::DateObjectImp::DateObjectImp):
+ (KJS::DateObjectImp::construct):
+ (KJS::DateObjectImp::callAsFunction):
+ (KJS::DateObjectFuncImp::DateObjectFuncImp):
+ (KJS::DateObjectFuncImp::callAsFunction):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::errorProtoFuncToString):
+ (KJS::ErrorObjectImp::ErrorObjectImp):
+ (KJS::ErrorObjectImp::construct):
+ (KJS::NativeErrorPrototype::NativeErrorPrototype):
+ (KJS::NativeErrorImp::NativeErrorImp):
+ (KJS::NativeErrorImp::construct):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::lengthGetter):
+ (KJS::FunctionImp::construct):
+ (KJS::Arguments::Arguments):
+ (KJS::ActivationImp::createArgumentsObject):
+ (KJS::encode):
+ (KJS::decode):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ (KJS::functionProtoFuncToString):
+ (KJS::FunctionObjectImp::FunctionObjectImp):
+ (KJS::FunctionObjectImp::construct):
+ * kjs/internal.cpp:
+ (KJS::StringImp::toObject):
+ * kjs/internal.h:
+ (KJS::StringImp::StringImp):
+ (KJS::NumberImp::operator new):
+ * kjs/lookup.h:
+ (KJS::staticFunctionGetter):
+ (KJS::cacheGlobalObject):
+ * kjs/math_object.cpp:
+ (KJS::MathObjectImp::getValueProperty):
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/nodes.cpp:
+ (KJS::Node::handleException):
+ (KJS::NumberNode::evaluate):
+ (KJS::StringNode::evaluate):
+ (KJS::ArrayNode::evaluate):
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostDecLocalVarNode::inlineEvaluateToNumber):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::typeStringForValue):
+ (KJS::LocalVarTypeOfNode::evaluate):
+ (KJS::TypeOfResolveNode::evaluate):
+ (KJS::TypeOfValueNode::evaluate):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::PreIncConstNode::evaluate):
+ (KJS::PreDecConstNode::evaluate):
+ (KJS::PostIncConstNode::evaluate):
+ (KJS::PostDecConstNode::evaluate):
+ (KJS::PreIncBracketNode::evaluate):
+ (KJS::PreDecBracketNode::evaluate):
+ (KJS::PreIncDotNode::evaluate):
+ (KJS::PreDecDotNode::evaluate):
+ (KJS::NegateNode::evaluate):
+ (KJS::BitwiseNotNode::evaluate):
+ (KJS::MultNode::evaluate):
+ (KJS::DivNode::evaluate):
+ (KJS::ModNode::evaluate):
+ (KJS::addSlowCase):
+ (KJS::add):
+ (KJS::AddNumbersNode::evaluate):
+ (KJS::AddStringsNode::evaluate):
+ (KJS::AddStringLeftNode::evaluate):
+ (KJS::AddStringRightNode::evaluate):
+ (KJS::SubNode::evaluate):
+ (KJS::LeftShiftNode::evaluate):
+ (KJS::RightShiftNode::evaluate):
+ (KJS::UnsignedRightShiftNode::evaluate):
+ (KJS::BitXOrNode::evaluate):
+ (KJS::BitOrNode::evaluate):
+ (KJS::valueForReadModifyAssignment):
+ (KJS::ForInNode::execute):
+ (KJS::TryNode::execute):
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::evaluate):
+ * kjs/number_object.cpp:
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ (KJS::NumberObjectImp::NumberObjectImp):
+ (KJS::NumberObjectImp::getValueProperty):
+ (KJS::NumberObjectImp::construct):
+ (KJS::NumberObjectImp::callAsFunction):
+ * kjs/object.cpp:
+ (KJS::JSObject::defineGetter):
+ (KJS::JSObject::defineSetter):
+ (KJS::JSObject::putDirect):
+ (KJS::Error::create):
+ * kjs/object.h:
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ (KJS::ObjectObjectImp::ObjectObjectImp):
+ (KJS::ObjectObjectImp::construct):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::regExpProtoFuncToString):
+ (KJS::RegExpImp::getValueProperty):
+ (KJS::RegExpObjectImp::RegExpObjectImp):
+ (KJS::RegExpObjectImp::arrayOfMatches):
+ (KJS::RegExpObjectImp::getBackref):
+ (KJS::RegExpObjectImp::getLastParen):
+ (KJS::RegExpObjectImp::getLeftContext):
+ (KJS::RegExpObjectImp::getRightContext):
+ (KJS::RegExpObjectImp::getValueProperty):
+ (KJS::RegExpObjectImp::createRegExpImp):
+ * kjs/regexp_object.h:
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::StringInstance):
+ (KJS::StringInstance::lengthGetter):
+ (KJS::StringInstance::indexGetter):
+ (KJS::stringInstanceNumericPropertyGetter):
+ (KJS::StringPrototype::StringPrototype):
+ (KJS::replace):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ (KJS::StringObjectImp::StringObjectImp):
+ (KJS::StringObjectImp::construct):
+ (KJS::StringObjectImp::callAsFunction):
+ (KJS::StringObjectFuncImp::StringObjectFuncImp):
+ (KJS::StringObjectFuncImp::callAsFunction):
+ * kjs/string_object.h:
+ (KJS::StringInstanceThatMasqueradesAsUndefined::StringInstanceThatMasqueradesAsUndefined):
+ * kjs/testkjs.cpp:
+ (GlobalObject::GlobalObject):
+ (functionGC):
+ (functionRun):
+ (functionReadline):
+ (kjsmain):
+ * kjs/ustring.h:
+ * kjs/value.cpp:
+ (KJS::JSCell::operator new):
+ (KJS::jsString):
+ (KJS::jsOwnedString):
+ (KJS::jsNumberCell):
+ * kjs/value.h:
+ (KJS::jsNaN):
+ (KJS::jsNumber):
+ (KJS::jsNumberFromAnd):
+ (KJS::JSCell::marked):
+ (KJS::JSCell::mark):
+ (KJS::JSValue::toJSNumber):
+ Removed collectOnMainThreadOnly, as this is the only way to collect now. Replaced calls to
+ static Collector methods with calls to per-thread Heap ones.
+
+2008-05-02 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ - Mac build fix
+
+ * wtf/StrHash.h: Added header guards and removed #include "config.h".
+
+2008-05-01 Ada Chan <adachan@apple.com>
+
+ #include <wtf/StrHash.h> in identifier.cpp.
+
+ Reviewed by Maciej.
+
+ * kjs/identifier.cpp:
+
+2008-05-01 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-05-01 Sam Weinig <sam@webkit.org>
+
+ Fix build.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-05-01 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - Fix "sample" output so that it can be imported into Instruments
+ - Also keep track of number of times a function is profiled.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Add StrHash.h which needed
+ to be pulled out of identifier.cpp so that it could be used by the
+ profiler and identifiers.
+ * kjs/identifier.cpp: Ditto.
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::printDataInspectorStyle): Inspector style
+ printing should show microseconds.
+ (KJS::FunctionCallProfile::printDataSampleStyle): Sample style printing
+ now counts the number of times a function is in the stack tree and does
+ not print microseconds since that does not make sense for a sampler.
+ * profiler/FunctionCallProfile.h: Keep track of number of times a
+ function is profiled.
+ (KJS::FunctionCallProfile::numberOfCalls):
+ * profiler/Profiler.cpp:
+ (KJS::functionNameCountPairComparator): Comparator for sort function in
+ printDataSampleStyle.
+ (KJS::Profiler::printDataSampleStyle): Print the number of times that a
+ function is listed in the stack tree in order of most times listed.
+ * wtf/HashCountedSet.h: Added copyToVector since it didn't exist and is
+ a more standard way to copy a HashSet to a Vector. I added on variant
+ that takes a pair as the Vector's type and so the HashCountedSet simply
+ fills in that pair with its internal pair, and another variant that
+ takes a Vector of the type of the HashCountedSet and only fills in the
+ Vector with the first element of the pair.
+ (WTF::copyToVector):
+ * wtf/StrHash.h: Added.
+ (WTF::):
+
+2008-04-29 David Kilzer <ddkilzer@apple.com>
+
+ BUILD FIX for ENABLE(DASHBOARD_SUPPORT)
+
+ * wtf/Platform.h: Defined ENABLE(DASHBOARD_SUPPORT) to 1 only for
+ PLATFORM(MAC) and PLATFORM(WIN). Changed default to 0 for other
+ ports.
+
+2008-04-29 Greg Bolsinga <bolsinga@apple.com>
+
+ Reviewed by Darin.
+
+ Wrapped Dashboard code with ENABLE(DASHBOARD_SUPPORT)
+
+ * wtf/Platform.h:
+
+2008-04-29 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ -Keep call count.
+
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::FunctionCallProfile):
+ (KJS::FunctionCallProfile::didExecute): Implements call count and fixed a bug where a stackIndex
+ of 0 was causing the assert to be hit.
+ (KJS::FunctionCallProfile::stopProfiling):
+ (KJS::FunctionCallProfile::endAndRecordCall):
+ * profiler/FunctionCallProfile.h:
+
+2008-04-29 Simon Hausmann <hausmann@webkit.org>
+
+ Qt/Windows build fix. The externally declared hash tables are actually
+ declared const and the const is mangled in the symbol name, so when
+ importing they also need to be marked const.
+
+ When compiling without MULTIPLE_THREADS use a const HashTable&
+ instead of a HashTable& in ThreadClassInfoHashTables to avoid
+ initializing the latter with a const reference.
+
+ * kjs/JSGlobalObject.cpp:
+
+2008-04-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix.
+
+ * kjs/ExecState.h: For whatever reason, MSVC couldn't generate a default constructor for
+ a struct that had a "const List" member. Removing the const qulifier makes the problem go away.
+
+2008-04-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Fix run-webkit-tests --threading
+ and provisionally fix <https://bugs.webkit.org/show_bug.cgi?id=18661>
+ Proxy server issue in Sunday's Nightly
+
+ Changed ClassInfo objects for built-in objects to hold a getter function returning
+ a per-thread instance. This makes it safe to share these ClassInfo objects between threads -
+ and these are the only ones that need to be shared.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::~Lexer):
+ * kjs/lexer.h:
+ Made mainTable a member of Lexer, so that it no longer needs to be shared between threads.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::deleteProperty):
+ (KJS::JSObject::findPropertyHashEntry):
+ (KJS::JSObject::propertyIsEnumerable):
+ (KJS::JSObject::getPropertyAttributes):
+ (KJS::JSObject::getPropertyNames):
+ * kjs/object.h:
+ (KJS::ClassInfo::propHashTable):
+ Added a new classPropHashTableGetterFunction field to ClassInfo. If it is non-zero, the
+ static table is not used.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::ThreadClassInfoHashTables::ThreadClassInfoHashTables): This new class holds per-thread
+ HashTables for built-in classes. The old static structs are copied to create per-thread
+ instances.
+ (KJS::JSGlobalObject::threadClassInfoHashTables): An accessor/initializer for the above.
+ (KJS::JSGlobalObject::init): Copy per-thread data into a single structure for faster access.
+ Also, construct globalExec.
+ (KJS::JSGlobalObject::reset): Adapted for globalExec now being an OwnPtr.
+ (KJS::JSGlobalObject::mark): Ditto.
+ (KJS::JSGlobalObject::globalExec): Ditto.
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): Made JSGlobalObject::JSGlobalObjectData::globalExec an OwnPtr, so that it can
+ be initialized from JSGlobalObject::init() after them. Otherwise, ExecState constructor was
+ trying to access half-initialized JSGlobalObject to make its own copy of these table
+ references, and failed.
+ (KJS::JSGlobalObject::JSGlobalObject): Pass "this" value to init() to create globalExec.
+ (KJS::JSGlobalObject::perThreadData): An accessor for per-thread data.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/ExecState.h:
+ (KJS::ExecState::propertyNames):
+ (KJS::ExecState::emptyList):
+ (KJS::ExecState::arrayTable):
+ (KJS::ExecState::dateTable):
+ (KJS::ExecState::mathTable):
+ (KJS::ExecState::numberTable):
+ (KJS::ExecState::RegExpImpTable):
+ (KJS::ExecState::RegExpObjectImpTable):
+ (KJS::ExecState::stringTable):
+ * kjs/ExecStateInlines.h:
+ (KJS::ExecState::ExecState):
+ Each ExecState holds its own reference to per-thread data, for even faster access. Moved
+ m_emptyList and m_propertyNames to the same structure, making ExecState faster to construct
+ and take less space on the stack.
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreading): Initialize thread-static data
+ added to JSGlobalObject.
+
+ * API/JSCallbackConstructor.cpp:
+ * API/JSCallbackFunction.cpp:
+ * API/JSCallbackObject.cpp:
+ * JavaScriptCore.exp:
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyAttributes):
+ * kjs/JSVariableObject.h:
+ * kjs/array_instance.cpp:
+ * kjs/array_object.cpp:
+ (KJS::ArrayPrototype::getOwnPropertySlot):
+ * kjs/bool_object.cpp:
+ * kjs/create_hash_table:
+ * kjs/date_object.cpp:
+ (KJS::DatePrototype::getOwnPropertySlot):
+ (KJS::DateObjectImp::DateObjectImp):
+ * kjs/error_object.cpp:
+ * kjs/function.cpp:
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ * kjs/internal.cpp:
+ * kjs/lookup.h:
+ * kjs/math_object.cpp:
+ (KJS::MathObjectImp::getOwnPropertySlot):
+ * kjs/number_object.cpp:
+ (KJS::NumberObjectImp::getOwnPropertySlot):
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::RegExpImp::getOwnPropertySlot):
+ (KJS::RegExpImp::put):
+ (KJS::RegExpObjectImp::getOwnPropertySlot):
+ (KJS::RegExpObjectImp::put):
+ * kjs/string_object.cpp:
+ (KJS::StringPrototype::getOwnPropertySlot):
+ Adjust for the above changes.
+
+2008-04-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam.
+
+ - make sure RefPtr's default hash doesn't ref/deref when computing the hash
+ - remove remnants of the hash table storage type optimization
+
+ * wtf/HashFunctions.h: Used "using" to get the hash and equal functions
+ from PtrHash<P*> into PtrHash<RefPtr<P>>.
+
+ * wtf/HashMap.h: Replaced uses of PairBaseHashTraits with PairHashTraits.
+ Eliminated storage-related typedefs. Removed constructor, destructor,
+ copy constructor, and destructor since the compiler-generated ones are
+ fine. Removed refAll and derefAll. Took out unnnecessary typecasts.
+ Removed use of RefCounter.
+
+ * wtf/HashSet.h: Eliminated storage-related typedefs. Removed constructor,
+ destructor, copy constructor, and destructor since the compiler-generated
+ ones are fine. Removed refAll and derefAll. Removed unneeded template
+ arguents from HashSetTranslatorAdapter. Eliminated unneeded HashSetTranslator
+ template.
+
+ * wtf/HashTable.h: Tweaked formatting. Removed NeedsRef, RefCounterBase,
+ RefCounter, HashTableRefCounterBase, HashTableRefCounter, and Assigner
+ class templates.
+
+ * wtf/HashTraits.h: Removed StorageTraits, needsRef, PairBaseHashTraits,
+ and HashKeyStorageTraits.
+
+ * wtf/RefPtrHashMap.h: Made all the same fixes as in HashMap. Also made
+ the corresponding changes to RefPtrHashMapRawKeyTranslator.
+
+2008-04-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Mitz.
+
+ - fix assertion hit every time you view www.apple.com
+
+ * kjs/PropertyNameArray.cpp:
+ (KJS::PropertyNameArray::add): Changed assertion to allow null and empty strings.
+ Now to find out why we have a property named "" and if that's a bug!
+
+2008-04-27 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fix crash inside PtrHash::hash when loading a page.
+
+ * wtf/HashFunctions.h: Explicitly use the superclass implementation of hash to avoid infinite recursion.
+
+2008-04-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix <rdar://problem/5657459> REGRESSION: JavaScriptCore no longer builds with
+ GCC 4.2 due to pointer aliasing warnings
+
+ Fix this by removing the HashTable optimizations that allowed us to share a back end
+ implementation between hash tables with integers, pointers, RefPtr, and String objects
+ as keys. The way it worked was incompatible with strict aliasing.
+
+ This increases code size. On Mac OS X we'll have to regenerate .order files to avoid
+ slowing down Safari startup times.
+
+ This creates a slight slowdown in SunSpider, mitigated by the following four speedups:
+
+ - speed up array put slightly by moving a branch (was already done for get)
+
+ - speed up symbol table access by adding a function named inlineGet to HashMap
+ and using that in symbolTableGet/Put
+
+ - speed up PropertyNameArray creation by reducing the amount of reference count
+ churn and uniqueness checking when adding names and not doing any allocation at
+ all when building small arrays
+
+ - speed up conversion of strings to floating point numbers by eliminating the
+ malloc/free of the buffer for the ASCII copy of the string; a way to make
+ things even faster would be to change strtod to take a UTF-16 string
+
+ Note that there is considerable unused complexity now in HashSet/Map/Table to support
+ "storage types", which is no longer used. Will do in a separate patch.
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::JSCallbackObject<Base>::getPropertyNames): Removed explicit cast to Identifier to
+ take advantage of the new PropertyNameArray::add overload and avoid reference count churn.
+ * API/JSObjectRef.cpp:
+ (JSPropertyNameAccumulatorAddName): Ditto.
+ * JavaScriptCore.exp: Updated PropertyNameArray::add entry point name.
+
+ * kjs/JSVariableObject.cpp: Removed now-unneeded IdentifierRepHashTraits::nullRepPtr
+ definition (see below).
+ (KJS::JSVariableObject::getPropertyNames): Removed explicit cast to Identifier.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet): Use inlineGet for speed. Also changed to do
+ early exit instead of nesting the body inside an if.
+ (KJS::JSVariableObject::symbolTablePut): Ditto.
+
+ * kjs/PropertyNameArray.cpp:
+ (KJS::PropertyNameArray::add): Changed implementation to take a raw pointer instead of
+ a reference to an identifier. Do uniqueness checking by searching the vector when the
+ vector is short, only building the set once the vector is large enough.
+
+ * kjs/PropertyNameArray.h: Added an overload of add for a raw pointer, and made the old
+ add function call that one. Added an addKnownUnique function for use when the new
+ name is known to be different from any other in the array. Changed the vector to have
+ an inline capacity of 20.
+
+ * kjs/SymbolTable.h: Changed IdentifierRepHash to inherit from the default hash for
+ a RefPtr so we don't have to define so much. Added an overload of the hash function for
+ a raw pointer as required by the new RefPtrHashMap. Got rid of the now-unneeded
+ IdentifierRepHashTraits -- the default traits now work fine. Added a definition of
+ empthValueIsZero to SymbolTableIndexHashTraits; not having it was incorrect, but harmless.
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::put): Move the maxArrayIndex check inside the branch that checks
+ the index against the length, as done in the get function.
+
+ * kjs/function.cpp:
+ (KJS::globalFuncKJSPrint): Changed to use the new getCString instead of cstring.
+
+ * kjs/internal.cpp: Removed printInfo debugging function, a client of cstring.
+ If we need a debugging function we can easily make a better one and we haven't
+ used this one in a long time.
+ * kjs/internal.h: Ditto.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::getPropertyNames): Removed explicit cast to Identifier.
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::getEnumerablePropertyNames): Ditto. Also added a special case for
+ the case where the propertyNames array is empty -- in that case we know we're adding
+ a set of names that are non-overlapping so we can use addKnownUnique.
+ * kjs/ustring.cpp:
+ (KJS::UString::getCString): Replaces cstring. Puts the C string into a CStringBuffer,
+ which is a char Vector with an inline capacity. Also returns a boolean to indicate if
+ the converion was lossy, which eliminates the need for a separate is8Bit call.
+ (KJS::UString::toDouble): Changed to call getCString instead of cstring.
+ * kjs/ustring.h: Ditto.
+
+ * wtf/HashFunctions.h: Overload the hash and equal functions for RefPtr's default
+ hash to take raw pointers. This works with the changes to RefPtrHashMap to avoid
+ introducing refcount churn.
+
+ * wtf/HashMap.h: Removed special code to convert the deleted value to the empty value
+ when writing a new value into the map. This is now handled elsewhere.
+ (WTF::HashMap::get): Removed code that checks for an empty hash table before calling
+ HashTable::lookup; it's slightly more efficient to do this check inside lookup.
+
+ * wtf/HashTable.h:
+ (WTF::HashTable::isDeletedBucket): Changed to use isDeletedValue instead of using
+ deletedValue and the equality operator.
+ (WTF::HashTable::deleteBucket): Changed to use constructDeletedValue instead of
+ using deletedValue and the assignment operator.
+ (WTF::HashTable::checkKey): Added. Factors out the check for values that are empty
+ or deleted keys that's used in various functions below.
+ (WTF::HashTable::lookup): Changed to use checkKey, check for a 0 table, and also
+ made public for use by RefPtrHashMap.
+ (WTF::HashTable::lookupForWriting): Changed to use checkKey.
+ (WTF::HashTable::fullLookupForWriting): Changed to use checkKey.
+ (WTF::HashTable::add): Changed to use checkKey, and call initializeBucket on a
+ deleted bucket before putting a new entry into it.
+ (WTF::HashTable::addPassingHashCode): Ditto.
+ (WTF::HashTable::deallocateTable): Check isDeletedBucket before calling ~ValueType.
+
+ * wtf/HashTraits.h: Got ridd of all the HashTraits specialization for the integer
+ types, since GeneicHashTraitsBase already deals with integers separately. Put the
+ deleted value support into GenericHashTraitsBase. Changed FloatHashTraits to
+ inherit from GenericHashTraits, and define construct/isDeletedValue rather than
+ deletedValue. Removed the ref and deref functions from RefPtr's HashTraits, and
+ defined construct/isDeletedValue. Eliminated DeletedValueAssigner. Changed
+ PairHashTraits to define construct/isDeletedValue, and also merged
+ PairBaseHashTraits in with PairHashTraits. Got rid of all specialization of
+ HashKeyStorageTraits. We'll remove that, and the needsRef data member, later.
+
+ * wtf/RefPtr.h: Added HashTableDeletedValueType, an enum type with a single value,
+ HashTableDeletedValue. Used that type to make a new constructor to construct
+ deleted values and also added an isHashTableDeletedValue function.
+
+ * wtf/RefPtrHashMap.h: Added RefPtrHashMapRawKeyTranslator and used it to implement
+ the raw pointer functions. This is a way to continue to avoid refcount thrash. We
+ can't use the old way because it depended on the underlying map using a non-RefPtr
+ type.
+ (WTF::HashMap::find): Use find with RefPtrHashMapRawKeyTranslator.
+ (WTF::HashMap::contains): Use contains with RefPtrHashMapRawKeyTranslator.
+ (WTF::HashMap::inlineAdd): Use add with RefPtrHashMapRawKeyTranslator.
+ (WTF::HashMap::get): Removed code that checks for an empty hash table before calling
+ HashTable::lookup; it's slightly more efficient to do this check inside lookup.
+ (WTF::HashMap::inlineGet): Added. Just like get, but marked inline for use in the
+ symbol table code.
+
+2008-04-25 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Mark Rowe.
+
+ Remove SavedBuiltins and SavedProperties classes and the methods used to
+ save data to them. The CachedPage now stores a the JSGlobalObject in full.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSGlobalObject.h:
+ * kjs/JSVariableObject.cpp:
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::localStorage):
+ * kjs/SavedBuiltins.h: Removed.
+ * kjs/object.h:
+ * kjs/property_map.cpp:
+ * kjs/property_map.h:
+
+2008-04-25 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Sam Weinig.
+
+ Add some content to an empty ICU header file to prevent verification errors.
+
+ * icu/unicode/utf_old.h:
+
+2008-04-25 David Kilzer <ddkilzer@apple.com>
+
+ <rdar://problem/5819422> REGRESSION: Wrong line number passed to -willLeaveCallFrame
+
+ Patch by George Dicker and Michael Kahl. Reviewed by Darin.
+
+ When -[NSObject(WebScriptDebugDelegate) webView:willLeaveCallFrame:sourceId:line:forWebFrame:]
+ is invoked, the first line number of the function is returned instead of the last
+ line number. This regressed in r28458.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNodeWithDebuggerHooks::execute): Pass lastLine() instead of lineNo()
+ when calling Debugger::returnEvent().
+
+2008-04-25 Darin Adler <darin@apple.com>
+
+ Done with Stephanie Lewis.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Prepare for compilation with gcc 4.2 by
+ adding -fno-strict-aliasing to CollatorICU.cpp.
+
+2008-04-24 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Add a #define to easily enable collecting on every allocation to aid
+ debugging GC bugs.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+
+2008-04-24 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam and Sam.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ -Only profile the page group that starts profiling to avoid profiling
+ tools that shouldn't be profiled unless explicitly requested to.
+
+ * JavaScriptCore.exp: Export new signature.
+ * kjs/JSGlobalObject.cpp: Add unique identifiers to the JSGlobalObject.
+ (KJS::JSGlobalObject::init):
+ * kjs/JSGlobalObject.h: Ditto.
+ (KJS::JSGlobalObject::setPageGroupIdentifier):
+ (KJS::JSGlobalObject::pageGroupIdentifier):
+ * profiler/Profiler.cpp: Check the identifier of the page group of the
+ lexical global exec state and only profile if it matches the given page
+ group identifier.
+ (KJS::Profiler::startProfiling):
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+ * profiler/Profiler.h: Ditto.
+ (KJS::Profiler::Profiler):
+
+2008-04-24 Julien Chaffraix <jchaffraix@webkit.org>
+
+ Reviewed by Simon.
+
+ Bug 15940: Implement threading API for Qt
+ https://bugs.webkit.org/show_bug.cgi?id=15940
+
+ Original patch by Justin Haygood, tweaked by me.
+
+ * JavaScriptCore.pri:
+ * wtf/ThreadingQt.cpp: Added.
+ (WTF::threadMapMutex):
+ (WTF::threadMap):
+ (WTF::establishIdentifierForThread):
+ (WTF::clearThreadForIdentifier):
+ (WTF::threadForIdentifier):
+ (WTF::initializeThreading):
+ (WTF::ThreadPrivate::getReturnValue):
+ (WTF::ThreadPrivate::ThreadPrivate):
+ (WTF::ThreadPrivate::run):
+ (WTF::createThread):
+ (WTF::waitForThreadCompletion): return !res to return
+ 0 on success (to match the pthreads implementation).
+ (WTF::detachThread):
+ (WTF::identifierByQthreadHandle):
+ (WTF::currentThread):
+ (WTF::Mutex::Mutex):
+ (WTF::Mutex::~Mutex):
+ (WTF::Mutex::lock):
+ (WTF::Mutex::tryLock):
+ (WTF::Mutex::unlock):
+ (WTF::ThreadCondition::ThreadCondition):
+ (WTF::ThreadCondition::~ThreadCondition):
+ (WTF::ThreadCondition::wait):
+ (WTF::ThreadCondition::timedWait):
+ (WTF::ThreadCondition::signal):
+
+2008-04-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - simplify use of HashTraits to prepare for some upcoming hash table changes
+
+ * kjs/SymbolTable.h: Made SymbolTableIndexHashTraits derive from HashTraits<size_t>
+ and specialize only the empty value.
+
+2008-04-23 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Reviewed by Simon.
+
+ Removed the #define for USE_SYSTEM_MALLOC that we set in WebKit.pri
+ already.
+
+ * wtf/Platform.h:
+
+2008-04-21 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ <rdar://problem/5770054> JavaScript profiler (10928)
+ - When stop profiling is called we need to stop the timers on all the
+ functions that are still running.
+
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::didExecute):
+ (KJS::FunctionCallProfile::stopProfiling):
+ * profiler/FunctionCallProfile.h:
+ * profiler/Profiler.cpp:
+ (KJS::Profiler::stopProfiling):
+
+2008-04-21 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Move collector main thread initialization from WebKit/win to KJS::initializeThreading.
+
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading):
+
+2008-04-21 Adam Roben <aroben@apple.com>
+
+ MSVC build fix
+
+ Reviewed by Alexey Proskuryakov.
+
+ * kjs/ustring.h:
+ (KJS::UString::cost): Disable a warning about assigning a 32-bit
+ size_t into a 31-bit size_t.
+
+2008-04-21 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Lars.
+
+ Made convertValueToQVariant accessible from within WebKit/qt/Api
+
+ * bindings/qt/qt_runtime.h:
+
+2008-04-21 Holger Hans Peter Freyther <holger.freyther@trolltech.com>
+
+ Reviewed by Simon.
+
+ Build fix for Qt 4.3
+
+ * When building WebCore/internal make sure the QT_[BEGIN,END]_NAMESPACE is
+ always defined. Do this by adding defines to the compiler line
+ * For users of our API this is not feasible. Every public header file should
+ include qwebkitglobal.h. Define the QT_BEGIN_NAMESPACE and QT_END_NAMESPACE
+ when we are building everything < 4.4.0 and don't have them defined.
+
+ * kjs/testkjs.pro:
+
+2008-04-19 Matt Lilek <webkit@mattlilek.com>
+
+ Not reviewed, Windows build fix - copy the profiler headers in all
+ configurations, not just Debug_Internal.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-04-19 Mike Hommey <glandium@debian.org>
+
+ Reviewed by Alp Toker.
+
+ Don't build testkjs with rpath.
+
+ * GNUmakefile.am:
+
+2008-04-18 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fixes. Rename LocalStorage.h to LocalStorageEntry.h
+ to avoid header detection issues between WebCore/storage/LocalStorage.h
+ and it, and add $(PROFILER_SOURCES) to the wx JSCore build.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * jscore.bkl:
+ * kjs/ExecState.h:
+ * kjs/JSVariableObject.h:
+ * kjs/LocalStorage.h: Removed.
+ * kjs/LocalStorageEntry.h: Copied from JavaScriptCore/kjs/LocalStorage.h.
+ * kjs/function.h:
+
+2008-04-18 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Reviewed by Alp Toker.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16620
+ [GTK] Autotools make dist and make check support
+
+ Cleanups.
+
+ * GNUmakefile.am:
+
+2008-04-18 Jon Honeycutt <jhoneycutt@apple.com>
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Windows
+ build fix.
+
+2008-04-11 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Antti Koivisto.
+
+ Silence GCC 4.3 warnings by removing extraneous consts.
+
+ * kjs/ustring.cpp:
+ * kjs/ustring.h:
+
+2008-04-18 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ - Use Deque instead of Vector since the profiler uses prepend a lot
+ and deque is faster at that.
+
+ * profiler/FunctionCallProfile.h:
+ (KJS::FunctionCallProfile::milliSecs): Corrected the name to match
+ its output.
+ * wtf/Deque.h:
+ (WTF::deleteAllValues):
+
+2008-04-18 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam and Adam.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ - Cleaned up the header file and made some functions static, added
+ a new, sane, printing function, and fixed a few minor bugs.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * profiler/FunctionCallProfile.cpp:
+ (KJS::FunctionCallProfile::didExecute): Removed assertion that time is
+ > 0 because at ms resolution that may not be true and only cross-
+ platform way to get time differences is in ms.
+ (KJS::FunctionCallProfile::printDataInspectorStyle): Added a new
+ printing function for dumping data in a sane style.
+ (KJS::FunctionCallProfile::printDataSampleStyle): Fixed a bug where we
+ displayed too much precision when printing our floats. Also added logic
+ to make sure we don't display 0 because that doesn't make sense for a
+ sampling profile.
+ * profiler/FunctionCallProfile.h:
+ * profiler/Profiler.cpp: Moved functions that could be static into the
+ implementation, and chaned the ASSERTs to early returns. I did this
+ because console.profile() is a JS function and so was being profiled
+ but asserting because the profiler had not been started! In the future
+ I would like to put the ASSERTs back and not profile the calls to
+ console.profile() and console.profileEnd().
+ (KJS::Profiler::willExecute):
+ (KJS::Profiler::didExecute):
+ (KJS::getStackNames): Fixed a bug where the wrong ExecState was being
+ used.
+ (KJS::getFunctionName):
+ (KJS::Profiler::printDataInspectorStyle):
+ * profiler/Profiler.h:
+
+2008-04-18 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Fix leaks during plugin tests (which actually excercise background JS), and potential
+ PAC brokenness that was not reported, but very likely.
+
+ The leaks shadowed a bigger problem with Identifier destruction. Identifier::remove involves
+ an IdentifierTable lookup, which is now a per-thread instance. Since garbage collection can
+ currently happen on a different thread than allocation, a wrong table was used.
+
+ No measurable change on SunSpider total, ~1% variation on individual tests.
+
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::create):
+ (KJS::UString::Rep::destroy):
+ * kjs/ustring.h:
+ Replaced isIdentifier with a pointer to IdentifierTable, so that destruction can be done
+ correctly. Took one bit from reportedCost, to avoid making UString::Rep larger (performance
+ effect was measurable on SunSpider).
+
+ * kjs/identifier.cpp:
+ (KJS::IdentifierTable::IdentifierTable):
+ (KJS::IdentifierTable::~IdentifierTable):
+ (KJS::IdentifierTable::add):
+ (KJS::IdentifierTable::remove):
+ Make IdentifierTable a real class. Its destructor needs to zero out outstanding references,
+ because some identifiers may briefly outlive it during thread destruction, and we don't want
+ them to use their stale pointers.
+
+ (KJS::LiteralIdentifierTable):
+ (KJS::Identifier::add):
+ Now that LiteralIdentifierTable is per-thread and can be destroyed not just during application
+ shutdown, it is not appropriate to simply bump refcount for strings that get there; changed
+ the table to hold RefPtrs.
+
+ (KJS::CStringTranslator::translate):
+ (KJS::UCharBufferTranslator::translate):
+ (KJS::Identifier::addSlowCase):
+ (KJS::Identifier::remove):
+ * kjs/identifier.h:
+ (KJS::Identifier::add):
+ Use and update UString::Rep::identifierTable as appropriate. Updating it is now done in
+ IdentifierTable::add, not in translators.
+
+2008-04-18 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Get rid of static compareWithCompareFunctionArguments in array_instance.cpp.
+
+ No change on SunSpider, CelticKane or iBench JavaScript. It is probable that in some cases,
+ merge sort is still faster, but more investigation is needed to determine a new cutoff.
+ Or possibly, it would be better to do what FIXME says (change to tree sort).
+
+ Also, made arguments a local variable - not sure why it was a member of
+ CompareWithCompareFunctionArguments.
+
+ * kjs/array_instance.cpp:
+ (KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
+ (KJS::CompareWithCompareFunctionArguments::operator()):
+ (KJS::ArrayInstance::sort):
+
+2008-04-18 Simon Hausmann <hausmann@webkit.org>
+
+ Build fix for gcc 4.3. Include stdio.h for printf.
+
+ * profiler/FunctionCallProfile.cpp:
+ * profiler/Profiler.cpp:
+
+2008-04-17 Jon Honeycutt <jhoneycutt@apple.com>
+
+ Reviewed by mrowe.
+
+ * wtf/Platform.h: Add HAVE_ACCESSIBILITY to Platform.h.
+
+2008-04-17 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Maciej.
+
+ Thread static data destructors are not guaranteed to be called in any particular order;
+ turn ThreadSpecific into a phoenix-style singleton to avoid accessing freed memory when
+ deleted objects are interdependent (e.g. CommonIdentifiers and internal identifier tables).
+
+ No change on SunSpider.
+
+ * wtf/ThreadSpecific.h:
+ (WTF::ThreadSpecific::Data::Data):
+ (WTF::::get):
+ (WTF::::set):
+ (WTF::::destroy):
+
+2008-04-15 Srinivas Rao. M Hamse <msrinirao@gmail.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ - gcc 3.x build fix
+
+ * kjs/nodes.h: CallerType definition made public for gcc 3.x compilation
+
+2008-04-16 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Sam Weinig
+
+ Change ThreadSafeShared to act like RefCounted by starting out with a single ref by default
+
+ * wtf/Threading.h:
+ (WTF::ThreadSafeShared::ThreadSafeShared):
+
+2008-04-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ - To keep the behavior of the WebKit and JavaScriptCore API's the same,
+ we need to hide the fact that the global object and the window object
+ are no longer the same thing, and the the global object now changes on
+ navigations. To do this, only the wrapper should ever be exposed. This
+ fixes the two remaining spots where the internal global object is exposed,
+ the windowScriptObject returned from [WebFrame windowObject] and the object
+ return by calling JSContextGetGlobalObject on [WebFrame globalContext].
+
+ * API/JSContextRef.cpp:
+ (JSContextGetGlobalObject):
+ This is a bit of a hack, this returns the "this" representation of the globalObject
+ which will be the WrapperWindow for WebCore and the globalObject for non-WebCore.
+
+ * API/JSObjectRef.cpp:
+ (JSObjectSetProperty):
+ Call the new putWithAttributes method instead of relying on lower-level calls.
+ This is needed so that the window wrapper can forward the calls.
+
+ * JavaScriptCore.exp:
+ * kjs/Activation.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::putWithAttributes):
+ * kjs/JSGlobalObject.h:
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTablePutWithAttributes):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::putWithAttributes):
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::handleSlowCase):
+ (KJS::ConstDeclNode::evaluateSingle):
+ (KJS::EvalNode::processDeclarations):
+ * kjs/object.cpp:
+ (KJS::JSObject::putWithAttributes):
+ * kjs/object.h:
+ Rename initializeVariable to putWithAttributes and move it down to JSObject so it
+ can be used for JSObjectSetProperty.
+
+2008-04-16 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam and Geoff.
+
+ -<rdar://problem/5770054> JavaScript profiler (10928)
+ Inital profiler prototype
+
+ * GNUmakefile.am: Added new files to project
+ * JavaScriptCore.pri: Ditto
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Ditto
+ * JavaScriptCore.xcodeproj/project.pbxproj: Ditto
+ * JavaScriptCoreSources.bkl: Ditto
+ * kjs/config.h: Put compiling flag in here.
+ * kjs/function.cpp: Instrument calling the function eval().
+ (KJS::eval):
+ * kjs/interpreter.cpp: Instrument evaluating global scopes.
+ (KJS::Interpreter::evaluate):
+ * kjs/object.cpp: Instrument JS function calls.
+ (KJS::JSObject::call):
+ * profiler: Added.
+ * profiler/FunctionCallProfile.cpp: Added.
+ (KJS::FunctionCallProfile::FunctionCallProfile):
+ (KJS::FunctionCallProfile::~FunctionCallProfile):
+ (KJS::FunctionCallProfile::willExecute): Call right before the JS function or executing context is executed to start the profiler's timer.
+ (KJS::FunctionCallProfile::didExecute): Call right after the JS function or executing context is executed to stop the profiler's timer.
+ (KJS::FunctionCallProfile::addChild): Add a child to the current FunctionCallProfile if it isn't already a child of the current FunctionalCallProfile.
+ (KJS::FunctionCallProfile::findChild): Return the child that matches the given name if there is one.
+ (KJS::FunctionCallProfile::printDataSampleStyle): Print the current profiled information in a format that matches sample's output.
+ * profiler/FunctionCallProfile.h: Added.
+ (KJS::FunctionCallProfile::FunctionCallProfile):
+ (KJS::FunctionCallProfile::~FunctionCallProfile):
+ (KJS::FunctionCallProfile::functionName):
+ (KJS::FunctionCallProfile::microSecs):
+ * profiler/Profiler.cpp: Added.
+ (KJS::Profiler::profiler):
+ (KJS::Profiler::sharedProfiler): Return global singleton (may change due to multi-threading concerns)
+ (KJS::Profiler::startProfiling): Don't start collecting profiling information until the user starts the profiler. Also don't clear old prfiled data until the profiler is restarted.
+ (KJS::Profiler::stopProfiling): Stop collecting profile information.
+ (KJS::Profiler::willExecute): Same as above.
+ (KJS::Profiler::didExecute): Same as above.
+ (KJS::Profiler::insertStackNamesInTree): Follow the stack of the given names and if a sub-stack is not in the current tree, add it.
+ (KJS::Profiler::getStackNames): Get the names from the different passed in parameters and order them as a stack.
+ (KJS::Profiler::getFunctionName): Get the function name from the given parameter.
+ (KJS::Profiler::printDataSampleStyle): Print the current profiled information in a format that matches sample's output.
+ (KJS::Profiler::debugLog):
+ * profiler/Profiler.h: Added.
+ (KJS::Profiler::Profiler):
+
+2008-04-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ - Remove kjs_ prefix from strtod, dtoa, and freedtoa and put it
+ in the KJS namespace.
+ - Make strtod, dtoa, and freedtoa c++ functions instead of extern "C".
+ - Remove mode switching from dtoa. ~2% improvement on test 26.
+ - Removes all unnecessary #defines from dtoa code.
+
+ * JavaScriptCore.exp:
+ * kjs/dtoa.cpp:
+ (KJS::ulp):
+ (KJS::b2d):
+ (KJS::d2b):
+ (KJS::ratio):
+ (KJS::strtod):
+ (KJS::freedtoa):
+ (KJS::dtoa):
+ * kjs/dtoa.h:
+ * kjs/function.cpp:
+ (KJS::parseInt):
+ * kjs/lexer.cpp:
+ (KJS::Lexer::lex):
+ * kjs/number_object.cpp:
+ (KJS::integer_part_noexp):
+ (KJS::numberProtoFuncToExponential):
+ * kjs/ustring.cpp:
+ (KJS::UString::from):
+ (KJS::UString::toDouble):
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Get rid of static execForCompareByStringForQSort in array_instance.cpp.
+
+ No change on SunSpider, CelticKane or iBench JavaScript.
+
+ * kjs/array_instance.cpp:
+ (KJS::ArraySortComparator::ArraySortComparator):
+ (KJS::ArraySortComparator::operator()):
+ (KJS::ArrayInstance::sort):
+ Switch slow case to std::sort, so that ExecState can be passed in a comparator.
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ MSVC build fix.
+
+ * kjs/CommonIdentifiers.cpp:
+ * kjs/CommonIdentifiers.h:
+ * kjs/Parser.cpp:
+ * kjs/Parser.h:
+ * kjs/identifier.cpp:
+ * kjs/lexer.h:
+ * wtf/ThreadSpecific.h:
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Build fix.
+
+ * kjs/date_object.cpp:
+ * kjs/date_object.h:
+ Don't include DateMath.h from date_object.h, as the latter is used from WebCore, while
+ where the former is not available.
+
+2008-04-16 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Unreviewed build fix for MSVC. It does not want to have
+ WTF in the KJS namespace.
+
+ * kjs/CommonIdentifiers.h:
+
+2008-04-16 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Unreviewed build fix for gcc.
+
+ ::msToGregorianDateTime is not known to it.
+
+ * kjs/date_object.cpp:
+ (KJS::DateInstance::msToGregorianDateTime):
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Initialize threadMapMutex safely (as already done in ThreadingWin).
+
+ * wtf/ThreadingGtk.cpp:
+ (WTF::threadMapMutex):
+ (WTF::initializeThreading):
+ * wtf/ThreadingPthreads.cpp:
+ (WTF::threadMapMutex):
+ (WTF::initializeThreading):
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ Cache Gregorian date/time structure on DateInstance objects for 1.027x SunSpider speedup
+ (1.65x on date-format-xparb, 1.13x on date-format-tofte).
+
+ * kjs/DateMath.h:
+ (KJS::GregorianDateTime::copyFrom): Added. It presumably makes sense to keep GregorianDateTime
+ Noncopyable, so it's not just operator=.
+
+ * kjs/date_object.h: Added a per-object cache.
+
+ * kjs/date_object.cpp:
+ (KJS::DateInstance::DateInstance):
+ (KJS::DateInstance::msToGregorianDateTime):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ Use the cache when converting.
+
+2008-04-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Implement an abstraction for thread-specific storage, use it to get rid of some static objects.
+
+ SunSpider results were not conclusive, possibly up to 0.2% slowdown.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ Added ThreadSpecific.h
+
+ * wtf/ThreadSpecific.h: Added.
+ (WTF::::ThreadSpecific):
+ (WTF::::~ThreadSpecific):
+ (WTF::::get):
+ (WTF::::set):
+ (WTF::::destroy):
+ (WTF::T):
+ (WTF::::operator):
+ Only implemented for platforms that use pthreads.
+
+ * kjs/CommonIdentifiers.cpp:
+ (KJS::CommonIdentifiers::shared):
+ * kjs/CommonIdentifiers.h:
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading):
+ * kjs/Parser.cpp:
+ (KJS::parser):
+ * kjs/Parser.h:
+ * kjs/identifier.cpp:
+ (KJS::identifierTable):
+ (KJS::literalIdentifierTable):
+ (KJS::Identifier::initializeIdentifierThreading):
+ * kjs/identifier.h:
+ * kjs/lexer.cpp:
+ (KJS::lexer):
+ * kjs/lexer.h:
+ Make static instances per-thread.
+
+2008-04-15 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Adam.
+
+ Add ENABLE_OFFLINE_WEB_APPLICATIONS to FEATURE_DEFINES.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-04-15 Andre Poenitz <andre.poenitz@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fix compilation with Qt namespaces
+
+ Qt can be configured to have all of its classes inside a specified namespaces.
+ This is for example used in plugin/component environments like Eclipse.
+
+ This change makes it possible to let the Qt port compile against a namespaced
+ Qt by the use of macros Qt provides to properly forward declare Qt classes in
+ the namespace.
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+
+2008-04-14 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Adam.
+
+ Don't leak the prototype class.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::create):
+
+2008-04-14 Steve Falkenburg <sfalken@apple.com>
+
+ Fix build.
+
+ * wtf/ThreadingWin.cpp:
+
+2008-04-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ https://bugs.webkit.org/show_bug.cgi?id=18488
+ FastMalloc doesn't release thread-specific data on Windows
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::threadMapMutex): (WTF::initializeThreading): Call threadMapMutex once to initialize the static safely.
+ (WTF::ThreadFunctionInvocation::ThreadFunctionInvocation): Added a structure to wrap thread entry point and arguments.
+ (WTF::wtfThreadEntryPoint): Make sure to end all WTF threads with pthread_exit(), to give pthreads-win32 a chance to call
+ destructors of thread-specific data.
+ (WTF::createThread): Use _beginthreadex instead of CreateThread, because MSDN says so. Also removed a call to CreateEvent,
+ for which I could see no reason at all.
+
+2008-04-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Touched a file to make JavaScriptCore.vcproj rebuild.
+
+ * wtf/MathExtras.h:
+
+2008-04-14 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ Rubberstamped by Alexey Proskuryakov.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Disable
+ the "potentially uninitialized variable" warning for grammar.cpp, as
+ it seems to be incorrect. yylval gets initialized by the lexer, but
+ MSVC doesn't seem to understand this.
+
+2008-04-11 Antti Koivisto <antti@apple.com>
+
+ Reviewed by Maciej.
+
+ Add default hash for pairs of hashable types.
+
+ * wtf/HashFunctions.h:
+ (WTF::PairHash::hash):
+ (WTF::PairHash::equal):
+ (WTF::):
+
+2008-04-11 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Make DateMath.cpp thread safe.
+
+ No measurable change on SunSpider (should be a very small speedup).
+
+ * kjs/DateMath.cpp:
+ (KJS::mimimumYearForDST): (KJS::equivalentYearForDST): Got rid of double caching of the
+ same precomputed value.
+ (KJS::calculateUTCOffset): (KJS::getUTCOffset): Factored actual UTC offset calculation code
+ out of getUTCOffset(), and notification setup into initDateMath().
+
+ (KJS::initDateMath): Added.
+
+ * kjs/DateMath.h:
+ * kjs/InitializeThreading.cpp:
+ (KJS::initializeThreading):
+ Added initDateMath().
+
+2008-04-11 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix.
+
+ * kjs/grammar.y:
+
+2008-04-11 Alexey Proskuryakov <ap@webkit.org>
+
+ Tiger build fix. Forward declaring a union didn't work for whatever reason, make the
+ parameters void*.
+
+ * kjs/grammar.y:
+ * kjs/lexer.cpp:
+ (kjsyylex):
+ (KJS::Lexer::lex):
+ * kjs/lexer.h:
+
+2008-04-11 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ Generate a pure (re-entrant) parser with Bison.
+
+ No change on SunSpider.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+ * kjs/grammar.y:
+ * kjs/lexer.cpp:
+ (kjsyylex):
+ (KJS::Lexer::lex):
+ * kjs/lexer.h:
+ Pass state as function arguments, instead of global data. Don't call lexer() as often as
+ before, as this function is about to become slower due to thread-specific storage.
+
+ * kjs/function.cpp:
+ (KJS::isStrWhiteSpace): Don't call isSeparatorSpace() for 8-bit characters, as these are
+ already taken care of. This is a small speedup, compensating for a small slowdown caused
+ by switching Bison mode.
+
+2008-04-10 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Geoff.
+
+ https://bugs.webkit.org/show_bug.cgi?id=18402
+ REGRESSION: visited element handling is incorrect in nested join/toString calls
+
+ No change on SunSpider total, possibly a tiny improvement (about 0.1%).
+
+ Test: fast/js/array-tostring-and-join.html
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::visitedElements): Store visited elements HashSet here, making it
+ common to toString/toLocalizedString/join again.
+
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ Got rid of static variables. Replaced UString with Vector to avoid O(n^2) behavior and
+ regain performance.
+
+ * wtf/Vector.h:
+ (WTF::::resize):
+ (WTF::::grow):
+ (WTF::::reserveCapacity):
+ (WTF::::append):
+ (WTF::::insert):
+ Added null checks, so that Vector methods don't crash when out of memory. The caller should
+ check that data pointer is not null before proceeding.
+
+2008-04-10 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fix https://bugs.webkit.org/show_bug.cgi?id=18367 and the many dupes.
+ Bug 18367: Crash during celtic kane js speed 2007 test
+
+ GCC 4.2 on x86_64 Linux decided to reorder the local variables in markCurrentThreadConservatively's
+ stack frame. This lead to the range of addresses the collector treated as stack to exclude the
+ contents of volatile registers that markCurrentThreadConservatively forces onto the stack. This was
+ leading to objects being prematurely collected if the only reference to them was via a register at
+ the time a collection occurred.
+
+ The fix for this is to move the calculation of the top of the stack into a NEVER_INLINE function
+ that is called from markCurrentThreadConservatively. This forces the dummy variable we use for
+ determining the top of stack to be in a different stack frame which prevents the compiler from
+ reordering it relative to the registers that markCurrentThreadConservatively forces onto the stack.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::markCurrentThreadConservativelyInternal):
+ (KJS::Collector::markCurrentThreadConservatively):
+ * kjs/collector.h:
+
+2008-04-10 Adam Roben <aroben@apple.com>
+
+ VC++ Express build fix
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj: Link against user32.lib so
+ that anyone who links against WTF.lib will get user32.lib
+ automatically.
+
+2008-04-09 Adam Roben <aroben@apple.com>
+
+ VC++ Express build fix
+
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj: Link against
+ user32.lib.
+
+2008-04-09 Adam Roben <aroben@apple.com>
+
+ Build fix
+
+ * JavaScriptCore.exp: Export isMainThread.
+
+2008-04-09 Adam Roben <aroben@apple.com>
+
+ Build fix
+
+ * wtf/AlwaysInline.h: Make sure to #include Platform.h before using
+ the macros it defines.
+
+2008-04-08 Mark Rowe <mrowe@apple.com>
+
+ Export WTF::initializeThreading() from JavaScriptCore.
+
+ * JavaScriptCore.exp:
+
+2008-04-04 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ First step in implementing the "split window"
+
+ - Add a GlobalThisValue to ExecState which should be used
+ in places that used to implement the "use the global object
+ as this if null" rule.
+ - Factor out lookupGetter/lookupSetter into virtual methods
+ on JSObject so that they can be forwarded.
+ - Make defineGetter/defineSetter virtual methods for the same
+ reason.
+ - Have PrototypeReflexiveFunction store the globalObject used
+ to create it so that it can be used to get the correct thisObject
+ for eval.
+
+ * API/JSObjectRef.cpp:
+ (JSObjectCallAsFunction):
+ * JavaScriptCore.exp:
+ * kjs/Activation.h:
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ (KJS::GlobalExecState::GlobalExecState):
+ * kjs/ExecState.h:
+ (KJS::ExecState::globalThisValue):
+ * kjs/ExecStateInlines.h:
+ (KJS::ExecState::ExecState):
+ (KJS::FunctionExecState::FunctionExecState):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ (KJS::JSGlobalObject::toGlobalObject):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
+ (KJS::JSGlobalObject::JSGlobalObject):
+ * kjs/array_instance.cpp:
+ (KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
+ (KJS::compareWithCompareFunctionForQSort):
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncSort):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::ActivationImp::toThisObject):
+ (KJS::globalFuncEval):
+ (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
+ (KJS::PrototypeReflexiveFunction::mark):
+ * kjs/function.h:
+ (KJS::PrototypeReflexiveFunction::cachedGlobalObject):
+ * kjs/function_object.cpp:
+ (KJS::functionProtoFuncApply):
+ (KJS::functionProtoFuncCall):
+ * kjs/nodes.cpp:
+ (KJS::ExpressionNode::resolveAndCall):
+ (KJS::FunctionCallValueNode::evaluate):
+ (KJS::LocalVarFunctionCallNode::inlineEvaluate):
+ (KJS::ScopedVarFunctionCallNode::inlineEvaluate):
+ (KJS::FunctionCallBracketNode::evaluate):
+ (KJS::FunctionCallDotNode::inlineEvaluate):
+ * kjs/object.cpp:
+ (KJS::JSObject::call):
+ (KJS::JSObject::put):
+ (KJS::tryGetAndCallProperty):
+ (KJS::JSObject::lookupGetter):
+ (KJS::JSObject::lookupSetter):
+ (KJS::JSObject::toThisObject):
+ (KJS::JSObject::toGlobalObject):
+ (KJS::JSObject::fillGetterPropertySlot):
+ * kjs/object.h:
+ * kjs/object_object.cpp:
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ * kjs/string_object.cpp:
+ (KJS::replace):
+
+2008-04-08 Brady Eidson <beidson@apple.com>
+
+ Encourage Windows to rebuild - AGAIN...
+
+ * kjs/DateMath.cpp:
+
+2008-04-08 Adam Roben <aroben@apple.com>
+
+ Mac build fix
+
+ * JavaScriptCore.exp: Add callOnMainThread, and sorted the list.
+
+2008-04-08 Brady Eidson <beidson@apple.com>
+
+ Rubberstamped by Adam Roben
+
+ Touch some files to *strongly* encourage Windows to rebuilt with DOM_STORAGE enabled
+
+ * kjs/DateMath.cpp:
+
+2008-04-08 Adam Roben <aroben@apple.com>
+
+ Move callOnMainThread to WTF
+
+ Reviewed by Alexey Proskuryakov.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ Added new files.
+
+ * wtf/MainThread.cpp:
+ * wtf/MainThread.h:
+ * wtf/gtk/MainThreadGtk.cpp:
+ * wtf/mac/MainThreadMac.mm:
+ * wtf/qt/MainThreadQt.cpp:
+ * wtf/win/MainThreadWin.cpp:
+ * wtf/wx/MainThreadWx.cpp:
+ Moved here from WebCore/platform. Replaced all instances of "WebCore"
+ with "WTF".
+
+ * kjs/bool_object.cpp: Touched to force JavaScriptCore.vcproj to
+ build.
+ to the WTF namespace.
+ * wtf/ThreadingWin.cpp:
+ (WTF::initializeThreading): Call initializeMainThread.
+
+2008-04-07 Brady Eidson <beidson@apple.com>
+
+ Add "ENABLE_DOM_STORAGE" to keep in sync with the rest of the project
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-04-07 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * wtf/ThreadingWin.cpp: Back out some changes I didn't mean to land.
+
+2008-04-07 Adam Roben <aroben@apple.com>
+
+ Add WTF::isMainThread
+
+ Reviewed by Alexey Proskuryakov.
+
+ * wtf/Threading.h: Declare the new function.
+ * wtf/ThreadingGtk.cpp:
+ (WTF::initializeThreading): Initialize the main thread identifier.
+ (WTF::isMainThread): Added.
+ * wtf/ThreadingNone.cpp: Ditto ThreadingGtk.cpp.
+ (WTF::initializeThreading):
+ (WTF::isMainThread):
+ * wtf/ThreadingPthreads.cpp: Ditto.
+ (WTF::initializeThreading):
+ (WTF::isMainThread):
+ * wtf/ThreadingWin.cpp: Ditto.
+ (WTF::initializeThreading):
+ (WTF::isMainThread):
+
+2008-04-06 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Make UString thread-safe.
+
+ No change on SunSpider total, although individual tests have changed a lot, up to 3%.
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreading): Call UString::null() to initialize
+ a static.
+
+ * kjs/identifier.cpp:
+ (KJS::CStringTranslator::translate):
+ (KJS::UCharBufferTranslator::translate):
+ Use "true" for a boolean value instead of 1, because it's C++.
+
+ * kjs/ustring.h:
+ (KJS::CString::adopt): Added a method to create from a char* buffer without copying.
+ (KJS::UString::Rep::ref): Removed an assertion for JSLock::lockCount, as it's no longer
+ necessary to hold JSLock when working with strings.
+ (KJS::UString::Rep::deref): Ditto.
+ (KJS::UString::Rep::isStatic): Added a field to quickly determine that this is an empty
+ or null static string.
+
+ * kjs/ustring.cpp:
+ (KJS::): Removed normalStatBufferSize and statBufferSize, as there is no reason to have such
+ an advanced implementation of a debug-only ascii() method. Removed a long-obsolete comment
+ about UChar.
+ (KJS::UString::Rep::createCopying): Removed an assertion for JSLock::lockCount.
+ (KJS::UString::Rep::create): Ditto.
+ (KJS::UString::Rep::destroy): Ditto. Do not do anything for static null and empty strings,
+ as refcounting is not reliable for those. Reordered branches for a noticeable speed gain -
+ apparently this functiton is hot enough for SunSpider to see an effect from this!
+ (KJS::UString::null): Moved a star, added a comment.
+ (KJS::UString::cstring): Reimplemented to not call ascii(), which is not thread-safe.
+ (KJS::UString::ascii): Simplified statBuffer handling logic.
+ (KJS::UString::toDouble): Use cstring() instead of ascii().
+
+2008-04-02 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Ensure that debug symbols are generated for x86_64 and ppc64 builds.
+
+ * Configurations/Base.xcconfig:
+
+2008-04-01 Christian Dywan <christian@imendio.com>
+
+ Build fix for GCC 4.3.
+
+ * wtf/unicode/icu/CollatorICU.cpp: include string.h
+
+2008-04-01 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Darin.
+
+ Turn off using 64-bit arithmetic on 32-bit hardware, as dtoa own code is faster than
+ compiler-provided emulation.
+
+ 1% speedup on Acid3 test 26.
+
+ * kjs/dtoa.cpp:
+
+2008-04-01 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Make MathExtras.h thread safe.
+
+ * kjs/math_object.cpp:
+ (KJS::mathProtoFuncRandom): If threading is enabled, rely on initializeThreading to call
+ wtf_random_init().
+
+ * wtf/Threading.h:
+ * wtf/ThreadingGtk.cpp:
+ (WTF::initializeThreading):
+ * wtf/ThreadingNone.cpp:
+ (WTF::initializeThreading):
+ * wtf/ThreadingPthreads.cpp:
+ (WTF::initializeThreading):
+ * wtf/ThreadingWin.cpp:
+ (WTF::initializeThreading):
+ Call wtf_random_init(); made the function non-inline to avoid having to include too many
+ headers in Threading.h.
+
+2008-03-31 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Make matching of regexps using ^ much faster
+ http://bugs.webkit.org/show_bug.cgi?id=18086
+
+ * pcre/pcre_compile.cpp:
+ (compileBranch):
+ (branchNeedsLineStart):
+ * pcre/pcre_exec.cpp:
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2008-03-29 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ <rdar://problem/5829556> REGRESSION: Leak in KJS::initializeThreading()
+
+ * kjs/InitializeThreading.cpp: (KJS::initializeThreading): There is no guarantee that
+ initializeThreading() is called only once; check that the mutex hasn't been already allocated.
+
+2008-03-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Bug 17924: Crash in KJS::ConstDeclNode::evaluate with |with| and |const|
+ <http://bugs.webkit.org/show_bug.cgi?id=17924>
+ <rdar://problem/5806933>
+
+ It turns out this is trivially avoidable if we just match firefox's
+ semantics and ensure that an assignment in a const declaration always
+ writes to the variable object.
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::handleSlowCase):
+
+2008-03-28 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Sam Weinig.
+
+ Fix a dtoa thread safety issue.
+
+ WebCore can call kjs_strtod without holding JS lock, but we didn't have thread safety
+ compiled in for dtoa.
+
+ This is a 0.5% regression on SunSpider, which Sam Weinig has volunteered to cover with
+ his recent improvement.
+
+ * kjs/dtoa.cpp:
+ (Bigint::Balloc):
+ (Bigint::Bfree):
+ Changed to use fastMalloc/fastDelete - they are much faster than the dtoa custom version was
+ in the presence of locking (but somewhat slower in single-threaded case).
+ (Bigint::pow5mult): Got rid of the dreaded double-checked locking anti-pattern (had to
+ restructure the code to avoid significant performance implications).
+ (Bigint::lshift): Rewrote to avoid an allocation, if possible.
+
+ (Bigint::rv_alloc):
+ (Bigint::kjs_freedtoa):
+ (Bigint::kjs_dtoa):
+ Check for USE(MULTIPLE_THREADS), not dtoa legacy MULTIPLE_THREADS.
+
+ * kjs/InitializeThreading.cpp: Added.
+ (KJS::initializeThreading):
+ * kjs/InitializeThreading.h: Added.
+ Initialize threading at KJS level, if enabled.
+
+ * kjs/dtoa.h: Expose dtoa mutex for KJS::initializeThreading.
+
+ * kjs/testkjs.cpp: (kjsmain): Call initializeThreading.
+
+ * JavaScriptCore.exp: Export KJS::initializeThreading.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCoreSources.bkl:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ Added InitializeThreading.{h,cpp}.
+
+ * wtf/Threading.h: Removed a using directive for WTF::initializeThreading - it is only
+ to be called from KJS::initializeThreading, and having it in the global namespace is useless.
+
+2008-03-28 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Darin
+
+ Export Unicode/UTF8.h and convertUTF16ToUTF8() for more flexible conversion in WebCore
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-03-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ <rdar://problem/5826236> Regular expressions with large nested repetition counts can have their
+ compiled length calculated incorrectly.
+
+ * pcre/pcre_compile.cpp:
+ (multiplyWithOverflowCheck):
+ (calculateCompiledPatternLength): Check for overflow when dealing with nested repetition counts
+ and bail with an error rather than returning incorrect results.
+
+2008-03-26 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Brady Eidson.
+
+ Update FEATURE_DEFINES to be consistent with the other locations in which it is defined.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-03-26 Adam Roben <aroben@apple.com>
+
+ Fix Bug 18060: Assertion failure (JSLock not held) beneath
+ JSCallbackObject<Base>::toString
+
+ <http://bugs.webkit.org/show_bug.cgi?id=18060>
+
+ Reviewed by Geoff Garen.
+
+ Bug fix:
+
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::JSCallbackObject<Base>::toString): Make the DropAllLocks
+ instance only be in scope while calling convertToType.
+
+ Test:
+
+ * API/testapi.c:
+ (MyObject_convertToType): Implement type conversion to string.
+ * API/testapi.js: Add a test for type conversion to string.
+
+2008-03-26 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * kjs/array_instance.cpp: Touched this.
+ * wtf/HashFunctions.h:
+ (WTF::intHash): Added 8- and 16-bit versions of intHash.
+
+2008-03-26 Adam Roben <aroben@apple.com>
+
+ Force JSC headers to be copied by touching a file
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::getPropertyNames):
+
+2008-03-26 Adam Roben <aroben@apple.com>
+
+ Windows build fix after r31324
+
+ Written with Darin.
+
+ Added HashTable plumbing to support using wchar_t as a key type.
+
+ * wtf/HashFunctions.h:
+ * wtf/HashTraits.h:
+ (WTF::):
+
+2008-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - JSC part of fix for "SVG multichar glyph matching matches longest instead of first (affects Acid3 test 79)"
+ http://bugs.webkit.org/show_bug.cgi?id=18118
+
+ * wtf/HashFunctions.h:
+ (WTF::):
+ * wtf/HashTraits.h:
+ (WTF::):
+
+2008-03-26 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Cache C string identifiers by address, not value, assuming that C strings can only
+ be literals.
+
+ 1% speedup on Acid3 test 26.
+
+ * kjs/identifier.cpp:
+ (KJS::literalIdentifierTable):
+ (KJS::Identifier::add):
+ Added a new table to cache UString::Reps created from C strings by address. Elements are
+ never removed from this cache, as only predefined identifiers can get there.
+
+ * kjs/identifier.h:
+ (KJS::Identifier::Identifier): Added a warning.
+
+2008-03-26 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Maciej.
+
+ An assertion was failing in function-toString-object-literals.html when parsing 1e-500.
+ The condition existed before, and got uncovered by turning compiled-out dtoa checks into
+ ASSERTs.
+
+ The assertion was verifying that the caller wasn't constructing a Bigint from 0.
+ This might have had some reason behind it originally, but I couldn't find any,
+ and this doesn't look like a reasonable requirement.
+
+ * kjs/dtoa.cpp: (d2b): Removed the assertion (two copies in different code paths).
+
+2008-03-25 Adam Roben <aroben@apple.com>
+
+ Fix Bug 18077: Integrate testapi.c into the Windows build
+
+ <http://bugs.webkit.org/show_bug.cgi?id=18077>
+
+ Reviewed by Steve Falkenburg.
+
+ * JavaScriptCore.vcproj/testapi/testapi.vcproj: Added.
+
+2008-03-25 Adam Roben <aroben@apple.com>
+
+ Make testapi.c compile under MSVC
+
+ Currently you must compile testapi.c as C++ code since MSVC does not
+ support many C features that GCC does.
+
+ Reviewed by Steve Falkenburg.
+
+ * API/testapi.c:
+ (nan): Added an implementation of this for MSVC.
+ (assertEqualsAsUTF8String): Use malloc instead of dynamically-sized
+ stack arrays.
+ (assertEqualsAsCharactersPtr): Ditto.
+ (print_callAsFunction): Ditto.
+ (main): Ditto, and explicitly cast from UniChar* to JSChar*.
+
+2008-03-25 Adam Roben <aroben@apple.com>
+
+ Stop using JavaScriptCore's custom stdbool.h and stdint.h on Windows
+
+ We can't remove the os-win32 directory yet because other ports (at
+ least wx) are still relying on it.
+
+ Reviewed by Steve Falkenburg.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ - Made all the include paths match the one for the Debug
+ configuration (these got out of sync in r30797)
+ - Removed os-win32 from the include path
+ - Removed os-win32 from the directories we copy to $WebKitOutputDir.
+ - Removed stdint.h from the project
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ Delete the files that we may have previously copied from the os-win32
+ directory.
+
+2008-03-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix.
+
+ * kjs/dtoa.cpp: Include stdint.h.
+
+2008-03-25 Alexey Proskuryakov <ap@webkit.org>
+
+ Rubber-stamped by Darin.
+
+ Cleanup dtoa.cpp style.
+
+ * kjs/dtoa.cpp:
+ (Bigint::Balloc):
+ (Bigint::Bfree):
+ (Bigint::multadd):
+ (Bigint::s2b):
+ (Bigint::hi0bits):
+ (Bigint::lo0bits):
+ (Bigint::i2b):
+ (Bigint::mult):
+ (Bigint::pow5mult):
+ (Bigint::lshift):
+ (Bigint::cmp):
+ (Bigint::diff):
+ (Bigint::ulp):
+ (Bigint::b2d):
+ (Bigint::d2b):
+ (Bigint::ratio):
+ (Bigint::):
+ (Bigint::match):
+ (Bigint::hexnan):
+ (Bigint::kjs_strtod):
+ (Bigint::quorem):
+ (Bigint::rv_alloc):
+ (Bigint::nrv_alloc):
+ (Bigint::kjs_freedtoa):
+ (Bigint::kjs_dtoa):
+ * kjs/dtoa.h:
+
+2008-03-24 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - convert a JavaScript immediate number to a string more efficiently
+
+ 2% speedup of Acid3 test 26
+
+ * kjs/JSImmediate.cpp:
+ (KJS::JSImmediate::toString): Take advantage of the fact that all immediate
+ numbers are integers, and use the faster UString function for formatting integers
+ instead of the slower one that works for floating point. I think this is a leftover
+ from when immediate numbers were floating point.
+
+2008-03-23 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=18048
+ The "thisObject" parameter to JSEvaluateScript is not used properly
+
+ Making passing a thisObject to JSEvaluateScript actually set the thisObject of the created
+ ExecState.
+
+ * API/testapi.c:
+ (main): Add tests for setting the thisObject when calling JSEvaluateScript.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState): Assign the thisObject to m_thisValue and remove the comment.
+
+2008-03-22 Jesse Ruderman <jruderman@gmail.com>
+
+ Reviewed by Sam Weinig. Landed by eseidel.
+
+ Make testkjs flush stdout after printing.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/testkjs.cpp:
+ (functionPrint):
+
+2008-03-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Optimise lookup of Math, undefined, NaN and Infinity
+
+ Added a method to JSVariableObject to allow us to inject DontDelete properties
+ into the symbol table and localStorage. This results in a 0.4% progression in
+ SunSpider, with a 8% gain in math-partial-sums.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableInsert):
+
+2008-03-21 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ Global properties that use LocalStorage are not correctly listed as enumerable.
+
+ The problem was caused by JSObject::getPropertyAttributes not being aware
+ of the JSVariableObject SymbolTable. The fix is to make getPropertyAttributes
+ virtual and override in JSVariableObject. This does not produce any performance
+ regression.
+
+ * JavaScriptCore.exp:
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames):
+ (KJS::JSVariableObject::getPropertyAttributes):
+ * kjs/JSVariableObject.h:
+ * kjs/object.h:
+
+2008-03-21 Arkadiusz Miskiewicz <arekm@maven.pl>
+
+ Webkit does not build on linux powerpc
+
+ <http://bugs.webkit.org/show_bug.cgi?id=17019>
+
+ Reviewed by David Kilzer.
+
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::Unlock):
+
+2008-03-21 Rodney Dawes <dobey@wayofthemonkey.com>
+
+ Reviewed by Holger.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17981
+
+ Add javascriptcore_cppflags to Programs_minidom_CPPFLAGS.
+
+ * GNUmakefile.am:
+
+2008-03-21 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Consolidate static identifier initializers within CommonIdentifiers.
+
+ No reliably measurable change on SunSpider; maybe a tiny improvement (within 0.2%).
+
+ * kjs/CommonIdentifiers.h: Added static identifiers that were lazily initialized
+ throughout the code.
+
+ * kjs/date_object.cpp:
+ (KJS::DateObjectImp::DateObjectImp):
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ Use the values from CommonIdentifiers.
+
+ * kjs/lookup.h: Caching the identifier in a static wasn't a win on SunSpider, removed it.
+
+ * kjs/value.h:
+ (KJS::jsNaN): We already have a shared NaN value, no need for a duplicate here.
+
+ * wtf/MathExtras.h:
+ (wtf_atan2): Having local variables for numeric_limits constants is good for readability,
+ but there is no reason to keep them static.
+
+ * JavaScriptCore.exp: Don't needlessly export JSGlobalObject::s_head.
+
+2008-03-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Fix for leak introduced by inline ScopeChainNode use
+
+ To avoid any extra branches when managing an inline ScopeChainNode
+ in the ScopeChain the inline node gets inserted with a refcount of
+ 2. This meant than when the ScopeChain was destroyed the ScopeChainNodes
+ above the inline node would be leaked.
+
+ We resolve this by manually popping the inline node in the
+ FunctionExecState destructor.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/ExecStateInlines.h:
+ (KJS::FunctionExecState::~FunctionExecState):
+ * kjs/scope_chain.h:
+ (KJS::ScopeChain::popInlineScopeNode):
+
+2008-03-20 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Ensure that the defines in FEATURE_DEFINES are sorted so that they will match the default settings of build-webkit.
+ This will prevent the world from being rebuilt if you happen to switch between building in Xcode and with build-webkit on the
+ command-line.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-03-20 David Krause <david.krause@gmail.com>
+
+ Reviewed by David Kilzer.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17923
+ Bug 17923: ARM platform endian defines inaccurate
+
+ * wtf/Platform.h:
+ Replaced !defined(__ARMEL__) check with !defined(__VFP_FP__)
+ for PLATFORM(MIDDLE_ENDIAN)
+
+2008-03-20 Maciej Stachowiak <mjs@apple.com>
+
+ - fix build
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: install Activation.h as private
+
+2008-03-20 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - reduce function call overhead for 1.014x speedup on SunSpider
+
+ I moved some functions from ExecState.cpp to ExecStateInline.h and
+ from JSGlobalObject.cpp to JSGlobalObject.h, and declared them
+ inline; machine function call overhead for these was hurting JS
+ funcion call overhead.
+
+ * kjs/ExecState.cpp:
+ * kjs/ExecStateInlines.h: Added.
+ (KJS::ExecState::ExecState):
+ (KJS::ExecState::~ExecState):
+ (KJS::FunctionExecState::FunctionExecState):
+ (KJS::FunctionExecState::~FunctionExecState):
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::pushActivation):
+ (KJS::JSGlobalObject::checkActivationCount):
+ (KJS::JSGlobalObject::popActivation):
+ * kjs/function.cpp:
+
+2008-03-19 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Avoid heap allocating the root scope chain node for eval and closure free functions
+
+ Maciej suggested using an inline ScopeChainNode for functions that don't use eval
+ or closures as they are unable to ever capture the scope chain. This gives us a 2.4%
+ win in sunspider, a 15% win in controlflow-recursive, and big (>5%) wins in a number
+ of other tests.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/ExecState.h:
+ * kjs/scope_chain.h:
+ (KJS::ScopeChain::push):
+
+2008-03-19 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fix release build.
+
+ * kjs/JSGlobalObject.cpp: Add missing #include.
+
+2008-03-19 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Anders Carlsson.
+
+ Fix for <rdar://problem/5785694>
+ Crash occurs at KJS::Collector::collect() when loading web clip widgets with a PAC file
+
+ Make the activeExecStates stack per JSGlobalObject instead of static to ensure
+ thread safety.
+
+ * JavaScriptCore.exp:
+ * kjs/ExecState.cpp:
+ (KJS::InterpreterExecState::InterpreterExecState):
+ (KJS::InterpreterExecState::~InterpreterExecState):
+ (KJS::EvalExecState::EvalExecState):
+ (KJS::EvalExecState::~EvalExecState):
+ (KJS::FunctionExecState::FunctionExecState):
+ (KJS::FunctionExecState::~FunctionExecState):
+ * kjs/ExecState.h:
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::mark):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::activeExecStates):
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ (KJS::Collector::reportOutOfMemoryToAllExecStates): Iterate all JSGlobalObjects and report
+ the OutOfMemory condition to all the ExecStates in each.
+
+2008-03-19 Jasper Bryant-Greene <jasper@unix.geek.nz>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17941
+ Bug 17941: C++-style comments in JavaScriptCore API
+
+ * API/JSBase.h:
+ Remove C++-style comments from public JavaScriptCore API, replacing
+ with standard C90 block comments.
+
+2008-03-19 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17939
+ Bug 17939: Crash decompiling "const a = 1, b;"
+
+ * kjs/nodes2string.cpp:
+ (KJS::ConstDeclNode::streamTo): Null-check the correct variable.
+
+2008-03-18 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ Bug 17929: Incorrect decompilation with |const|, comma
+ http://bugs.webkit.org/show_bug.cgi?id=17929
+
+ There were actually two bugs here. First we weren't correctly handling const
+ nodes with multiple declarations. The second issue was caused by us not
+ giving the correct precedence to the initialisers.
+
+ * kjs/nodes2string.cpp:
+ (KJS::ConstDeclNode::streamTo):
+
+2008-03-18 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - Speed up JavaScript built-in properties by changing the
+ hash table to take advantage of the identifier objects
+
+ 5% speedup for Acid3 test 26
+
+ * JavaScriptCore.exp: Updated.
+ * kjs/create_hash_table: Compute size of hash table large enough so that there
+ are no collisions, but don't generate the hash table.
+ * kjs/identifier.h: Made the add function that returns a PassRefPtr public.
+ * kjs/lexer.cpp:
+ (KJS::Lexer::lex): Updated for change to HashTable interface.
+ * kjs/lookup.cpp:
+ (KJS::HashTable::changeKeysToIdentifiers): Added. Finds the identifier for
+ each property so the equality comparision can be done with pointer comparision.
+ * kjs/lookup.h: Made the key be a union of char* with UString::Rep* so it can
+ hold identifiers. Added a keysAreIdentifiers flag to the HashTable. Changed
+ the Lookup functions to be member functions of HashTable instead.
+ * kjs/object.cpp:
+ (KJS::JSObject::deleteProperty): Update for change to HashTable.
+ (KJS::JSObject::findPropertyHashEntry): Ditto.
+ (KJS::JSObject::getPropertyAttributes): Ditto.
+ (KJS::JSObject::getPropertyNames): Ditto.
+
+2008-03-18 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17925 and http://bugs.webkit.org/show_bug.cgi?id=17927.
+ - Bug 17925: Crash in KJS::JSObject::put after setting this.__proto__
+ - Bug 17927: Hang after attempting to create circular __proto__
+
+ * kjs/object.cpp:
+ (KJS::JSObject::put): Silently ignore attempts to set __proto__ to a non-object, non-null value.
+ Return after setting the exception when an attempt to set a cyclic __proto__ is detected so that
+ the cyclic value is not set.
+
+2008-03-18 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - inline ActivationImp::init for 0.8% SunSpider speedup
+
+ * kjs/Activation.h:
+ (KJS::ActivationImp::init): Moved here from function.cpp
+ * kjs/function.cpp:
+
+2008-03-18 Simon Hausmann <hausmann@webkit.org>
+
+ Fix the Qt build.
+
+ Including config.h like in the other .cpp files gets the #ifdeffery
+ correct for rand_s.
+
+ * kjs/JSWrapperObject.cpp:
+
+2008-03-17 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ JavaScriptCore changes to support a WebCore speedup.
+
+ * JavaScriptCore.exp: Export the UString::Rep::computeHash function.
+ * wtf/HashSet.h: Added a find and contains function that take a translator,
+ like the add function.
+
+2008-03-18 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - a few micro-optimizations for 1.2% SunSpider speedup
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction): check for Return completion before Throw,
+ it is more likely.
+ * kjs/object.cpp:
+ (KJS::JSObject::put): When walking prototype chain, instead of
+ checking isObject (a virtual call), compare to jsNull (compare to
+ a constant) since null is the only non-object that can be in a
+ prototype chain.
+
+2008-03-17 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Optimise multi-scope function call resolution
+
+ Refactor multiscope variable resolution and use to add
+ optimised FunctionCallResolveNode subclasses.
+
+ 2.6% gain in sunspider performance, *25%* gain in controlflow-recursive
+
+ * kjs/nodes.cpp:
+ (KJS::getSymbolTableEntry):
+ (KJS::ResolveNode::optimizeVariableAccess):
+ (KJS::getNonLocalSymbol):
+ (KJS::ExpressionNode::resolveAndCall):
+ (KJS::FunctionCallResolveNode::optimizeVariableAccess):
+ (KJS::FunctionCallResolveNode::inlineEvaluate):
+ (KJS::ScopedVarFunctionCallNode::inlineEvaluate):
+ (KJS::ScopedVarFunctionCallNode::evaluate):
+ (KJS::ScopedVarFunctionCallNode::evaluateToNumber):
+ (KJS::ScopedVarFunctionCallNode::evaluateToBoolean):
+ (KJS::ScopedVarFunctionCallNode::evaluateToInt32):
+ (KJS::ScopedVarFunctionCallNode::evaluateToUInt32):
+ (KJS::NonLocalVarFunctionCallNode::inlineEvaluate):
+ (KJS::NonLocalVarFunctionCallNode::evaluate):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToNumber):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToBoolean):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToInt32):
+ (KJS::NonLocalVarFunctionCallNode::evaluateToUInt32):
+ * kjs/nodes.h:
+ (KJS::ScopedVarFunctionCallNode::):
+ (KJS::NonLocalVarFunctionCallNode::):
+
+2008-03-17 David Kilzer <ddkilzer@apple.com>
+
+ Don't define PLATFORM(MIDDLE_ENDIAN) on little endian ARM.
+
+ Reviewed by Darin.
+
+ See <http://bugs.webkit.org/show_bug.cgi?id=15416#c13>.
+
+ * wtf/Platform.h: Added check for !defined(__ARMEL__) when defining
+ PLATFORM(MIDDLE_ENDIAN).
+
+2008-03-17 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff, Darin and Weinig.
+
+ Add fast multi-level scope lookup
+
+ Add logic and AST nodes to provide rapid variable resolution across
+ static scope boundaries. This also adds logic that allows us to skip
+ any static scopes that do not contain the variable to be resolved.
+
+ This results in a ~2.5% speedup in SunSpider, and gives a 25-30% speedup
+ in some simple and ad hoc closure and global variable access tests.
+
+ * JavaScriptCore.exp:
+ * kjs/Activation.h:
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSGlobalObject.h:
+ * kjs/JSVariableObject.cpp:
+ * kjs/JSVariableObject.h:
+ * kjs/function.cpp:
+ (KJS::ActivationImp::isDynamicScope):
+ * kjs/nodes.cpp:
+ (KJS::ResolveNode::optimizeVariableAccess):
+ (KJS::ScopedVarAccessNode::inlineEvaluate):
+ (KJS::ScopedVarAccessNode::evaluate):
+ (KJS::ScopedVarAccessNode::evaluateToNumber):
+ (KJS::ScopedVarAccessNode::evaluateToBoolean):
+ (KJS::ScopedVarAccessNode::evaluateToInt32):
+ (KJS::ScopedVarAccessNode::evaluateToUInt32):
+ (KJS::NonLocalVarAccessNode::inlineEvaluate):
+ (KJS::NonLocalVarAccessNode::evaluate):
+ (KJS::NonLocalVarAccessNode::evaluateToNumber):
+ (KJS::NonLocalVarAccessNode::evaluateToBoolean):
+ (KJS::NonLocalVarAccessNode::evaluateToInt32):
+ (KJS::NonLocalVarAccessNode::evaluateToUInt32):
+ (KJS::IfElseNode::optimizeVariableAccess):
+ (KJS::ScopeNode::optimizeVariableAccess):
+ * kjs/nodes.h:
+ (KJS::ScopedVarAccessNode::):
+ (KJS::NonLocalVarAccessNode::):
+ * kjs/object.h:
+
+ 2008-03-16 weihongzeng <weihong.zeng@hotmail.com>
+
+ Reviewed by Darin Adler.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15416
+ Add support for mixed-endian processors
+
+ * kjs/dtoa.cpp: Add IEEE_ARM, triggered by PLATFORM(MIDDLE_ENDIAN).
+
+2008-03-16 Kevin Ollivier <kevino@theolliviers.com>
+
+ Rubber stamped by Darin.
+
+ Add set-webkit-configuration support for wx port, and centralize
+ build dir location setting.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17790
+
+ * jscore.bkl:
+
+2008-03-14 Steve Falkenburg <sfalken@apple.com>
+
+ PGO build fixes.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-03-14 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Add logic to track whether a function uses a locally scoped eval or requires a closure
+
+ Now that we limit eval we can track those uses of eval that operate
+ in the local scope and functions that require a closure. We track
+ this information during initial parsing to avoid yet another tree
+ walk.
+
+ * JavaScriptCore.exp:
+ * kjs/NodeInfo.h:
+ * kjs/Parser.cpp:
+ (KJS::Parser::didFinishParsing):
+ * kjs/Parser.h:
+ (KJS::Parser::parse):
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ScopeNode::ScopeNode):
+ (KJS::ProgramNode::ProgramNode):
+ (KJS::ProgramNode::create):
+ (KJS::EvalNode::EvalNode):
+ (KJS::EvalNode::create):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::FunctionBodyNode::create):
+ * kjs/nodes.h:
+ (KJS::ScopeNode::):
+ (KJS::ScopeNode::usesEval):
+ (KJS::ScopeNode::needsClosure):
+
+2008-03-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Fixed another problem with Vector::shrinkCapacity.
+
+ moveOverlapping isn't good enough for the case where the buffer hasn't
+ changed, because it still destroys the contents of the buffer.
+
+ * wtf/Vector.h:
+ (WTF::::shrinkCapacity): Changed to explicitly check whether the call
+ to allocateBuffer produced a new buffer. If it didn't, there's no need
+ to move.
+
+2008-03-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Fixed a few problems with Vector::shrinkCapacity that I noticed in testing.
+
+ * wtf/Vector.h:
+ (WTF::VectorBufferBase::deallocateBuffer): Clear our m_buffer pointer
+ when we deallocate m_buffer, in case we're not asked to reallocate a new
+ buffer. (Otherwise, we would use a stale m_buffer if we were asked to
+ perform any operations after shrinkCapacity was called.)
+
+ (WTF::VectorBuffer::allocateBuffer): Made VectorBuffer with inline
+ capacity aware that calls to allocateBuffer might be shrinks, rather
+ than grows, so we shouldn't allocate a new buffer on the heap unless
+ our inline buffer is too small.
+
+ (WTF::::shrinkCapacity): Call resize() instead of just setting m_size,
+ so destructors run. Call resize before reallocating the buffer to make
+ sure that we still have access to the objects we need to destroy. Call
+ moveOverlapping instead of move, since a call to allocateBuffer on an
+ inline buffer may produce identical storage.
+
+2008-03-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Get rid of a localime() call on platforms that have better alternatives.
+
+ * kjs/DateMath.h: Added getLocalTime();
+
+ * kjs/DateMath.cpp:
+ (KJS::getLocalTime):
+ (KJS::getDSTOffsetSimple):
+ Implementation moved from getDSTOffsetSimple().
+
+ * kjs/date_object.cpp:
+ (KJS::DateObjectImp::callAsFunction): Switched to getLocalTime().
+
+2008-03-14 David D. Kilzer <ddkilzer@apple.com>
+
+ Unify concept of enabling the Mac Java bridge.
+
+ Reviewed by Darin and Anders.
+
+ * wtf/Platform.h: Define ENABLE_MAC_JAVA_BRIDGE here.
+
+2008-03-13 Mark Mentovai <mark@moxienet.com>
+
+ Reviewed by eseidel. Landed by eseidel.
+
+ * wtf/FastMalloc.cpp: #include <wtf/HashSet.h> outside of any
+ namespaces.
+
+2008-03-13 Mark Mentovai <mark@moxienet.com>
+
+ Reviewed by eseidel. Landed by eseidel.
+
+ * pcre/pcre_exec.cpp: Fix misnamed variable, allowing -DDEBUG build
+ to succeed.
+ * wtf/ThreadingPthreads.cpp: #include <sys/time.h> for gettimeofday
+ in non-pch build.
+
+2008-03-13 Steve Falkenburg <sfalken@apple.com>
+
+ PGO build fixes.
+
+ Disable PGO for normal release builds.
+ Added work-in-progress Release_PGOInstrument/Release_PGOOptimize targets.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-03-13 Beth Dakin <bdakin@apple.com>
+
+ Reviewed by Geoff.
+
+ Adding new functionality to Vector. Currently all of the shrink and
+ resize functions on Vector only shrink the size of the Vector, not
+ the capacity. For the Vector to take up as little memory as
+ possible, though, it is necessary to be able to shrink the capacity
+ as well. So this patch adds that functionality.
+
+ I need this for a speed up I am working on, and Geoff wants to use
+ it in a speed up he is working on also, so he asked me to commit it
+ now.
+
+ * wtf/Vector.h:
+ (WTF::VectorBufferBase::allocateBuffer):
+ (WTF::::shrinkCapacity):
+
+2008-03-13 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ Attempt at fixing the Qt/Windows build bot. Quote using double-quotes
+ instead of single quotes.
+
+ * pcre/dftables:
+
+2008-03-12 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+
+2008-03-12 Alp Toker <alp@atoker.com>
+
+ Another autotools testkjs build fix attempt.
+
+ * GNUmakefile.am:
+
+2008-03-12 Alp Toker <alp@atoker.com>
+
+ Attempt to fix the autotools testkjs build on systems with
+ non-standard include paths.
+
+ * GNUmakefile.am:
+
+2008-03-11 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5787743> REGRESSION: Crash at WTF::Collator::CreateCollator() running fast/js/kde/StringObject.html on Windows
+
+ * wtf/unicode/icu/CollatorICU.cpp:
+ (WTF::Collator::createCollator): Check for null (== user default) m_locale before calling strcmp.
+
+2008-03-11 Steve Falkenburg <sfalken@apple.com>
+
+ Disable LTCG/PGO for grammar.cpp and nodes.cpp.
+ PGO on these files causes us to hang.
+
+ Copy newer vsprops files from relative WebKitLibraries path to environment variable based path.
+
+ Reviewed by Oliver.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+
+2008-03-10 Darin Adler <darin@apple.com>
+
+ - Windows build fix
+
+ * kjs/function.cpp: (KJS::decode): Initialize variable.
+
+2008-03-10 Brent Fulgham <bfulgham@gmail.com>
+
+ Windows build fix
+
+ Reviewed by Adam.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ Set the PATH to include Cygwin before running touch.
+
+2008-03-10 Eric Seidel <eric@webkit.org>
+
+ Build fix for JSC on windows.
+
+ * API/JSStringRefCF.cpp:
+ (JSStringCreateWithCFString):
+ * kjs/function.cpp:
+ (KJS::decode):
+ * kjs/nodes2string.cpp:
+ (KJS::escapeStringForPrettyPrinting):
+
+2008-03-10 Eric Seidel <eric@webkit.org>
+
+ No review, build fix only.
+
+ Attempt to fix the windows build?
+
+ * kjs/ustring.h: change unsigned short to UChar
+
+2008-03-10 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Darin.
+
+ Remove KJS::UChar, use ::UChar instead
+ http://bugs.webkit.org/show_bug.cgi?id=17017
+
+ * API/JSStringRef.cpp:
+ (JSStringCreateWithCharacters):
+ (JSStringCreateWithUTF8CString):
+ * API/JSStringRefCF.cpp:
+ (JSStringCreateWithCFString):
+ * JavaScriptCore.exp:
+ * kjs/Parser.h:
+ * kjs/function.cpp:
+ (KJS::decode):
+ (KJS::parseInt):
+ (KJS::parseFloat):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnescape):
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+ * kjs/identifier.cpp:
+ (KJS::Identifier::equal):
+ (KJS::CStringTranslator::translate):
+ * kjs/interpreter.h:
+ * kjs/lexer.cpp:
+ (KJS::Lexer::setCode):
+ (KJS::Lexer::shift):
+ (KJS::Lexer::lex):
+ (KJS::Lexer::convertUnicode):
+ (KJS::Lexer::makeIdentifier):
+ * kjs/lookup.cpp:
+ (KJS::keysMatch):
+ * kjs/nodes2string.cpp:
+ (KJS::escapeStringForPrettyPrinting):
+ (KJS::SourceStream::operator<<):
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp):
+ (KJS::RegExp::match):
+ * kjs/string_object.cpp:
+ (KJS::substituteBackreferences):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::computeHash):
+ (KJS::UString::UString):
+ (KJS::UString::append):
+ (KJS::UString::ascii):
+ (KJS::UString::operator=):
+ (KJS::UString::is8Bit):
+ (KJS::UString::toStrictUInt32):
+ (KJS::UString::find):
+ (KJS::operator==):
+ (KJS::operator<):
+ (KJS::compare):
+ (KJS::UString::UTF8String):
+ * kjs/ustring.h:
+ * pcre/pcre.h:
+
+2008-03-09 Steve Falkenburg <sfalken@apple.com>
+
+ Stop Windows build if an error occurs in a prior project.
+
+ Rubber stamped by Darin.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+
+2008-03-09 J¸rg Billeter <j@bitron.ch>
+
+ Reviewed by Alp Toker.
+
+ Conditionalise ICU for Unicode in the GTK+ port.
+
+ * wtf/Platform.h:
+
+2008-03-07 David D. Kilzer <ddkilzer@apple.com>
+
+ Unify concept of enabling Netscape Plug-in API (NPAPI).
+
+ Reviewed by Darin.
+
+ * wtf/Platform.h: Define ENABLE_NETSCAPE_PLUGIN_API here.
+
+2008-03-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed <rdar://problem/5689093> Stricter (ES4) eval semantics
+
+ The basic rule is:
+
+ - "eval(s)" is treated as an operator that gives the ES3 eval behavior.
+ ... but only if there is no overriding declaration of "eval" in scope.
+ - All other invocations treat eval as a function that evaluates a
+ script in the context of its "this" object.
+ ... but if its "this" object is not the global object it was
+ originally associated with, eval throws an exception.
+
+ Because only expressions of the form "eval(s)" have access to local
+ scope, the compiler can now statically determine whether a function
+ needs local scope to be dynamic.
+
+ * kjs/nodes.h: Added FunctionCallEvalNode. It works just like
+ FuncationCallResolveNode, except it statically indicates that the node
+ may execute eval in the ES3 way.
+ * kjs/nodes.cpp:
+ * kjs/nodes2string.cpp:
+
+ * tests/mozilla/expected.html: This patch happens to fix a Mozilla JS
+ test, but it's a bit of a pyrrhic victory. The test intends to test
+ Mozilla's generic API for calling eval on any object, but, in reality,
+ we only support calling eval on the global object.
+
+2008-03-06 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+
+2008-03-06 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+
+2008-03-06 Alp Toker <alp@atoker.com>
+
+ Fix the build fix in r30845 to support out-of-tree builds.
+
+ * GNUmakefile.am:
+
+2008-03-06 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::ThreadCondition::timedWait):
+
+2008-03-06 Darin Adler <darin@apple.com>
+
+ - another small step towards fixing the Qt build
+
+ * JavaScriptCore.pri: Remove more references to the now-obsolete bindings directory.
+
+2008-03-06 Darin Adler <darin@apple.com>
+
+ - a small step towards fixing the Qt build
+
+ * JavaScriptCore.pri: Remove references to files no longer present in JavaScriptCore/bindings.
+
+2008-03-06 Brady Eidson <beidson@apple.com>
+
+ Gtk Build fix
+
+ * wtf/ThreadingGtk.cpp:
+ (WTF::ThreadCondition::timedWait):
+
+2008-03-06 Alexey Proskuryakov <ap@webkit.org>
+
+ Wx build fix.
+
+ * wtf/unicode/icu/CollatorICU.cpp:
+ (WTF::Collator::userDefault): Put ICU workaround under both PLATFORM(DARWIN) and
+ PLATFORM(CF) checks, so that each port can decide if it wants to use CF on Mac for it.
+
+2008-03-06 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Darin
+
+ Add a timedWait() method to ThreadCondition
+
+ * JavaScriptCore.exp:
+
+ * wtf/Threading.h:
+
+ * wtf/ThreadingGtk.cpp:
+ (WTF::ThreadCondition::timedWait):
+
+ * wtf/ThreadingNone.cpp:
+ (WTF::ThreadCondition::timedWait):
+
+ * wtf/ThreadingPthreads.cpp:
+ (WTF::ThreadCondition::timedWait):
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::ThreadCondition::timedWait): Needs implementation
+
+2008-03-06 Alexey Proskuryakov <ap@webkit.org>
+
+ More build fixes.
+
+ * jscore.bkl: Add the wtf/unicode directory.
+ * wtf/unicode/CollatorDefault.cpp:
+ (WTF::Collator::userDefault): Use a constructor that does exist.
+ * wtf/unicode/icu/CollatorICU.cpp: Mac build fix for case-sensitive file systems.
+
+2008-03-06 Darin Adler <darin@apple.com>
+
+ - try to fix the Qt build
+
+ * JavaScriptCore.pri: Add the wtf/unicode directory.
+
+2008-03-06 Darin Adler <darin@apple.com>
+
+ - try to fix the GTK build
+
+ * GNUmakefile.am: Add a -I for the wtf/unicode directory.
+
+2008-03-06 Darin Adler <darin@apple.com>
+
+ - try to fix the Mac build
+
+ * icu/unicode/parseerr.h: Copied from ../WebCore/icu/unicode/parseerr.h.
+ * icu/unicode/ucol.h: Copied from ../WebCore/icu/unicode/ucol.h.
+ * icu/unicode/uloc.h: Copied from ../WebCore/icu/unicode/uloc.h.
+ * icu/unicode/unorm.h: Copied from ../WebCore/icu/unicode/unorm.h.
+ * icu/unicode/uset.h: Copied from ../WebCore/icu/unicode/uset.h.
+
+2008-03-06 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5687269> Need to create a Collator abstraction for WebCore and JavaScriptCore
+
+ * wtf/Threading.h:
+ (WTF::initializeThreading):
+ * wtf/ThreadingGtk.cpp:
+ (WTF::initializeThreading):
+ * wtf/ThreadingNone.cpp:
+ * wtf/ThreadingPthreads.cpp:
+ * wtf/ThreadingWin.cpp:
+ Added AtomicallyInitializedStatic.
+
+ * kjs/string_object.cpp: (KJS::localeCompare): Changed to use Collator.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ Added new fiiles to projects.
+
+ * wtf/unicode/Collator.h: Added.
+ (WTF::Collator::):
+ * wtf/unicode/CollatorDefault.cpp: Added.
+ (WTF::Collator::Collator):
+ (WTF::Collator::~Collator):
+ (WTF::Collator::setOrderLowerFirst):
+ (WTF::Collator::collate):
+ * wtf/unicode/icu/CollatorICU.cpp: Added.
+ (WTF::cachedCollatorMutex):
+ (WTF::Collator::Collator):
+ (WTF::Collator::~Collator):
+ (WTF::Collator::setOrderLowerFirst):
+ (WTF::Collator::collate):
+ (WTF::Collator::createCollator):
+ (WTF::Collator::releaseCollator):
+
+2008-03-05 Kevin Ollivier <kevino@theolliviers.com>
+
+ Fix the wx build after the bindings move.
+
+ * JavaScriptCoreSources.bkl:
+ * jscore.bkl:
+
+2008-03-05 Alp Toker <alp@atoker.com>
+
+ GTK+ build fix for breakage introduced in r30800.
+
+ Track moved bridge sources from JavaScriptCore to WebCore.
+
+ * GNUmakefile.am:
+
+2008-03-05 Brent Fulgham <bfulgham@gmail.com>
+
+ Reviewed by Adam Roben.
+
+ Remove definition of WTF_USE_SAFARI_THEME from wtf/Platform.h
+ because the PLATFORM(CG) flag is not set until config.h has
+ already included this file.
+
+ * wtf/Platform.h: Remove useless definition of WTF_USE_SAFARI_THEME
+
+2008-03-05 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Alexey and Mark Rowe
+
+ Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html
+
+ DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
+ removing particular items for Databases that were shutting down.
+
+ This filtering operation is not atomic, and therefore causes a race condition with the
+ MessageQueue waking up and reading from the message queue.
+
+ The end result was an attempt to dereference a null DatabaseTask. Timing-wise, this never
+ seemed to happen in a debug build, otherwise an assertion would've caught it. Replacing that
+ assertion with a crash in a release build is what revealed this bug.
+
+ * wtf/MessageQueue.h:
+ (WTF::::waitForMessage): Tweak the waiting logic to check the queue's empty state then go back
+ to sleep if the queue was empty - checking m_killed each time it wakes up.
+
+2008-03-05 David D. Kilzer <ddkilzer@apple.com>
+
+ Remove unused header includes from interpreter.cpp.
+
+ Reviewed by Darin.
+
+ * kjs/interpreter.cpp: Remove unused header includes.
+
+2008-03-05 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam.
+
+ Remove bindings/.
+
+ * bindings: Removed.
+
+2008-03-05 Anders Carlsson <andersca@apple.com>
+
+ Don't build bindings/ anymore.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2008-03-05 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Geoff.
+
+ Don't build JavaScriptCore/bindings.
+
+ * JavaScriptCore.exp:
+ Export a couple of new functions.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ Remove bindings/
+
+ * kjs/config.h:
+ No need to define HAVE_JNI anymore.
+
+ * kjs/interpreter.cpp:
+ Remove unnecessary include.
+
+2008-03-05 David D. Kilzer <ddkilzer@apple.com>
+
+ Allow override of default script file name using command-line argument.
+
+ Reviewed by Adele.
+
+ * API/minidom.c:
+ (main): Allow first command-line argument to override the default script
+ file name of "minidom.js".
+ * API/testapi.c:
+ (main): Allow first command-line argument to override the default script
+ file name of "testapi.js".
+
+2008-03-04 Mark Rowe <mrowe@apple.com>
+
+ Mac build fix.
+
+ * JavaScriptCore.exp: Add new symbol to exports file.
+
+2008-03-03 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Anders.
+
+ Make ForInNode check for the timeout interrupt
+
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::execute):
+
+2008-03-02 Brent Fulgham <bfulgham@gmail.com>
+
+ Reviewed by Alp Toker.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17415
+ GTK Build (using autotools) on Mac OS (DarwinPorts) Fails
+
+ Add -lstdc++ to link flags for minidom program. This corrects
+ a build error for the GTK+ on Mac OS.
+
+ * GNUmakefile.am:
+
+2008-03-01 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ Update Xcode configuration to support building debug and release from the mysterious future.
+
+ * Configurations/Base.xcconfig:
+ * Configurations/DebugRelease.xcconfig:
+
+2008-02-29 Brent Fulgham <bfulgham@gmail.com>
+
+ http://bugs.webkit.org/show_bug.cgi?id=17483
+ Implement scrollbars on Windows (Cairo)
+
+ Reviewed by Adam Roben.
+
+ * wtf/Platform.h:
+
+2008-02-29 Adam Roben <aroben@apple.com>
+
+ Remove unused DebuggerImp::abort and DebuggerImp::aborted
+
+ Reviewed by Tim and Sam.
+
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct):
+ * kjs/internal.h:
+ (KJS::DebuggerImp::DebuggerImp):
+ * kjs/nodes.cpp:
+ (KJS::Node::handleException):
+ (KJS::FunctionBodyNodeWithDebuggerHooks::execute):
+
+2008-02-28 Eric Christopher <echristo@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ ** TOTAL **: 1.005x as fast 2867.6ms +/- 0.4% 2853.2ms +/- 0.3% significant
+
+ * kjs/nodes.cpp: Tell the compiler that exceptions are unexpected (for
+ the sake of branch prediction and code organization).
+
+2008-02-27 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Sam Weinig.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17030
+ Small buffer overflow within initialization
+
+ * kjs/date_object.cpp:
+ (KJS::DateObjectFuncImp::callAsFunction):
+ (KJS::parseDate):
+ Remove unnecessary and incorrect memset() calls - GregorianDateTime can initialize itself.
+
+2008-02-25 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Dan Bernstein.
+
+ - Add a variant of remove that takes a position and a length.
+
+ * wtf/Vector.h:
+ (WTF::Vector::remove):
+
+2008-02-25 Mark Mentovai <mark@moxienet.com>
+
+ Reviewed by Mark Rowe.
+
+ Enable CollectorHeapIntrospector to build by itself, as well as in an AllInOneFile build.
+ http://bugs.webkit.org/show_bug.cgi?id=17538
+
+ * kjs/CollectorHeapIntrospector.cpp: Provide "using" declaration for
+ WTF::RemoteMemoryReader.
+ * kjs/collector.h: Move CollectorHeap declaration here...
+ * kjs/collector.cpp: ... from here.
+
+2008-02-25 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam.
+
+ * JavaScriptCore.exp: Sort the contents of this file.
+
+2008-02-25 Adam Roben <aroben@apple.com>
+
+ MSVC build fix
+
+ * kjs/testkjs.cpp:
+ (functionQuit): Don't add a return statement after exit(0) for MSVC.
+
+2008-02-24 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17529
+ Add support for reading from stdin from testkjs
+
+ * kjs/testkjs.cpp:
+ (GlobalObject::GlobalObject): Add readline function to global object.
+ (functionReadline): Added. Reads characters from stdin until a '\n' or
+ EOF is encountered. The input is returned as a String to the caller.
+
+2008-02-24 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17528
+ Give testkjs a bath
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj: Make the testkjs.cpp use 4 space indentation.
+ * kjs/testkjs.cpp:
+ (StopWatch::getElapsedMS):
+ (GlobalObject::className):
+ (GlobalObject::GlobalObject):
+ Rename GlobalImp to GlobalObject and setup the global functions
+ in the GlobalObject's constructor. Also, use static functions for
+ the implementation so we can use the standard PrototypeFunction
+ class and remove TestFunctionImp.
+ (functionPrint): Move print() functionality here.
+ (functionDebug): Move debug() functionality here.
+ (functionGC): Move gc() functionality here.
+ (functionVersion): Move version() functionality here.
+ (functionRun): Move run() functionality here.
+ (functionLoad): Move load() functionality here.
+ (functionQuit): Move quit() functionality here.
+ (prettyPrintScript): Fix indentation.
+ (runWithScripts): Since all the functionality of createGlobalObject is
+ now in the GlobalObject constructor, just call new here.
+ (parseArguments): Fix indentation.
+ (kjsmain): Ditto
+ (fillBufferWithContentsOfFile): Ditto.
+
+2008-02-24 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt and Mark Rowe.
+
+ http://bugs.webkit.org/show_bug.cgi?id=17505
+ Add support for getting command line arguments in testkjs
+
+ - This slightly changes the behavior of parsing arguments by requiring
+ a '-f' before all files.
+
+ * kjs/testkjs.cpp:
+ (createGlobalObject): Add a global property called 'arguments' which
+ contains an array with the parsed arguments as strings.
+ (runWithScripts): Pass in the arguments vector so that it can be passed
+ to the global object.
+ (parseArguments): Change parsing rules to require a '-f' before any script
+ file. After all '-f' and '-p' arguments have been parsed, the remaining
+ are added to the arguments vector and exposed to the script. If there is a
+ chance of ambiguity (the user wants to pass the string '-f' to the script),
+ the string '--' can be used separate the options from the pass through
+ arguments.
+ (kjsmain):
+
+2008-02-24 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=17511
+ REGRESSION: Reproducible crash in SegmentedSubstring::SegmentedSubstring(SegmentedSubstring const&)
+
+ * wtf/Deque.h:
+ (WTF::::expandCapacityIfNeeded): Fixed the case where m_start and m_end
+ are both zero but the buffer capacity is non-zero.
+ (WTF::::prepend): Added validity checks.
+
+2008-02-23 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Rubber stamped by Darin.
+
+ Add separator '\' after libJavaScriptCore_la_LIBADD and cleanup
+ whitespaces introduced in the previous commit.
+
+ * GNUmakefile.am:
+
+2008-02-23 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ * GNUmakefile.am: Add GLOBALDEPS for testkjs and minidom.
+
+2008-02-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17496
+ make Deque use a circular array; add iterators
+
+ * wtf/Deque.h: Wrote an all-new version of this class that uses a circular
+ buffer. Growth policy is identical to vector. Added iterators.
+
+ * wtf/Vector.h: Made two small refinements while using this to implement
+ Deque: Made VectorBufferBase derive from Noncopyable, which would have
+ saved me some debugging time if it had been there. Renamed Impl and
+ m_impl to Buffer and m_buffer.
+
+2008-02-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17067
+ eliminate attributes parameter from JSObject::put for speed/clarity
+
+ * API/JSCallbackObject.h: Removed attribute arguments.
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::JSCallbackObject<Base>::put): Ditto.
+ * API/JSObjectRef.cpp:
+ (JSObjectSetProperty): Use initializeVariable or putDirect when necessary
+ to set attribute values.
+ * JavaScriptCore.exp: Updated.
+ * bindings/objc/objc_runtime.h: Removed attribute arguments.
+ * bindings/objc/objc_runtime.mm:
+ (ObjcFallbackObjectImp::put): Ditto.
+ * bindings/runtime_array.cpp:
+ (RuntimeArray::put): Ditto.
+ * bindings/runtime_array.h: Ditto.
+ * bindings/runtime_object.cpp:
+ (RuntimeObjectImp::put): Ditto.
+ * bindings/runtime_object.h: Ditto. Also removed canPut which was only
+ called from one place in WebCore that can use hasProperty instead.
+
+ * kjs/Activation.h: Removed attribute argument from put and added the new
+ initializeVariable function that's used to put variables in variable objects.
+ Also made isActivationObject a const member.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::put): Removed attribute argument.
+ (KJS::JSGlobalObject::initializeVariable): Added. Used to give variables
+ their initial values, which can include the read-only property.
+ (KJS::JSGlobalObject::reset): Removed obsolete comments about flags.
+ Removed Internal flag, which is no longer needed.
+ * kjs/JSGlobalObject.h: More of the same.
+
+ * kjs/JSVariableObject.h: Added pure virtual initializeVariable function.
+ (KJS::JSVariableObject::symbolTablePut): Removed checkReadOnly flag; we always
+ check read-only.
+ (KJS::JSVariableObject::symbolTableInitializeVariable): Added.
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::put): Removed attribute argument.
+ * kjs/array_instance.h: Ditto.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::put): Ditto.
+ (KJS::Arguments::put): Ditto.
+ (KJS::ActivationImp::put): Ditto.
+ (KJS::ActivationImp::initializeVariable): Added.
+ * kjs/function.h: Removed attribute arguments.
+
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct): Removed Internal flag.
+
+ * kjs/lookup.h:
+ (KJS::lookupPut): Removed attributes argument. Also changed to use putDirect
+ instead of calling JSObject::put.
+ (KJS::cacheGlobalObject): Ditto.
+
+ * kjs/nodes.cpp:
+ (KJS::ConstDeclNode::handleSlowCase): Call initializeVariable to initialize
+ the constant.
+ (KJS::ConstDeclNode::evaluateSingle): Ditto.
+ (KJS::TryNode::execute): Use putDirect to set up the new object.
+ (KJS::FunctionBodyNode::processDeclarations): Removed Internal.
+ (KJS::ProgramNode::processDeclarations): Ditto.
+ (KJS::EvalNode::processDeclarations): Call initializeVariable to initialize
+ the variables and functions.
+ (KJS::FuncDeclNode::makeFunction): Removed Internal.
+ (KJS::FuncExprNode::evaluate): Ditto.
+
+ * kjs/object.cpp: Removed canPut, which was only being used in one code path,
+ not the normal high speed one.
+ (KJS::JSObject::put): Removed attribute argument. Moved the logic from
+ canPut here, in the one code ath that was still using it.
+ * kjs/object.h: Removed Internal attribute, ad canPut function. Removed the
+ attributes argument to the put function. Made isActivationObject const.
+
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpImp::put): Removed attributes argument.
+ (KJS::RegExpImp::putValueProperty): Ditto.
+ (KJS::RegExpObjectImp::put): Ditto.
+ (KJS::RegExpObjectImp::putValueProperty): Ditto.
+ * kjs/regexp_object.h: Ditto.
+
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::put): Removed attributes argument.
+ * kjs/string_object.h: Ditto.
+
+2008-02-23 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Not reviewed, Gtk build fix.
+
+ * kjs/testkjs.pro:
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix - move ThreadCondition implementation from WebCore to WTF.
+
+ * wtf/ThreadingWin.cpp:
+ (WTF::ThreadCondition::ThreadCondition):
+ (WTF::ThreadCondition::~ThreadCondition):
+ (WTF::ThreadCondition::wait):
+ (WTF::ThreadCondition::signal):
+ (WTF::ThreadCondition::broadcast):
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Touch some files, hoping that Windows build bot will create JSC headers.
+
+ * kjs/AllInOneFile.cpp:
+ * kjs/array_instance.cpp:
+ * wtf/HashTable.cpp:
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Qt/Wx build fix - this file was still in a wrong namespace, too.
+
+ * wtf/ThreadingNone.cpp:
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ More build fixing - fix mismatched braces.
+
+ * JavaScriptCore.pri:
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Wx and Gtk build fixes.
+
+ * JavaScriptCore.pri: Don't try to compile ThreadingPthreads.
+ * wtf/ThreadingGtk.cpp: Use a correct namespace.
+
+2008-02-23 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ Move basic threading support from WebCore to WTF.
+
+ Added mutex protection to MessageQueue::killed() for paranoia sake.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * wtf/Locker.h: Copied from WebCore/platform/Locker.h.
+ * wtf/MessageQueue.h: Copied from WebCore/platform/MessageQueue.h.
+ (WTF::::killed):
+ * wtf/Threading.h: Copied from WebCore/platform/Threading.h.
+ * wtf/ThreadingGtk.cpp: Copied from WebCore/platform/gtk/ThreadingGtk.cpp.
+ (WebCore::createThread):
+ * wtf/ThreadingNone.cpp: Copied from WebCore/platform/ThreadingNone.cpp.
+ * wtf/ThreadingPthreads.cpp: Copied from WebCore/platform/pthreads/ThreadingPthreads.cpp.
+ (WTF::createThread):
+ * wtf/ThreadingWin.cpp: Copied from WebCore/platform/win/ThreadingWin.cpp.
+ (WTF::createThread):
+ (WTF::Mutex::Mutex):
+ (WTF::Mutex::~Mutex):
+ (WTF::Mutex::lock):
+ (WTF::Mutex::tryLock):
+ (WTF::Mutex::unlock):
+
+2008-02-22 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Partial fix for <rdar://problem/5744037> Gmail out of memory (17455)
+
+ I'm removing KJS_MEM_LIMIT for the following reasons:
+
+ - We have a few reports of KJS_MEM_LIMIT breaking important web
+ applications, like GMail and Google Reader. (For example, if you
+ simply open 12 GMail tabs, tab #12 will hit the limit.)
+
+ - Firefox has no discernable JS object count limit, so any limit, even
+ a large one, is a potential compatibility problem.
+
+ - KJS_MEM_LIMIT does not protect against malicious memory allocation,
+ since there are many ways to maliciously allocate memory without
+ increasing the JS object count.
+
+ - KJS_MEM_LIMIT is already mostly broken, since it only aborts the
+ script that breaches the limit, not any subsequent scripts.
+
+ - We've never gotten bug reports about websites that would have
+ benefited from an unbroken KJS_MEM_LIMIT. The initial check-in of
+ KJS_MEM_LIMIT (KJS revision 80061) doesn't mention a website that
+ needed it.
+
+ - Any website that brings you anywhere close to crashing due to the
+ number of live JS objects will almost certainly put up the "slow
+ script" dialog at least 20 times beforehand.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ * kjs/collector.h:
+ * kjs/nodes.cpp:
+ (KJS::TryNode::execute):
+
+2008-02-22 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey P.
+
+ <rdar://problem/5759327> REGRESSION: while(NaN) acts like while(true)
+
+ Fix yet another case where we incorrectly relied on implicit double
+ to bool coercion.
+
+ * kjs/nodes.cpp:
+ (KJS::PostDecLocalVarNode::evaluateToBoolean):
+
+2008-02-20 Michael Knaup <michael.knaup@mac.com>
+
+ Reviewed by Darin.
+
+ Fix for Bug 16753: date set methods with no args should result in NaN (Acid3 bug)
+ The set values result in NaN now when called with no args, NaN or +/- inf values.
+ The setYear, setFullYear and setUTCFullYear methods used on NaN dates work as
+ descripted in the standard.
+
+ * kjs/date_object.cpp:
+ (KJS::fillStructuresUsingTimeArgs):
+ (KJS::fillStructuresUsingDateArgs):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::dateProtoFuncSetYear):
+
+2008-02-19 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin.
+
+ Change OpaqueJSClass and RootObject to start with a ref count of 1.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::OpaqueJSClass):
+ (OpaqueJSClass::createNoAutomaticPrototype):
+ (OpaqueJSClass::create):
+ * API/JSClassRef.h:
+ * API/JSObjectRef.cpp:
+ (JSClassCreate):
+ * bindings/runtime_root.cpp:
+ (KJS::Bindings::RootObject::create):
+ (KJS::Bindings::RootObject::RootObject):
+
+2008-02-19 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Anders.
+
+ - removed explicit initialization to 1 for RefCounted; that's now the default
+
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp): Removed RefCounted initializer.
+
+2008-02-19 Darin Adler <darin@apple.com>
+
+ Reviewed by Anders.
+
+ - next step for http://bugs.webkit.org/show_bug.cgi?id=17257
+ start ref counts at 1 instead of 0 for speed
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::RefCounted): Have refcounts default to 1. This allows us to start
+ removing the explicit initialization of RefCounted from classes and eventually we
+ can remove the ability to have the initial count of 0 entirely.
+
+2008-02-18 Samuel Weinig <sam@webkit.org>
+
+ Reviewed by Geoff Garen.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=17419
+ Remove CompatMode from JavaScriptCore as it is never set to anything other than NativeMode
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::setDebugger):
+ * kjs/date_object.cpp:
+ (KJS::dateProtoFuncGetYear):
+
+2008-02-18 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ * wtf/ASCIICType.h:
+ (WTF::toASCIIHexValue): Added.
+
+2008-02-17 Darin Adler <darin@apple.com>
+
+ * wtf/ListHashSet.h: (WTF::swap): Removed stray return statement.
+
+2008-02-15 Adam Roben <aroben@apple.com>
+
+ Make JavaScriptCore's FEATURE_DEFINES match WebCore's
+
+ Reviewed by Mark.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-02-14 Stephanie Lewis <slewis@apple.com>
+
+ Reviewed by Geoff.
+
+ Update order files.
+
+ * JavaScriptCore.order:
+
+2008-02-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed <rdar://problem/5737835> nee http://bugs.webkit.org/show_bug.cgi?id=17329
+ Crash in JSGlobalObject::popActivation when inserting hyperlink in Wordpress (17329)
+
+ Don't reset the "activations" stack in JSGlobalObject::reset, since we
+ might be executing a script during the call to reset, and the script
+ needs to safely run to completion.
+
+ Instead, initialize the "activations" stack when the global object is
+ created, and subsequently rely on pushing and popping during normal
+ execution to maintain the stack's state.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::init):
+ (KJS::JSGlobalObject::reset):
+
+2008-02-13 Bernhard Rosenkraenzer <bero@arklinux.org>
+
+ Reviewed by Darin.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17339
+ JavaScriptCore does not build with gcc 4.3
+
+ * kjs/interpreter.cpp: Add include of <unistd.h>, since that's where
+ getpid() comes from.
+
+2008-02-13 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey P.
+
+ <rdar://problem/5737003> REGRESSION (r27747): can't browse pictures on fastcupid.com
+
+ When converting numeric values to booleans we need to account for NaN
+
+ * kjs/nodes.cpp:
+ (KJS::MultNode::evaluateToBoolean):
+ (KJS::ModNode::evaluateToBoolean):
+
+2008-02-08 Samuel Weinig <sam@webkit.org>
+
+ Reviewed by Brady Eidson.
+
+ <rdar://problem/5659216> REGRESSION: PLT 0.3% slower due to r28868 (caching ClassNodeList and NamedNodeList)
+
+ - Tweak the statements in isASCIISpace to account for the statistical distribution of
+ usage in the PLT.
+
+ .4% speedup on my machine. Stephanie's machine shows this as .3% speedup.
+
+ * wtf/ASCIICType.h:
+ (WTF::isASCIISpace):
+
+2008-02-11 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Anders Carlsson.
+
+ Fixes for:
+ <rdar://problem/5735497> Match Firefox's cross-domain model more accurately by return the built-in version of functions even if they have been overridden
+ <rdar://problem/5735443> Crash when setting the Window objects prototype to a custom Object and then calling a method on it
+
+ - Expose the native Object.prototype.toString implementation so that it can be used for cross-domain
+ toString calling.
+
+ * JavaScriptCore.exp:
+ * kjs/object_object.cpp:
+ * kjs/object_object.h:
+
+2008-02-10 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Eric.
+
+ * kjs/ExecState.h:
+ (KJS::ExecState::takeException): Added.
+
+2008-02-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17256
+ eliminate default ref. count of 0 in RefCounted class
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::RefCounted): Remove default of 0.
+
+2008-02-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17256
+ Make clients of RefCounted explicitly set the count to 0.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::OpaqueJSClass):
+ * bindings/runtime_root.cpp:
+ (KJS::Bindings::RootObject::RootObject):
+
+2008-02-09 Darin Adler <darin@apple.com>
+
+ Reviewed by Mitz.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=17256
+ Change RegExp to start its ref count at 1, not 0
+
+ We'll want to do this to every RefCounted class, one at a time.
+
+ * kjs/nodes.h:
+ (KJS::RegExpNode::RegExpNode): Use RegExp::create instead of new RegExp.
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp): Marked inline, set initial ref count to 1.
+ (KJS::RegExp::create): Added. Calls new RegExp then adopts the initial ref.
+ * kjs/regexp.h: Reformatted. Made the constructors private. Added static
+ create functions that return objects already wrapped in PassRefPtr.
+ * kjs/regexp_object.cpp:
+ (KJS::regExpProtoFuncCompile): Use RegExp::create instead of new RegExp.
+ (KJS::RegExpObjectImp::construct): Ditto.
+ * kjs/string_object.cpp:
+ (KJS::stringProtoFuncMatch): Ditto.
+ (KJS::stringProtoFuncSearch): Ditto.
+
+2008-02-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ <rdar://problem/5731773> REGRESSION (r28973): Extraneous parentheses in function.toString()
+ https://bugs.webkit.org/show_bug.cgi?id=17214
+
+ Make a subclass of CommaNode to provide the correct precedence for each expression in
+ a variable declaration list.
+
+ * kjs/grammar.y:
+ * kjs/nodes.h:
+ (KJS::VarDeclCommaNode::):
+
+2008-02-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=17247
+ Labelled continue/break can fail in some cases
+
+ Test: fast/js/continue-break-multiple-labels.html
+
+ * kjs/nodes.h:
+ (KJS::StatementNode::pushLabel): Made this virtual.
+ (KJS::LabelNode::pushLabel): Forward pushLabel calls to the statement inside.
+
+2008-02-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15003
+ Function.prototype.constructor should not be DontDelete/ReadOnly (Acid3 bug)
+
+ Test: fast/js/constructor-attributes.html
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset): Remove unwanted attributes from "constructor".
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct): Ditto.
+ * kjs/nodes.cpp:
+ (KJS::FuncDeclNode::makeFunction): Ditto.
+ (KJS::FuncExprNode::evaluate): Ditto.
+
+2008-02-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Added an ASSERT to catch refCount underflow, since it caused a leak in
+ my last check-in.
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::deref):
+
+2008-02-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ PLT speedup related to <rdar://problem/5659272> REGRESSION: PLT .4%
+ slower due to r28884 (global variable symbol table optimization)
+
+ Tweaked RefCounted::deref() to be a little more efficient.
+
+ 1% - 1.5% speedup on my machine. .7% speedup on Stephanie's machine.
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::deref): Don't modify m_refCount if we're just going
+ to delete the object anyway. Also, use a simple == test, which might be
+ faster than <= on some hardware.
+
+2008-02-06 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=17094
+ Array.prototype functions create length properties with DontEnum/DontDelete
+
+ Test results match Gecko with very few obscure exceptions that seem to be
+ bugs in Gecko.
+
+ Test: fast/js/array-functions-non-arrays.html
+
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncConcat): Removed DontEnum and DontDelete from the call
+ to set length.
+ (KJS::arrayProtoFuncPop): Ditto. Also added missing call to deleteProperty,
+ which is not needed for real arrays, but is needed for non-arrays.
+ (KJS::arrayProtoFuncPush): Ditto.
+ (KJS::arrayProtoFuncShift): Ditto.
+ (KJS::arrayProtoFuncSlice): Ditto.
+ (KJS::arrayProtoFuncSort): Removed incorrect call to set length when
+ the array has no elements.
+ (KJS::arrayProtoFuncSplice): Removed DontEnum and DontDelete from the call
+ to set length.
+ (KJS::arrayProtoFuncUnShift): Ditto. Also added a check for 0 arguments to
+ make behavior match the specification in that case.
+ * kjs/nodes.cpp:
+ (KJS::ArrayNode::evaluate): Removed DontEnum and DontDelete from the call
+ to set length.
+
+2008-02-06 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - replace calls to put to set up properties with calls to putDirect, to
+ prepare for a future change where put won't take attributes any more,
+ and for a slight performance boost
+
+ * API/JSObjectRef.cpp:
+ (JSObjectMakeConstructor): Use putDirect instead of put.
+ * kjs/CommonIdentifiers.h: Removed lastIndex.
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset): Use putDirect instead of put.
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncConcat): Took out extra call to get length (unused).
+ (KJS::ArrayObjectImp::ArrayObjectImp): Use putDirect instead of put.
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype): Use putDirect instead of put.
+ * kjs/function.cpp:
+ (KJS::Arguments::Arguments): Use putDirect instead of put.
+ (KJS::PrototypeFunction::PrototypeFunction): Use putDirect instead of put.
+ * kjs/function_object.cpp:
+ (KJS::FunctionObjectImp::construct): Use putDirect instead of put.
+ * kjs/nodes.cpp:
+ (KJS::FuncDeclNode::makeFunction): Use putDirect instead of put.
+ (KJS::FuncExprNode::evaluate): Use putDirect instead of put.
+ * kjs/regexp_object.cpp:
+ (KJS::regExpProtoFuncCompile): Use setLastIndex instead of put(lastIndex).
+ (KJS::RegExpImp::match): Get and set lastIndex by using m_lastIndex instead of
+ calling get and put.
+ * kjs/regexp_object.h:
+ (KJS::RegExpImp::setLastIndex): Added.
+ * kjs/string_object.cpp:
+ (KJS::stringProtoFuncMatch): Use setLastIndex instead of put(lastIndex).
+
+2008-02-05 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Anders Carlsson.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=8080
+ NodeList (and other DOM lists) items are not enumeratable using for..in
+
+ * JavaScriptCore.exp:
+
+2008-02-05 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Update versioning to support the mysterious future.
+
+ * Configurations/Version.xcconfig: Add SYSTEM_VERSION_PREFIX_1060.
+
+2008-02-04 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Oliver Hunt.
+
+ Fixes Bug 16889: REGRESSION (r29425): Canvas-based graphing calculator fails to run
+ Bug 17015: REGRESSION (r29414-29428): www.fox.com "shows" menu fails to render
+ Bug 17164: REGRESSION: JavaScript pop-up menu appears at wrong location when hovering image at http://news.chinatimes.com/
+
+ <http://bugs.webkit.org/show_bug.cgi?id=16889>
+ <rdar://problem/5696255>
+
+ <http://bugs.webkit.org/show_bug.cgi?id=17015>
+
+ <http://bugs.webkit.org/show_bug.cgi?id=17164>
+ <rdar://problem/5720947>
+
+ The ActivationImp tear-off (r29425) introduced a problem with ReadModify
+ nodes that first resolve a slot, call valueForReadModifyNode(), and then
+ store a value in the previously resolved slot. Since valueForReadModifyNode()
+ may cause a tear-off, the slot needs to be resolved again, but this was
+ not happening with the existing code.
+
+ * kjs/nodes.cpp:
+ (KJS::ReadModifyLocalVarNode::evaluate):
+ (KJS::ReadModifyResolveNode::evaluate):
+
+2008-02-04 Cameron McCormack <cam@mcc.id.au>
+
+ Reviewed by Geoff Garen.
+
+ Remove some unneccesary UNUSED_PARAMs. Clarify ownership rule of return value of JSObjectCopyPropertyNames.
+
+ * API/JSNode.c:
+ (JSNode_appendChild):
+ (JSNode_removeChild):
+ (JSNode_replaceChild):
+ (JSNode_getNodeType):
+ (JSNode_getFirstChild):
+ * API/JSNodeList.c:
+ (JSNodeList_length):
+ * API/JSObjectRef.h:
+
+2008-02-04 Rodney Dawes <dobey@wayofthemonkey.com>
+
+ Reviewed by Alp Toker and Mark Rowe.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17175.
+ Bug 17175: Use of C++ compiler flags in CFLAGS
+
+ * GNUmakefile.am: Use global_cxxflags as well as global_cflags in CXXFLAGS.
+
+2008-02-04 Alp Toker <alp@atoker.com>
+
+ Rubber-stamped by Mark Rowe.
+
+ Remove all trailing whitespace in the GTK+ port and related
+ components.
+
+ * GNUmakefile.am:
+
+2008-02-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff Garen.
+
+ PLT speedup related to <rdar://problem/5659272> REGRESSION: PLT .4%
+ slower due to r28884 (global variable symbol table optimization)
+
+ Geoff's theory is that the slowdown was due to copying hash tables when
+ putting things into the back/forward cache. If that's true, then this
+ should fix the problem.
+
+ (According to Geoff's measurements, in a PLT that exaggerates the
+ importance of symbol table saving during cached page creation, this
+ patch is a ~3X speedup in cached page creation, and a 9% speedup overall.)
+
+ * JavaScriptCore.exp: Updated.
+
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::saveLocalStorage): Updated for changes to SavedProperty,
+ which has been revised to avoid initializing each SavedProperty twice when building
+ the array. Store the property names too, so we don't have to store the symbol table
+ separately. Do this by iterating the symbol table instead of the local storage vector.
+ (KJS::JSVariableObject::restoreLocalStorage): Ditto. Restore the symbol table as
+ well as the local storage vector.
+
+ * kjs/JSVariableObject.h: Removed save/restoreSymbolTable and do that work inside
+ save/restoreLocalStorage instead. Made restoreLocalStorage a non-const member function
+ that takes a const reference to a SavedProperties object.
+
+ * kjs/LocalStorage.h: Changed attributes to be unsigned instead of int to match
+ other declarations of attributes elsewhere.
+
+ * kjs/property_map.cpp:
+ (KJS::SavedProperties::SavedProperties): Updated for data member name change.
+ (KJS::PropertyMap::save): Updated for data member name change and to use the new
+ inline init function instead of setting the fields directly. This allows us to
+ skip initializing the SavedProperty objects when first allocating the array, and
+ just do it when we're actually setting up the individual elements.
+ (KJS::PropertyMap::restore): Updated for SavedProperty changes.
+
+ * kjs/property_map.h: Changed SavedProperty from a struct to a class. Set it up so
+ it does not get initialized at construction time to avoid initializing twice when
+ creating an array of SavedProperty. Removed the m_ prefixes from the members of
+ the SavedProperties struct. Generally we use m_ for class members and not struct.
+
+2008-02-02 Tony Chang <idealisms@gmail.com>
+
+ Reviewed by darin. Landed by eseidel.
+
+ Add #define guards for WIN32_LEAN_AND_MEAN and _CRT_RAND_S.
+
+ * kjs/config.h:
+ * wtf/FastMalloc.cpp:
+ * wtf/TCSpinLock.h:
+
+2008-01-28 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Darin Adler.
+
+ - Fix whitespace in nodes.h/cpp and nodes2string.cpp.
+
+ (NOTE: Specific changed functions elided for space and clarity)
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-01-27 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Patch for http://bugs.webkit.org/show_bug.cgi?id=17025
+ nodes.h/cpp has been rolling around in the mud - lets hose it down
+
+ - Rename member variables to use the m_ prefix.
+
+ (NOTE: Specific changed functions elided for space and clarity)
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+
+2008-01-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix <rdar://problem/5657450> REGRESSION: const is broken
+
+ Test: fast/js/const.html
+
+ SunSpider said this was 0.3% slower. And I saw some Shark samples in
+ JSGlobalObject::put -- not a lot but a few. We may be able to regain the
+ speed, but for now we will take that small hit for correctness sake.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::put): Pass the checkReadOnly flag in to symbolTablePut
+ instead of passing attributes.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTablePut): Removed the code to set attributes
+ here, since we only set attributes when creating a property. Added the code
+ to check read-only here, since we need that to implement const!
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::put): Pass the checkReadOnly flag in to symbolTablePut
+ instead of passing attributes.
+
+ * kjs/nodes.cpp:
+ (KJS::isConstant): Added.
+ (KJS::PostIncResolveNode::optimizeVariableAccess): Create a PostIncConstNode
+ if optimizing for a local variable and the variable is constant.
+ (KJS::PostDecResolveNode::optimizeVariableAccess): Ditto. But PostDecConstNode.
+ (KJS::PreIncResolveNode::optimizeVariableAccess): Ditto. But PreIncConstNode.
+ (KJS::PreDecResolveNode::optimizeVariableAccess): Ditto. But PreDecConstNode.
+ (KJS::PreIncConstNode::evaluate): Return the value + 1.
+ (KJS::PreDecConstNode::evaluate): Return the value - 1.
+ (KJS::PostIncConstNode::evaluate): Return the value converted to a number.
+ (KJS::PostDecConstNode::evaluate): Ditto.
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess): Create a ReadModifyConstNode
+ if optimizing for a local variable and the variable is constant.
+ (KJS::AssignResolveNode::optimizeVariableAccess): Ditto. But AssignConstNode.
+ (KJS::ScopeNode::optimizeVariableAccess): Pass the local storage to the
+ node optimizeVariableAccess functions, since that's where we need to look to
+ figure out if a variable is constant.
+ (KJS::FunctionBodyNode::processDeclarations): Moved the call to
+ optimizeVariableAccess until after localStorage is set up.
+ (KJS::ProgramNode::processDeclarations): Ditto.
+
+ * kjs/nodes.h: Fixed the IsConstant and HasInitializer values. They are used
+ as flag masks, so a value of 0 will not work for IsConstant. Changed the
+ first parameter to optimizeVariableAccess to be a const reference to a symbol
+ table and added a const reference to local storage. Added classes for const
+ versions of local variable access: PostIncConstNode, PostDecConstNode,
+ PreIncConstNode, PreDecConstNode, ReadModifyConstNode, and AssignConstNode.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::put): Tweaked comments a bit, and changed the checkReadOnly
+ expression to match the form used at the two other call sites.
+
+2008-01-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16498
+ ''.constructor.toString() gives [function]
+
+ Test: fast/js/function-names.html
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayObjectImp::ArrayObjectImp): Use the class name as the constructor's function name.
+ * kjs/bool_object.cpp:
+ (KJS::BooleanObjectImp::BooleanObjectImp): Ditto.
+ * kjs/date_object.cpp:
+ (KJS::DateObjectImp::DateObjectImp): Ditto.
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype): Make the error object be an Error.
+ (KJS::ErrorObjectImp::ErrorObjectImp): Use the class name as the constructor's function name.
+ (KJS::NativeErrorPrototype::NativeErrorPrototype): Take const UString&.
+ (KJS::NativeErrorImp::NativeErrorImp): Use the prototype's name as the constructor's function
+ name.
+ * kjs/error_object.h: Change ErrorPrototype to inherit from ErrorInstance. Change the
+ NativeErrorImp constructor to take a NativeErrorPrototype pointer for its prototype.
+ * kjs/function.h: Removed unneeded constructor for internal functions without names.
+ We want to avoid those!
+ * kjs/function_object.cpp:
+ (KJS::functionProtoFuncToString): Removed code that writes out just [function] for functions
+ that have no names. There's no reason to do that.
+ (KJS::FunctionObjectImp::FunctionObjectImp): Use the class name as the constructor's
+ function name.
+ * kjs/internal.cpp: Removed the unused constructor.
+ * kjs/number_object.cpp:
+ (KJS::fractionalPartToString): Marked static for internal linkage.
+ (KJS::exponentialPartToString): Ditto.
+ (KJS::numberProtoFuncToPrecision): Removed an unneeded else.
+ (KJS::NumberObjectImp::NumberObjectImp): Use the class name as the constructor's
+ function name.
+ (KJS::NumberObjectImp::getValueProperty): Tweaked formatting.
+ * kjs/object_object.cpp:
+ (KJS::ObjectObjectImp::ObjectObjectImp): Use "Object" for the function name.
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpObjectImp::RegExpObjectImp): Use "RegExp" for the function name.
+ * kjs/string_object.cpp:
+ (KJS::StringObjectImp::StringObjectImp): Use the class name as the constructor's
+ function name.
+
+2008-01-26 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=17027
+ Incorrect Function.toString behaviour with read/modify/write operators performed on negative numbers
+
+ Test: fast/js/function-toString-parentheses.html
+
+ The problem here was that a NumberNode with a negative number in it had the wrong
+ precedence. It's not a primary expression, it's a unary operator with a primary
+ expression after it.
+
+ Once the precedence of NumberNode was fixed, the cases from bug 17020 were also
+ fixed without trying to treat bracket nodes like dot nodes. That wasn't needed.
+ The reason we handle numbers before dot nodes specially is that the dot is a
+ legal character in a number. The same is not true of a bracket. Eventually we
+ could get smarter, and only add the parentheses when there is actual ambiguity.
+ There is none if the string form of the number already has a dot in it, or if
+ it's a number with a alphabetic name like infinity or NAN.
+
+ * kjs/nodes.h: Renamed back from ObjectAccess to DotExpr.
+ (KJS::NumberNode::precedence): Return PrecUnary for negative numbers, since
+ they serialize as a unary operator, not a primary expression.
+ * kjs/nodes2string.cpp:
+ (KJS::SourceStream::operator<<): Clear m_numberNeedsParens if this adds
+ parens; one set is enough.
+ (KJS::bracketNodeStreamTo): Remove unneeded special flag here. Normal
+ operator precedence suffices.
+ (KJS::NewExprNode::streamTo): Ditto.
+
+2008-01-26 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej and Darin.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=17020
+ Function.toString does not parenthesise numbers for the bracket accessor
+
+ It turns out that logic was there for all of the dot accessor nodes to make numbers be
+ parenthesised properly, so it was a trivial extension to extend that to the bracket nodes.
+ I renamed the enum type to reflect the fact that it is now used for both dot and bracket
+ accessors.
+
+ * kjs/nodes2string.cpp:
+ (KJS::bracketNodeStreamTo):
+ (KJS::BracketAccessorNode::streamTo):
+
+2008-01-26 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Fix Bug 17018: Incorrect code generated from Function.toString for get/setters in object literals
+
+ Don't quote getter and setter names during output, as that is simply wrong.
+
+ * kjs/nodes2string.cpp:
+ (KJS::PropertyNode::streamTo):
+
+2008-01-26 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16860
+ a bit of cleanup after the Activation optimization
+
+ * JavaScriptCore.exp: Export the GlobalExecState constructor instead of
+ the global flavor of the ExecState constructor. It'd probably be cleaner
+ to not export either one, but JSGlobalObject inlines the code that
+ constructs the ExecState. If we changed that, we could remove this export.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Re-sorted a few things and
+ put the new source files into the kjs group rather than at the top level.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState): Marked inline and updated for data member
+ name changes. This is now only for use for the derived classes. Also removed
+ code that sets the unused m_savedExec data member for the global case. That
+ data member is only used for the other two types.
+ (KJS::ExecState::~ExecState): Marked inline and removed all the code.
+ The derived class destructors now inclde the appropriate code.
+ (KJS::ExecState::lexicalGlobalObject): Removed unneeded special case for
+ an empty scope chain. The bottom function already returns 0 for that case,
+ so the general case code handles it fine. Also changed to use data members
+ directly rather than calling functions.
+ (KJS::GlobalExecState::GlobalExecState): Added. Calls through to the base
+ class constructor.
+ (KJS::GlobalExecState::~GlobalExecState): Added.
+ (KJS::InterpreterExecState::InterpreterExecState): Added. Moved code to
+ manipulate activeExecStates here since we don't want to have to check for the
+ special case of globalExec.
+ (KJS::InterpreterExecState::~InterpreterExecState): Added.
+ (KJS::EvalExecState::EvalExecState): Added.
+ (KJS::EvalExecState::~EvalExecState): Added.
+ (KJS::FunctionExecState::FunctionExecState): Added.
+ (KJS::FunctionExecState::~FunctionExecState): Added.
+
+ * kjs/ExecState.h: Tweaked the header, includes, and declarations a bit.
+ Made ExecState inherit from Noncopyable. Reformatted some comments and
+ made them a bit more brief. Rearranged declarations a little bit and removed
+ unused savedExec function. Changed seenLabels function to return a reference
+ rather than a pointer. Made constructors and destructor protected, and also
+ did the same with all data members. Renamed m_thisVal to m_thisValue and
+ ls to m_labelStack. Added three new derived classes for each of the
+ types of ExecState. The primary goal here was to remove a branch from the
+ code in the destructor, but it's also clearer than overloading the arguments
+ to the ExecState constructor.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::getCurrentTime): Fixed formatting.
+ (KJS::JSGlobalObject::pushActivation): Removed parentheses that don't make
+ the expression clearer -- other similar sites didn't have these parentheses,
+ even the one a couple lines earlier that sets stackEntry.
+ (KJS::JSGlobalObject::tearOffActivation): Got rid of unneeded static_cast
+ (I think I mentioned this during patch review) and used an early exit so that
+ the entire contents of the function aren't nested inside an if statement.
+ Also removed the check of codeType, instead checking Activation for 0.
+ For now, I kept the codeType check, but inside an assertion.
+
+ * kjs/JSGlobalObject.h: Changed type of globalExec to GlobalExecState.
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction): Changed type to FunctionExecState.
+ (KJS::GlobalFuncImp::callAsFunction): Changed type to EvalExecState.
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate): Changed type to GlobalExecState.
+
+ * kjs/nodes.cpp:
+ (KJS::ContinueNode::execute): Changed code since seenLabels() returns a
+ reference now instead of a pointer.
+ (KJS::BreakNode::execute): Ditto.
+ (KJS::LabelNode::execute): Ditto.
+
+2008-01-26 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Cleanup node2string a little.
+ - Remove some unnecessary branching.
+ - Factor out bracket and dot streaming into static inline functions.
+
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+ (KJS::bracketNodeStreamTo):
+ (KJS::dotNodeStreamTo):
+ (KJS::FunctionCallBracketNode::streamTo):
+ (KJS::FunctionCallDotNode::streamTo):
+ (KJS::PostIncBracketNode::streamTo):
+ (KJS::PostDecBracketNode::streamTo):
+ (KJS::PostIncDotNode::streamTo):
+ (KJS::PostDecDotNode::streamTo):
+ (KJS::DeleteBracketNode::streamTo):
+ (KJS::DeleteDotNode::streamTo):
+ (KJS::PreIncBracketNode::streamTo):
+ (KJS::PreDecBracketNode::streamTo):
+ (KJS::PreIncDotNode::streamTo):
+ (KJS::PreDecDotNode::streamTo):
+ (KJS::ReadModifyBracketNode::streamTo):
+ (KJS::AssignBracketNode::streamTo):
+ (KJS::ReadModifyDotNode::streamTo):
+ (KJS::AssignDotNode::streamTo):
+ (KJS::WhileNode::streamTo):
+
+2008-01-26 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=17001
+ Bug 17001: Build error with Gtk port on Mac OS X
+
+ If both XP_MACOSX and XP_UNIX are defined then X11.h and Carbon.h will both be included.
+ These provide conflicting definitions for a type named 'Cursor'. As XP_UNIX is set by
+ the build system when targeting X11, it doesn't make sense for XP_MACOSX to also be set
+ in this instance.
+
+ * bindings/npapi.h: Don't define XP_MACOSX if XP_UNIX is defined.
+
+2008-01-26 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=17013
+ JSC can't round trip certain for-loops
+
+ Test: fast/js/toString-for-var-decl.html
+
+ * kjs/nodes.h: Added PlaceholderTrueNode so we can put nodes into
+ for loops without injecting the word "true" into them (nice, but not
+ the bug fix). Fixed ForNode constructor so expr1WasVarDecl is set
+ only when there is an expression, since it's common for the actual
+ variable declaration to be moved by the parser.
+
+ * kjs/nodes2string.cpp:
+ (KJS::PlaceholderTrueNode::streamTo): Added. Empty.
+
+2008-01-25 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Fix for bug 17012: REGRESSION: JSC can't round trip an object literal
+
+ Add logic to ensure that object literals and function expressions get
+ parentheses when necessary.
+
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+ (KJS::SourceStream::operator<<):
+
+2008-01-24 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.sln:
+
+2008-01-24 Steve Falkenburg <sfalken@apple.com>
+
+ Build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln:
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
+ Fix QDateTime to JS Date conversion.
+ Several conversion errors (some UTC related, some month
+ offset related) and the conversion distance for Date
+ to DateTime conversion weights were fixed (it should never
+ be better to convert a JS Number into a Date rather than
+ an int).
+
+ * bindings/qt/qt_runtime.cpp:
+ (KJS::Bindings::convertValueToQVariant):
+ (KJS::Bindings::convertQVariantToValue):
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
+ Add support for calling QObjects.
+ Add support for invokeDefaultMethod (via a call to
+ a specific slot), and also allow using it as a
+ constructor, like QtScript.
+
+
+ * bindings/qt/qt_class.cpp:
+ (KJS::Bindings::QtClass::fallbackObject):
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtRuntimeObjectImp::construct):
+ (KJS::Bindings::QtInstance::QtInstance):
+ (KJS::Bindings::QtInstance::~QtInstance):
+ (KJS::Bindings::QtInstance::implementsCall):
+ (KJS::Bindings::QtInstance::invokeDefaultMethod):
+ * bindings/qt/qt_instance.h:
+ * bindings/qt/qt_runtime.cpp:
+ (KJS::Bindings::findMethodIndex):
+ (KJS::Bindings::QtRuntimeMetaMethod::QtRuntimeMetaMethod):
+ (KJS::Bindings::QtRuntimeMetaMethod::callAsFunction):
+ * bindings/qt/qt_runtime.h:
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
+ Code style cleanups.
+ Add spaces before/after braces in inline function.
+
+ * bindings/qt/qt_instance.h:
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
+ Code style cleanups.
+ Remove spaces and unneeded declared parameter names.
+
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtRuntimeObjectImp::removeFromCache):
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
+ Clear stale RuntimeObjectImps.
+ Since other objects can have refs to the QtInstance,
+ we can't rely on the QtInstance being deleted when the
+ RuntimeObjectImp is invalidate or deleted. This
+ could result in a stale JSObject being returned for
+ a valid Instance.
+
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtRuntimeObjectImp::QtRuntimeObjectImp):
+ (KJS::Bindings::QtRuntimeObjectImp::~QtRuntimeObjectImp):
+ (KJS::Bindings::QtRuntimeObjectImp::invalidate):
+ (KJS::Bindings::QtRuntimeObjectImp::removeFromCache):
+ (KJS::Bindings::QtInstance::getRuntimeObject):
+ * bindings/runtime.cpp:
+ (KJS::Bindings::Instance::createRuntimeObject):
+ * bindings/runtime.h:
+
+2008-01-23 Alp Toker <alp@atoker.com>
+
+ Rubber-stamped by Mark Rowe.
+
+ Remove whitespace after -I in automake include lists.
+
+ * GNUmakefile.am:
+
+2008-01-23 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Lars Knoll <lars@trolltech.com>.
+
+ Reworked the JavaScriptCore Qt bindings:
+
+ * Add initial support for string and variant arrays, as well
+ as sub QObjects in the JS bindings.
+
+ * Don't expose fields marked as not scriptable by moc.
+
+ * Add support for dynamic properties and accessing named
+ QObject children of an object (like QtScript and older
+ IE DOM style JS).
+ * Add support for custom toString methods.
+
+ * Fine tune some bindings to be closer to QtScript.
+ Make void functions return undefined, and empty/
+ null QStrings return a zero length string.
+
+ * Create framework for allowing more direct method calls.
+ Since RuntimeMethod doesn't allow us to add additional
+ methods/properties to a function, add these classes.
+ Start prototyping object.signal.connect(...).
+
+ * Add signal support to the Qt bindings.
+ Allow connecting to signals (object.signal.connect(slot)),
+ disconnecting, and emitting signals. Currently chooses
+ the first signal that matches the name, so this will need
+ improvement.
+
+ * Add property names, and resolve signals closer to use.
+ Enumerating properties now returns some of the Qt properties
+ and signals. Slots and methods aren't quite present. Also,
+ resolve signal connections etc. closer to the time of use, so
+ we can do more dynamic resolution based on argument type etc.
+ Still picks the first one with the same name, at the moment.
+
+ * Make signature comparison code consistent.
+ Use the same code for checking meta signatures in
+ the method and fallback getters, and avoid a
+ QByteArray construction when we can.
+
+ * Fix minor memory leak, and handle pointers better.
+ Delete the private object in the dtors, and use RefPtrs
+ for holding Instances etc.
+
+ * Handle method lookup better.
+ Allow invocation time method lookup based on the arguments,
+ which is closer to QtScript behaviour. Also, cache the
+ method lists and delete them in the QtClass dtor (stops
+ a memory leak).
+
+ * Improve JS to Qt data type conversions.
+ Add some support for Date & RegExp JS objects,
+ and provide some metrics on the quality of the
+ conversion.
+
+ * A couple of fixes for autotest failures.
+ Better support for converting lists, read/write only
+ QMetaProperty support, modified slot search order...)
+
+ * bindings/qt/qt_class.cpp:
+ (KJS::Bindings::QtClass::QtClass):
+ (KJS::Bindings::QtClass::~QtClass):
+ (KJS::Bindings::QtClass::name):
+ (KJS::Bindings::QtClass::fallbackObject):
+ (KJS::Bindings::QtClass::methodsNamed):
+ (KJS::Bindings::QtClass::fieldNamed):
+ * bindings/qt/qt_class.h:
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtInstance::QtInstance):
+ (KJS::Bindings::QtInstance::~QtInstance):
+ (KJS::Bindings::QtInstance::getRuntimeObject):
+ (KJS::Bindings::QtInstance::getClass):
+ (KJS::Bindings::QtInstance::implementsCall):
+ (KJS::Bindings::QtInstance::getPropertyNames):
+ (KJS::Bindings::QtInstance::invokeMethod):
+ (KJS::Bindings::QtInstance::invokeDefaultMethod):
+ (KJS::Bindings::QtInstance::stringValue):
+ (KJS::Bindings::QtInstance::booleanValue):
+ (KJS::Bindings::QtInstance::valueOf):
+ (KJS::Bindings::QtField::name):
+ (KJS::Bindings::QtField::valueFromInstance):
+ (KJS::Bindings::QtField::setValueToInstance):
+ * bindings/qt/qt_instance.h:
+ (KJS::Bindings::QtInstance::getBindingLanguage):
+ (KJS::Bindings::QtInstance::getObject):
+ * bindings/qt/qt_runtime.cpp:
+ (KJS::Bindings::QWKNoDebug::QWKNoDebug):
+ (KJS::Bindings::QWKNoDebug::~QWKNoDebug):
+ (KJS::Bindings::QWKNoDebug::operator<<):
+ (KJS::Bindings::):
+ (KJS::Bindings::valueRealType):
+ (KJS::Bindings::convertValueToQVariant):
+ (KJS::Bindings::convertQVariantToValue):
+ (KJS::Bindings::QtRuntimeMethod::QtRuntimeMethod):
+ (KJS::Bindings::QtRuntimeMethod::~QtRuntimeMethod):
+ (KJS::Bindings::QtRuntimeMethod::codeType):
+ (KJS::Bindings::QtRuntimeMethod::execute):
+ (KJS::Bindings::QtRuntimeMethodData::~QtRuntimeMethodData):
+ (KJS::Bindings::QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData):
+ (KJS::Bindings::QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData):
+ (KJS::Bindings::QtMethodMatchType::):
+ (KJS::Bindings::QtMethodMatchType::QtMethodMatchType):
+ (KJS::Bindings::QtMethodMatchType::kind):
+ (KJS::Bindings::QtMethodMatchType::isValid):
+ (KJS::Bindings::QtMethodMatchType::isVariant):
+ (KJS::Bindings::QtMethodMatchType::isMetaType):
+ (KJS::Bindings::QtMethodMatchType::isUnresolved):
+ (KJS::Bindings::QtMethodMatchType::isMetaEnum):
+ (KJS::Bindings::QtMethodMatchType::enumeratorIndex):
+ (KJS::Bindings::QtMethodMatchType::variant):
+ (KJS::Bindings::QtMethodMatchType::metaType):
+ (KJS::Bindings::QtMethodMatchType::metaEnum):
+ (KJS::Bindings::QtMethodMatchType::unresolved):
+ (KJS::Bindings::QtMethodMatchType::typeId):
+ (KJS::Bindings::QtMethodMatchType::name):
+ (KJS::Bindings::QtMethodMatchData::QtMethodMatchData):
+ (KJS::Bindings::QtMethodMatchData::isValid):
+ (KJS::Bindings::QtMethodMatchData::firstUnresolvedIndex):
+ (KJS::Bindings::indexOfMetaEnum):
+ (KJS::Bindings::findMethodIndex):
+ (KJS::Bindings::findSignalIndex):
+ (KJS::Bindings::QtRuntimeMetaMethod::QtRuntimeMetaMethod):
+ (KJS::Bindings::QtRuntimeMetaMethod::mark):
+ (KJS::Bindings::QtRuntimeMetaMethod::callAsFunction):
+ (KJS::Bindings::QtRuntimeMetaMethod::getOwnPropertySlot):
+ (KJS::Bindings::QtRuntimeMetaMethod::lengthGetter):
+ (KJS::Bindings::QtRuntimeMetaMethod::connectGetter):
+ (KJS::Bindings::QtRuntimeMetaMethod::disconnectGetter):
+ (KJS::Bindings::QtRuntimeConnectionMethod::QtRuntimeConnectionMethod):
+ (KJS::Bindings::QtRuntimeConnectionMethod::callAsFunction):
+ (KJS::Bindings::QtRuntimeConnectionMethod::getOwnPropertySlot):
+ (KJS::Bindings::QtRuntimeConnectionMethod::lengthGetter):
+ (KJS::Bindings::QtConnectionObject::QtConnectionObject):
+ (KJS::Bindings::QtConnectionObject::~QtConnectionObject):
+ (KJS::Bindings::QtConnectionObject::metaObject):
+ (KJS::Bindings::QtConnectionObject::qt_metacast):
+ (KJS::Bindings::QtConnectionObject::qt_metacall):
+ (KJS::Bindings::QtConnectionObject::execute):
+ (KJS::Bindings::QtConnectionObject::match):
+ (KJS::Bindings::::QtArray):
+ (KJS::Bindings::::~QtArray):
+ (KJS::Bindings::::rootObject):
+ (KJS::Bindings::::setValueAt):
+ (KJS::Bindings::::valueAt):
+ * bindings/qt/qt_runtime.h:
+ (KJS::Bindings::QtField::):
+ (KJS::Bindings::QtField::QtField):
+ (KJS::Bindings::QtField::fieldType):
+ (KJS::Bindings::QtMethod::QtMethod):
+ (KJS::Bindings::QtMethod::name):
+ (KJS::Bindings::QtMethod::numParameters):
+ (KJS::Bindings::QtArray::getLength):
+ (KJS::Bindings::QtRuntimeMethod::d_func):
+ (KJS::Bindings::QtRuntimeMetaMethod::d_func):
+ (KJS::Bindings::QtRuntimeConnectionMethod::d_func):
+ (KJS::Bindings::):
+ * bindings/runtime.cpp:
+ (KJS::Bindings::Instance::createBindingForLanguageInstance):
+ (KJS::Bindings::Instance::createRuntimeObject):
+ (KJS::Bindings::Instance::reallyCreateRuntimeObject):
+ * bindings/runtime.h:
+
+2008-01-22 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin and Adam.
+
+ <rdar://problem/5688975>
+ div element on microsoft site has wrong left offset.
+
+ Return true even if NPN_GetProperty returns null or undefined. This matches Firefox
+ (and is what the Silverlight plug-in expects).
+
+ * bindings/NP_jsobject.cpp:
+ (_NPN_GetProperty):
+
+2008-01-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=16909
+ REGRESSION: Amazon.com crash (ActivationImp)
+
+ (and a bunch of other crashes)
+
+ Plus, a .7% SunSpider speedup to boot.
+
+ Replaced the buggy currentExec and savedExec mechanisms with an
+ explicit ExecState stack.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect): Explicitly mark the ExecState stack.
+
+ (KJS::Collector::reportOutOfMemoryToAllExecStates): Slight change in
+ behavior: We no longer throw an exception in any global ExecStates,
+ since global ExecStates are more like pseudo-ExecStates, and aren't
+ used for script execution. (It's unclear what would happen if you left
+ an exception waiting around in a global ExecState, but it probably
+ wouldn't be good.)
+
+2008-01-21 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Reviewed by Alp Toker.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16955
+ Get errors when cross-compile webkit-gtk
+
+ * GNUmakefile.am: removed ICU_CFLAGS
+
+2008-01-18 Kevin McCullough <kmccullough@apple.com>
+
+ - Build fix.
+
+ * kjs/ustring.h:
+
+2008-01-18 Kevin McCullough <kmccullough@apple.com>
+
+ - Build fix.
+
+ * kjs/ustring.cpp:
+ * kjs/ustring.h:
+ (KJS::UString::cost):
+
+2008-01-18 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ - Correctly report cost of appended strings to trigger GC.
+
+ * kjs/ustring.cpp:
+ (KJS::UString::Rep::create):
+ (KJS::UString::UString): Don't create unnecssary objects.
+ (KJS::UString::cost): Report cost if necessary but also keep track of
+ reported cost.
+ * kjs/ustring.h:
+
+2008-01-18 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Holger.
+
+ Fix return type conversions from Qt slots to JS values.
+
+ This also fixes fast/dom/open-and-close-by-DOM.html, which called
+ layoutTestController.windowCount().
+
+ When constructing the QVariant that holds the return type we cannot
+ use the QVarian(Type) constuctor as that will create a null variant.
+ We have to use the QVariant(Type, void *) constructor instead, just
+ like in QMetaObject::read() for example.
+
+
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtInstance::getRuntimeObject):
+
+2008-01-18 Prasanth Ullattil <prasanth.ullattil@trolltech.com>
+
+ Reviewed by Simon Hausmann <hausmann@webkit.org>.
+
+ Fix compilation on Win64(2): Implemented currentThreadStackBase on X86-64 on Windows
+
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+
+2008-01-18 Prasanth Ullattil <prasanth.ullattil@trolltech.com>
+
+ Reviewed by Simon Hausmann <hausmann@webkit.org>.
+
+ Fix compilation on Win64(1): Define WTF_PLATFORM_X86_64 correctly on Win64.
+
+
+ * wtf/Platform.h:
+
+2008-01-17 Antti Koivisto <antti@apple.com>
+
+ Fix Windows build.
+
+ * kjs/regexp_object.cpp:
+ (KJS::regExpProtoFuncToString):
+
+2008-01-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=16901
+ Convert remaining JS function objects to use the new PrototypeFunction class
+
+ - Moves Boolean, Function, RegExp, Number, Object and Global functions to their
+ own static function implementations so that they can be used with the
+ PrototypeFunction class. SunSpider says this is 1.003x as fast.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/array_object.h:
+ * kjs/bool_object.cpp:
+ (KJS::BooleanInstance::BooleanInstance):
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::booleanProtoFuncValueOf):
+ (KJS::BooleanObjectImp::BooleanObjectImp):
+ (KJS::BooleanObjectImp::implementsConstruct):
+ (KJS::BooleanObjectImp::construct):
+ (KJS::BooleanObjectImp::callAsFunction):
+ * kjs/bool_object.h:
+ (KJS::BooleanInstance::classInfo):
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::errorProtoFuncToString):
+ * kjs/error_object.h:
+ * kjs/function.cpp:
+ (KJS::globalFuncEval):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncIsNaN):
+ (KJS::globalFuncIsFinite):
+ (KJS::globalFuncDecodeURI):
+ (KJS::globalFuncDecodeURIComponent):
+ (KJS::globalFuncEncodeURI):
+ (KJS::globalFuncEncodeURIComponent):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnEscape):
+ (KJS::globalFuncKJSPrint):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ * kjs/function.h:
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ (KJS::functionProtoFuncToString):
+ (KJS::functionProtoFuncApply):
+ (KJS::functionProtoFuncCall):
+ * kjs/function_object.h:
+ * kjs/number_object.cpp:
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncValueOf):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ * kjs/number_object.h:
+ (KJS::NumberInstance::classInfo):
+ (KJS::NumberObjectImp::classInfo):
+ (KJS::NumberObjectImp::):
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ (KJS::objectProtoFuncValueOf):
+ (KJS::objectProtoFuncHasOwnProperty):
+ (KJS::objectProtoFuncIsPrototypeOf):
+ (KJS::objectProtoFuncDefineGetter):
+ (KJS::objectProtoFuncDefineSetter):
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ (KJS::objectProtoFuncPropertyIsEnumerable):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ * kjs/object_object.h:
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::regExpProtoFuncTest):
+ (KJS::regExpProtoFuncExec):
+ (KJS::regExpProtoFuncCompile):
+ (KJS::regExpProtoFuncToString):
+ * kjs/regexp_object.h:
+
+2008-01-16 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej & Darin.
+
+ Fixes Bug 16868: Gmail crash
+ and Bug 16871: Crash when loading apple.com/startpage
+
+ <http://bugs.webkit.org/show_bug.cgi?id=16868>
+ <rdar://problem/5686108>
+
+ <http://bugs.webkit.org/show_bug.cgi?id=16871>
+ <rdar://problem/5686670>
+
+ Adds ActivationImp tear-off for cross-window eval() and fixes an
+ existing garbage collection issue exposed by the ActivationImp tear-off
+ patch (r29425) that can occur when an ExecState's m_callingExec is
+ different than its m_savedExec.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::mark):
+ * kjs/function.cpp:
+ (KJS::GlobalFuncImp::callAsFunction):
+
+2008-01-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver.
+
+ Clean up MathObjectImp, it needed a little scrubbing.
+
+ * kjs/math_object.cpp:
+ (KJS::MathObjectImp::MathObjectImp):
+ (KJS::MathObjectImp::getOwnPropertySlot):
+ (KJS::MathObjectImp::getValueProperty):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/math_object.h:
+ (KJS::MathObjectImp::classInfo):
+ (KJS::MathObjectImp::):
+
+2008-01-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Rename Lexer variable bol to atLineStart.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::setCode):
+ (KJS::Lexer::nextLine):
+ (KJS::Lexer::lex):
+ * kjs/lexer.h:
+
+2008-01-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen and Anders Carlsson.
+
+ Remove uses of KJS_PURE_ECMA as we don't ever build with it defined,
+ and we have many features that are not included in the ECMA spec.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::setCode):
+ (KJS::Lexer::nextLine):
+ (KJS::Lexer::lex):
+ * kjs/lexer.h:
+ * kjs/string_object.cpp:
+ * kjs/string_object.h:
+
+2008-01-15 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Fix <rdar://problem/5595552> r27608 introduced a 20% increase in JS binary size, 4% increase in WebCore binary size
+
+ - This changes the way JS functions that use Lookup tables are handled. Instead of using
+ one class per function, which allowed specialization of the virtual callAsFunction
+ method, we now use one class, PrototypeFunction, which takes a pointer to a static
+ function to use as the implementation. This significantly decreases the binary size
+ of JavaScriptCore (about 145k on an Intel only build) while still keeping some of the
+ speedup r27608 garnered (SunSpider says this is 1.005x as slow, which should leave some
+ wiggle room from the original 1% speedup) and keeps the functions implementations in separate
+ functions to help with optimizations.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/array_object.cpp:
+ (KJS::arrayProtoFuncToString):
+ (KJS::arrayProtoFuncToLocaleString):
+ (KJS::arrayProtoFuncJoin):
+ (KJS::arrayProtoFuncConcat):
+ (KJS::arrayProtoFuncPop):
+ (KJS::arrayProtoFuncPush):
+ (KJS::arrayProtoFuncReverse):
+ (KJS::arrayProtoFuncShift):
+ (KJS::arrayProtoFuncSlice):
+ (KJS::arrayProtoFuncSort):
+ (KJS::arrayProtoFuncSplice):
+ (KJS::arrayProtoFuncUnShift):
+ (KJS::arrayProtoFuncFilter):
+ (KJS::arrayProtoFuncMap):
+ (KJS::arrayProtoFuncEvery):
+ (KJS::arrayProtoFuncForEach):
+ (KJS::arrayProtoFuncSome):
+ (KJS::arrayProtoFuncIndexOf):
+ (KJS::arrayProtoFuncLastIndexOf):
+ * kjs/array_object.h:
+ * kjs/date_object.cpp:
+ (KJS::DatePrototype::getOwnPropertySlot):
+ (KJS::dateProtoFuncToString):
+ (KJS::dateProtoFuncToUTCString):
+ (KJS::dateProtoFuncToDateString):
+ (KJS::dateProtoFuncToTimeString):
+ (KJS::dateProtoFuncToLocaleString):
+ (KJS::dateProtoFuncToLocaleDateString):
+ (KJS::dateProtoFuncToLocaleTimeString):
+ (KJS::dateProtoFuncValueOf):
+ (KJS::dateProtoFuncGetTime):
+ (KJS::dateProtoFuncGetFullYear):
+ (KJS::dateProtoFuncGetUTCFullYear):
+ (KJS::dateProtoFuncToGMTString):
+ (KJS::dateProtoFuncGetMonth):
+ (KJS::dateProtoFuncGetUTCMonth):
+ (KJS::dateProtoFuncGetDate):
+ (KJS::dateProtoFuncGetUTCDate):
+ (KJS::dateProtoFuncGetDay):
+ (KJS::dateProtoFuncGetUTCDay):
+ (KJS::dateProtoFuncGetHours):
+ (KJS::dateProtoFuncGetUTCHours):
+ (KJS::dateProtoFuncGetMinutes):
+ (KJS::dateProtoFuncGetUTCMinutes):
+ (KJS::dateProtoFuncGetSeconds):
+ (KJS::dateProtoFuncGetUTCSeconds):
+ (KJS::dateProtoFuncGetMilliSeconds):
+ (KJS::dateProtoFuncGetUTCMilliseconds):
+ (KJS::dateProtoFuncGetTimezoneOffset):
+ (KJS::dateProtoFuncSetTime):
+ (KJS::dateProtoFuncSetMilliSeconds):
+ (KJS::dateProtoFuncSetUTCMilliseconds):
+ (KJS::dateProtoFuncSetSeconds):
+ (KJS::dateProtoFuncSetUTCSeconds):
+ (KJS::dateProtoFuncSetMinutes):
+ (KJS::dateProtoFuncSetUTCMinutes):
+ (KJS::dateProtoFuncSetHours):
+ (KJS::dateProtoFuncSetUTCHours):
+ (KJS::dateProtoFuncSetDate):
+ (KJS::dateProtoFuncSetUTCDate):
+ (KJS::dateProtoFuncSetMonth):
+ (KJS::dateProtoFuncSetUTCMonth):
+ (KJS::dateProtoFuncSetFullYear):
+ (KJS::dateProtoFuncSetUTCFullYear):
+ (KJS::dateProtoFuncSetYear):
+ (KJS::dateProtoFuncGetYear):
+ * kjs/date_object.h:
+ * kjs/function.cpp:
+ (KJS::PrototypeFunction::PrototypeFunction):
+ (KJS::PrototypeFunction::callAsFunction):
+ * kjs/function.h:
+ * kjs/lookup.h:
+ (KJS::HashEntry::):
+ (KJS::staticFunctionGetter):
+ * kjs/math_object.cpp:
+ (KJS::mathProtoFuncAbs):
+ (KJS::mathProtoFuncACos):
+ (KJS::mathProtoFuncASin):
+ (KJS::mathProtoFuncATan):
+ (KJS::mathProtoFuncATan2):
+ (KJS::mathProtoFuncCeil):
+ (KJS::mathProtoFuncCos):
+ (KJS::mathProtoFuncExp):
+ (KJS::mathProtoFuncFloor):
+ (KJS::mathProtoFuncLog):
+ (KJS::mathProtoFuncMax):
+ (KJS::mathProtoFuncMin):
+ (KJS::mathProtoFuncPow):
+ (KJS::mathProtoFuncRandom):
+ (KJS::mathProtoFuncRound):
+ (KJS::mathProtoFuncSin):
+ (KJS::mathProtoFuncSqrt):
+ (KJS::mathProtoFuncTan):
+ * kjs/math_object.h:
+ * kjs/string_object.cpp:
+ (KJS::stringProtoFuncToString):
+ (KJS::stringProtoFuncValueOf):
+ (KJS::stringProtoFuncCharAt):
+ (KJS::stringProtoFuncCharCodeAt):
+ (KJS::stringProtoFuncConcat):
+ (KJS::stringProtoFuncIndexOf):
+ (KJS::stringProtoFuncLastIndexOf):
+ (KJS::stringProtoFuncMatch):
+ (KJS::stringProtoFuncSearch):
+ (KJS::stringProtoFuncReplace):
+ (KJS::stringProtoFuncSlice):
+ (KJS::stringProtoFuncSplit):
+ (KJS::stringProtoFuncSubstr):
+ (KJS::stringProtoFuncSubstring):
+ (KJS::stringProtoFuncToLowerCase):
+ (KJS::stringProtoFuncToUpperCase):
+ (KJS::stringProtoFuncToLocaleLowerCase):
+ (KJS::stringProtoFuncToLocaleUpperCase):
+ (KJS::stringProtoFuncLocaleCompare):
+ (KJS::stringProtoFuncBig):
+ (KJS::stringProtoFuncSmall):
+ (KJS::stringProtoFuncBlink):
+ (KJS::stringProtoFuncBold):
+ (KJS::stringProtoFuncFixed):
+ (KJS::stringProtoFuncItalics):
+ (KJS::stringProtoFuncStrike):
+ (KJS::stringProtoFuncSub):
+ (KJS::stringProtoFuncSup):
+ (KJS::stringProtoFuncFontcolor):
+ (KJS::stringProtoFuncFontsize):
+ (KJS::stringProtoFuncAnchor):
+ (KJS::stringProtoFuncLink):
+ * kjs/string_object.h:
+
+2008-01-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Some tweaks to our headerdoc, suggested by David Gatwood on the docs
+ team.
+
+ * API/JSBase.h:
+ * API/JSObjectRef.h:
+ * API/JSStringRef.h:
+ * API/JSValueRef.h:
+
+2008-01-15 Alp Toker <alp@atoker.com>
+
+ Rubber-stamped by Anders.
+
+ Make the HTTP backend configurable in the GTK+ port. curl is currently
+ the only option.
+
+ * wtf/Platform.h: Don't hard-code WTF_USE_CURL for GTK
+
+2008-01-15 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Beth Dakin.
+
+ Remove unneeded variable.
+
+ * kjs/string_object.cpp:
+ (KJS::StringProtoFuncSubstr::callAsFunction):
+
+2008-01-14 Steve Falkenburg <sfalken@apple.com>
+
+ Use shared vsprops for most vcproj properties.
+
+ Reviewed by Darin.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add missing Debug_Internal config.
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj: Add missing Debug_Internal config.
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+
+2008-01-14 Adam Roben <aroben@apple.com>
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Added
+ some headers that were missing from the vcproj so their contents will
+ be included in Find in Files.
+
+2008-01-14 Adam Roben <aroben@apple.com>
+
+ Fix Bug 16871: Crash when loading apple.com/startpage
+
+ <http://bugs.webkit.org/show_bug.cgi?id=16871>
+ <rdar://problem/5686670>
+
+ Patch written by Darin, reviewed by me.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::mark): Call ActivationImp::markChildren if our
+ m_activation is on the stack. This is what ScopeChain::mark also does,
+ but apparently in some cases it's possible for an ExecState's
+ ActivationImp to not be in any ScopeChain.
+
+2008-01-14 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Oliver.
+
+ -<rdar://problem/5622667> REGRESSION (Leopard-ToT): Endless loading loop
+ trying to view techreport.com comments
+ - We need to set values in the map, because if they are already in the
+ map they will not be reset when we use add().
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::put):
+
+2008-01-14 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam.
+
+ - re-speed-up the page load test (my StringImpl change slowed it down)
+
+ * wtf/RefCounted.h:
+ (WTF::RefCounted::RefCounted): Allow derived classes to start with a reference
+ count other than 0. Eventually everyone will want to start with a 1. This is a
+ staged change. For now, there's a default of 0, and you can specify 1. Later,
+ there will be no default and everyone will have to specify. And then later, there
+ will be a default of 1. Eventually, we can take away even the option of starting
+ with 0!
+
+ * wtf/Vector.h:
+ (WTF::Vector::Vector): Sped up creation of non-empty vectors by removing the
+ overhead of first constructing something empty and then calling resize.
+ (WTF::Vector::clear): Sped up the common case of calling clear on an empty
+ vector by adding a check for that case.
+ (WTF::Vector::releaseBuffer): Marked this function inline and removed a branch
+ in the case of vectors with no inline capacity (normal vectors) by leaving out
+ the code to copy the inline buffer in that case.
+
+2008-01-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by David Kilzer.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16787
+ array.splice() with 1 element not working
+
+ Test: fast/js/array-splice.html
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFuncSplice::callAsFunction): Implement this Mozilla extension, and fix
+ some other edge cases.
+
+2008-01-13 Steve Falkenburg <sfalken@apple.com>
+
+ Share common files across projects.
+
+ Unify vsprops files
+ Debug: common.vsprops, debug.vsprops
+ Debug_Internal: common.vsprops, debug.vsprops, debug_internal.vsprops
+ Release: common.vsprops, release.vsprops
+
+ Shared properties can go into common.vsprops, shared debug settings can go into debug.vsprops.
+ debug_internal.vsprops will be mostly empty except for file path prefix modifiers.
+
+ Reviewed by Adam Roben.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.vcproj/debug.vsprops: Removed.
+ * JavaScriptCore.vcproj/debug_internal.vsprops: Removed.
+ * JavaScriptCore.vcproj/release.vsprops: Removed.
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+
+2008-01-13 Marius Bugge Monsen <mbm@trolltech.com>
+
+ Contributions and review by Adriaan de Groot,
+ Simon Hausmann, Eric Seidel, and Darin Adler.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16590
+ Compilation fixes for Solaris.
+
+ * kjs/DateMath.h:
+ (KJS::GregorianDateTime::GregorianDateTime): Use the WIN_OS code path
+ for SOLARIS too, presumably because Solaris also lacks the tm_gtoff and tm_zone
+ fields.
+ (KJS::GregorianDateTime::operator tm): Ditto.
+
+ * kjs/collector.cpp:
+ (KJS::currentThreadStackBase): Use thr_stksegment on Solaris.
+
+ * wtf/MathExtras.h:
+ (isfinite): Implement for Solaris.
+ (isinf): Ditto.
+ (signbit): Ditto. But this one is wrong, so I added a FIXME.
+
+ * wtf/Platform.h: Define PLATFORM(SOLARIS) when "sun" or "__sun" is defined.
+
+2008-01-13 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Anders Carlsson.
+
+ Add binding language type to Instance.
+ Allows runtime determination of the type of an
+ Instance, to allow safe casting. Doesn't actually
+ add any safe casting yet, though.
+
+ Add a helper function to get an Instance from a JSObject*.
+ Given an object and the expected binding language, see if
+ the JSObject actually wraps an Instance of the given type
+ and return it. Otherwise return 0.
+
+ Move RuntimeObjectImp creations into Instance.
+ Make the ctor protected, and Instance a friend class, so
+ that all creation of RuntimeObjectImps goes through
+ one place.
+
+ Remove copy ctor/assignment operator for QtInstance.
+ Instance itself is Noncopyable, so QtInstance doesn't
+ need to have these.
+
+ Add caching for QtInstance and associated RuntimeObjectImps.
+ Push any dealings with QtLanguage bindings into QtInstance,
+ and cache them there, rather than in the Instance layer. Add
+ a QtRuntimeObjectImp to help with caching.
+
+ * JavaScriptCore.exp:
+ * bindings/c/c_instance.h:
+ * bindings/jni/jni_instance.h:
+ * bindings/objc/objc_instance.h:
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtRuntimeObjectImp::QtRuntimeObjectImp):
+ (KJS::Bindings::QtRuntimeObjectImp::~QtRuntimeObjectImp):
+ (KJS::Bindings::QtRuntimeObjectImp::invalidate):
+ (KJS::Bindings::QtRuntimeObjectImp::removeFromCache):
+ (KJS::Bindings::QtInstance::QtInstance):
+ (KJS::Bindings::QtInstance::~QtInstance):
+ (KJS::Bindings::QtInstance::getQtInstance):
+ (KJS::Bindings::QtInstance::getRuntimeObject):
+ * bindings/qt/qt_instance.h:
+ (KJS::Bindings::QtInstance::getBindingLanguage):
+ * bindings/runtime.cpp:
+ (KJS::Bindings::Instance::createBindingForLanguageInstance):
+ (KJS::Bindings::Instance::createRuntimeObject):
+ (KJS::Bindings::Instance::getInstance):
+ * bindings/runtime.h:
+ * bindings/runtime_object.h:
+ (KJS::RuntimeObjectImp::getInternalInstance):
+
+2008-01-12 Alp Toker <alp@atoker.com>
+
+ Reviewed by Mark Rowe.
+
+ Hide non-public symbols in GTK+/autotools release builds.
+
+ * GNUmakefile.am:
+
+2008-01-12 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Mark Rowe.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=16852
+ Fixes leaking of ActivationStackNode objects.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::deleteActivationStack):
+ (KJS::JSGlobalObject::~JSGlobalObject):
+ (KJS::JSGlobalObject::init):
+ (KJS::JSGlobalObject::reset):
+ * kjs/JSGlobalObject.h:
+
+2008-01-12 Darin Adler <darin@apple.com>
+
+ - try to fix Qt Windows build
+
+ * pcre/dftables: Remove reliance on the list form of Perl pipes.
+
+2008-01-12 Darin Adler <darin@apple.com>
+
+ - try to fix Qt build
+
+ * kjs/function.cpp: Added include of scope_chain_mark.h.
+ * kjs/scope_chain_mark.h: Added multiple-include guards.
+
+2008-01-12 Mark Rowe <mrowe@apple.com>
+
+ Another Windows build fix.
+
+ * kjs/Activation.h:
+
+2008-01-12 Mark Rowe <mrowe@apple.com>
+
+ Attempted Windows build fix. Use struct consistently when forward-declaring
+ ActivationStackNode and StackActivation.
+
+ * kjs/Activation.h:
+ * kjs/JSGlobalObject.h:
+
+2008-01-12 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Fixes a problem with the ActivationImp tear-off patch (r29425) where
+ some of the calls to JSGlobalObject::tearOffActivation() were using
+ the wrong test to determine whether it should leave a relic behind.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::argumentsGetter):
+ (KJS::ActivationImp::getOwnPropertySlot):
+
+2008-01-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed <rdar://problem/5665251> REGRESSION (r28880-r28886): Global
+ variable access (16644)
+
+ This bug was caused by var declarations shadowing built-in properties of
+ the global object.
+
+ To match Firefox, we've decided that var declarations will never shadow
+ built-in properties of the global object or its prototypes. We used to
+ behave more like IE, which allows shadowing, but walking that line got
+ us into trouble with websites that sent us down the Firefox codepath.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet): New code to support calling
+ hasProperty before the variable object is fully initialized (so you
+ can call it during initialization).
+
+ * kjs/nodes.cpp:.
+ (KJS::ProgramNode::initializeSymbolTable): Always do a full hasProperty
+ check when looking for duplicates, not getDirect, since it only checks
+ the property map, and not hasOwnProperty, since it doesn't check
+ prototypes.
+ (KJS::EvalNode::processDeclarations): ditto
+
+ * kjs/property_slot.h:
+ (KJS::PropertySlot::ungettableGetter): Best function name evar.
+
+2008-01-11 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Optimized ActivationImp allocation, so that activation records are now
+ first allocated on an explicitly managed stack and only heap allocated
+ when necessary. Roughly a 5% improvement on SunSpider, and a larger
+ improvement on benchmarks that use more function calls.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/Activation.h: Added.
+ (KJS::ActivationImp::ActivationData::ActivationData):
+ (KJS::ActivationImp::ActivationImp):
+ (KJS::ActivationImp::classInfo):
+ (KJS::ActivationImp::isActivationObject):
+ (KJS::ActivationImp::isOnStack):
+ (KJS::ActivationImp::d):
+ (KJS::StackActivation::StackActivation):
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ (KJS::ExecState::~ExecState):
+ * kjs/ExecState.h:
+ (KJS::ExecState::replaceScopeChainTop):
+ (KJS::ExecState::setActivationObject):
+ (KJS::ExecState::setLocalStorage):
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ (KJS::JSGlobalObject::pushActivation):
+ (KJS::JSGlobalObject::checkActivationCount):
+ (KJS::JSGlobalObject::popActivationHelper):
+ (KJS::JSGlobalObject::popActivation):
+ (KJS::JSGlobalObject::tearOffActivation):
+ * kjs/JSGlobalObject.h:
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::JSVariableObjectData::JSVariableObjectData):
+ (KJS::JSVariableObject::JSVariableObject):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::argumentsGetter):
+ (KJS::ActivationImp::ActivationImp):
+ (KJS::ActivationImp::~ActivationImp):
+ (KJS::ActivationImp::init):
+ (KJS::ActivationImp::getOwnPropertySlot):
+ (KJS::ActivationImp::markHelper):
+ (KJS::ActivationImp::mark):
+ (KJS::ActivationImp::ActivationData::ActivationData):
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/function.h:
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::ReadModifyResolveNode::evaluate):
+ (KJS::AssignResolveNode::evaluate):
+ (KJS::WithNode::execute):
+ (KJS::TryNode::execute):
+ (KJS::FunctionBodyNode::processDeclarations):
+ (KJS::FuncExprNode::evaluate):
+ * kjs/object.h:
+ * kjs/scope_chain.h:
+ (KJS::ScopeChain::replace):
+ * kjs/scope_chain_mark.h: Added.
+ (KJS::ScopeChain::mark):
+
+2008-01-11 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Fix the (clean) qmake build. For generating chartables.c we don't
+ depend on a separate input source file anymore, the dftables perl
+ script is enough. So use that instead as value for the .input
+ variable, to ensure that qmake also generates a rule to call dftables.
+
+ * pcre/pcre.pri:
+
+2008-01-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by John Sullivan.
+
+ Fixed some world leak reports:
+ * <rdar://problem/5669436> PLT complains about world leak of 1 JavaScript
+ Interpreter after running cvs-base suite
+
+ * <rdar://problem/5669423> PLT complains about world leak if browser
+ window is open when PLT starts
+
+ * kjs/collector.h: Added the ability to distinguish between global
+ objects and GC-protected global objects, since we only consider the
+ latter to be world leaks.
+ * kjs/collector.cpp:
+
+2008-01-11 Mark Rowe <mrowe@apple.com>
+
+ Silence qmake warning about ctgen lacking input.
+
+ Rubber-stamped by Alp Toker.
+
+ * pcre/pcre.pri:
+
+2008-01-10 David Kilzer <ddkilzer@apple.com>
+
+ dftables should be rewritten as a script
+
+ <http://bugs.webkit.org/show_bug.cgi?id=16818>
+ <rdar://problem/5681463>
+
+ Reviewed by Darin.
+
+ Rewrote the dftables utility in Perl. Attempted to switch all
+ build systems to call the script directly instead of building
+ a binary first. Only the Xcode build was able to be tested.
+
+ * DerivedSources.make: Added pcre directory to VPATH and changed
+ to invoke dftables directly.
+ * GNUmakefile.am: Removed build information and changed to invoke
+ dftables directly.
+ * JavaScriptCore.vcproj/JavaScriptCore.sln: Removed reference to
+ dftables project.
+ * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: Ditto.
+ * JavaScriptCore.vcproj/dftables: Removed.
+ * JavaScriptCore.vcproj/dftables/dftables.vcproj: Removed.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Removed dftables target.
+ * jscore.bkl: Removed dftables executable definition.
+ * pcre/dftables: Copied from JavaScriptCore/pcre/dftables.cpp.
+ * pcre/dftables.cpp: Removed.
+ * pcre/dftables.pro: Removed.
+ * pcre/pcre.pri: Removed references to dftables.cpp and changed to
+ invoke dftables directly.
+
+2008-01-10 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16782
+ <rdar://problem/5675331> REGRESSION(r29266): Reproducible crash in fast/replaced/image-map.html
+
+ The crash resulted from a native object (DumpRenderTree's
+ EventSender) causing its wrapper to be invalidated (by clicking a
+ link that replaced the document in the window) and consequently
+ deallocated. The fix is to use RefPtrs to protect the native object
+ from deletion by self-invalidation.
+
+ * bindings/runtime_method.cpp:
+ (RuntimeMethod::callAsFunction):
+ * bindings/runtime_object.cpp:
+ (RuntimeObjectImp::fallbackObjectGetter):
+ (RuntimeObjectImp::fieldGetter):
+ (RuntimeObjectImp::methodGetter):
+ (RuntimeObjectImp::put):
+ (RuntimeObjectImp::defaultValue):
+ (RuntimeObjectImp::callAsFunction):
+
+2008-01-07 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Turn testIsInteger assertions into compile-time asserts and move them into HashTraits.h
+ where possible.
+
+ * kjs/testkjs.cpp:
+ * wtf/HashTraits.h:
+
+2008-01-07 Nikolas Zimmermann <zimmermann@kde.org>
+
+ Reviewed by Mark.
+
+ Enable SVG_FONTS by default.
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2008-01-07 Darin Adler <darin@apple.com>
+
+ Rubber stamped by David Kilzer.
+
+ - get rid of empty fpconst.cpp
+
+ * GNUmakefile.am: Remove fpconst.cpp.
+ * JavaScriptCore.pri: Ditto.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Ditto.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Ditto.
+ * JavaScriptCoreSources.bkl: Ditto.
+
+ * kjs/fpconst.cpp: Removed.
+
+2008-01-07 Darin Adler <darin@apple.com>
+
+ Reviewed by David Kilzer.
+
+ - fix alignment problem with NaN and Inf globals
+
+ * kjs/fpconst.cpp: Move the contents of this file from here back to
+ value.cpp. The reason this was in a separate file is that the DARWIN
+ version of this used a declaration of the globals with a different
+ type to avoid creating "init routines". That's no longer necessary for
+ DARWIN and was never necessary for the non-DARWIN code path.
+ To make this patch easy to merge, I didn't actually delete this file
+ yet. We'll do that in a separate changeset.
+
+ * kjs/value.cpp: If C99's NAN and INFINITY are present, then use them,
+ othrewise use the union trick from fpconst.cpp. I think it would be
+ better to eliminate KJS::NaN and KJS::Inf and just use NAN and INFINITY
+ directly or std::numeric_limits<double>::quiet_nan() and
+ std::numeric_limits<double>::infinity(). But when I tried that, it
+ slowed down SunSpider. Someone else could do that cleanup if they
+ could do it without slowing down the engine.
+
+2008-01-07 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Added
+ JavaScript.h to the project.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make:
+ Copy JavaScript.h to WEBKITOUTPUTDIR.
+
+2008-01-07 Timothy Hatcher <timothy@apple.com>
+
+ Reviewed by Darin.
+
+ Fix Mac build.
+
+ * API/JSNode.c:
+ * API/JSNode.h:
+ * API/JSNodeList.c:
+ * API/JSNodeList.h:
+ * API/JavaScript.h:
+ * API/JavaScriptCore.h:
+ * API/minidom.c:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-01-07 Alp Toker <alp@atoker.com>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16029
+ JavaScriptCore.h is not suitable for platforms other than Mac OS X
+
+ Introduce a new JavaScriptCore/JavaScript.h public API header. This
+ should be used by all new portable code using the JavaScriptCore API.
+
+ JavaScriptCore/JavaScriptCore.h will remain for compatibility with
+ existing applications that depend on it including JSStringRefCF.h
+ which isn't portable.
+
+ Also add minidom to the GTK+/autotools build since we can now support
+ it on all platforms.
+
+ * API/JSNode.h:
+ * API/JSNodeList.h:
+ * API/JavaScript.h: Added.
+ * API/JavaScriptCore.h:
+ * ForwardingHeaders/JavaScriptCore/JavaScript.h: Added.
+ * GNUmakefile.am:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2008-01-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Abstract all DateObject.set* functions in preparation for fixing:
+ http://bugs.webkit.org/show_bug.cgi?id=16753
+
+ SunSpider had random changes here and there but was overall a wash.
+
+ * kjs/date_object.cpp:
+ (KJS::fillStructuresUsingTimeArgs):
+ (KJS::setNewValueFromTimeArgs):
+ (KJS::setNewValueFromDateArgs):
+ (KJS::DateProtoFuncSetMilliSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMilliseconds::callAsFunction):
+ (KJS::DateProtoFuncSetSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetUTCSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetMinutes::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMinutes::callAsFunction):
+ (KJS::DateProtoFuncSetHours::callAsFunction):
+ (KJS::DateProtoFuncSetUTCHours::callAsFunction):
+ (KJS::DateProtoFuncSetDate::callAsFunction):
+ (KJS::DateProtoFuncSetUTCDate::callAsFunction):
+ (KJS::DateProtoFuncSetMonth::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMonth::callAsFunction):
+ (KJS::DateProtoFuncSetFullYear::callAsFunction):
+ (KJS::DateProtoFuncSetUTCFullYear::callAsFunction):
+
+2008-01-06 Nikolas Zimmermann <zimmermann@kde.org>
+
+ Reviewed by Dan.
+
+ Add new helper function isArabicChar - SVG Fonts support needs it.
+
+ * wtf/unicode/icu/UnicodeIcu.h:
+ (WTF::Unicode::isArabicChar):
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::isArabicChar):
+
+2008-01-06 Alp Toker <alp@atoker.com>
+
+ Reviewed by Mark Rowe.
+
+ Use $(EXEEXT) to account for the .exe extension in the GTK+ Windows
+ build. (This is already done correctly in DerivedSources.make.) Issue
+ noticed by Mikkel when building in Cygwin.
+
+ Add a missing slash. This was a hack from the qmake build system that
+ isn't necessary with autotools.
+
+ * GNUmakefile.am:
+
+2008-01-05 Darin Adler <darin@apple.com>
+
+ * API/JSRetainPtr.h: One more file that needed the change below.
+
+2008-01-05 Darin Adler <darin@apple.com>
+
+ * wtf/OwnPtr.h: OwnPtr needs the same fix as RefPtr below.
+
+2008-01-05 Adam Roben <aroben@apple.com>
+
+ Build fix.
+
+ Reviewed by Maciej.
+
+ * wtf/RetainPtr.h: Use PtrType instead of T* because of the
+ RemovePointer magic.
+
+2008-01-05 Darin Adler <darin@apple.com>
+
+ Rubber stamped by Maciej Stachowiak.
+
+ - cut down own PIC branches by using a pointer-to-member-data instead of a
+ pointer-to-member-function in WTF smart pointers
+
+ * wtf/OwnArrayPtr.h:
+ * wtf/OwnPtr.h:
+ * wtf/PassRefPtr.h:
+ * wtf/RefPtr.h:
+ * wtf/RetainPtr.h:
+ Use a pointer to the m_ptr member instead of the get member.
+ The GCC compiler generates better code for this idiom.
+
+2008-01-05 Henry Mason <hmason@mac.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16738
+ Bug 16738: Collector block offset could be stored as an cell offset instead of a byte offset
+
+ Gives a 0.4% SunSpider boost and prettier code.
+
+ * kjs/collector.cpp: Switched to cell offsets from byte offsets
+ (KJS::Collector::heapAllocate):
+ (KJS::Collector::sweep):
+
+2008-01-04 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Have the two malloc zones print useful diagnostics if their free method are unexpectedly invoked.
+ Due to <rdar://problem/5671357> this can happen if an application attempts to free a pointer that
+ was not allocated by any registered malloc zone on the system.
+
+ * kjs/CollectorHeapIntrospector.h:
+ * wtf/FastMalloc.cpp:
+
+2008-01-04 Alp Toker <alp@atoker.com>
+
+ GTK+ autotools build fix. Terminate empty rules.
+
+ * GNUmakefile.am:
+
+2008-01-03 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Fix compilation with gcc 4.3: limits.h is needed for INT_MAX.
+
+ * pcre/pcre_exec.cpp:
+
+2008-01-03 Darin Adler <darin@apple.com>
+
+ * tests/mozilla/expected.html: The fix for bug 16696 also fixed a test
+ case, ecma_3/RegExp/perlstress-002.js, so updated results to expect
+ that test to succeed.
+
+2008-01-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16696
+ JSCRE fails fails to match Acid3 regexp
+
+ Test: fast/regex/early-acid3-86.html
+
+ The problem was with the cutoff point between backreferences and octal
+ escape sequences. We need to determine the cutoff point by counting the
+ total number of capturing brackets, which requires an extra pass through
+ the expression when compiling it.
+
+ * pcre/pcre_compile.cpp:
+ (CompileData::CompileData): Added numCapturingBrackets. Removed some
+ unused fields.
+ (compileBranch): Use numCapturingBrackets when calling checkEscape.
+ (calculateCompiledPatternLength): Use numCapturingBrackets when calling
+ checkEscape, and also store the bracket count at the end of the compile.
+ (jsRegExpCompile): Call calculateCompiledPatternLength twice -- once to
+ count the number of brackets and then a second time to calculate the length.
+
+2008-01-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16696
+ JSCRE fails fails to match Acid3 regexp
+
+ Test: fast/regex/early-acid3-86.html
+
+ The problem was with the cutoff point between backreferences and octal
+ escape sequences. We need to determine the cutoff point by counting the
+ total number of capturing brackets, which requires an extra pass through
+ the expression when compiling it.
+
+ * pcre/pcre_compile.cpp:
+ (CompileData::CompileData): Added numCapturingBrackets. Removed some
+ unused fields.
+ (compileBranch): Use numCapturingBrackets when calling checkEscape.
+ (calculateCompiledPatternLength): Use numCapturingBrackets when calling
+ checkEscape, and also store the bracket count at the end of the compile.
+ (jsRegExpCompile): Call calculateCompiledPatternLength twice -- once to
+ count the number of brackets and then a second time to calculate the length.
+
+2008-01-02 David Kilzer <ddkilzer@webkit.org>
+
+ Reviewed and landed by Darin.
+
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::execute): Added a missing return.
+
+2008-01-02 Darin Adler <darin@apple.com>
+
+ - try to fix Qt build
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::foldCase): Add some missing const.
+
+2008-01-02 Alice Liu <alice.liu@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ need to export ASCIICType.h for use in DRT
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * wtf/ASCIICType.h:
+ (WTF::isASCIIUpper):
+
+2008-01-02 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Beth Dakin.
+
+ Cleanup error_object.h/cpp.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/error_object.cpp:
+ (KJS::ErrorInstance::ErrorInstance):
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::ErrorProtoFuncToString::ErrorProtoFuncToString):
+ (KJS::ErrorProtoFuncToString::callAsFunction):
+ (KJS::ErrorObjectImp::ErrorObjectImp):
+ (KJS::ErrorObjectImp::implementsConstruct):
+ (KJS::ErrorObjectImp::construct):
+ (KJS::ErrorObjectImp::callAsFunction):
+ (KJS::NativeErrorPrototype::NativeErrorPrototype):
+ (KJS::NativeErrorImp::NativeErrorImp):
+ (KJS::NativeErrorImp::implementsConstruct):
+ (KJS::NativeErrorImp::construct):
+ (KJS::NativeErrorImp::callAsFunction):
+ (KJS::NativeErrorImp::mark):
+ * kjs/error_object.h:
+ (KJS::ErrorInstance::classInfo):
+ (KJS::NativeErrorImp::classInfo):
+
+2008-01-02 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Alp Toker.
+
+ * GNUmakefile.am: Add missing dependency on grammar.y.
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - fix for http://bugs.webkit.org/show_bug.cgi?id=16695
+ JSC allows non-identifier codepoints in identifiers (affects Acid3)
+
+ Test: fast/js/kde/parse.html
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::lex): Added additional states to distinguish Unicode escapes at the
+ start of identifiers from ones inside identifiers. Rejected characters that don't pass
+ the isIdentStart and isIdentPart tests.
+ (KJS::Lexer::convertUnicode): Removed incorrect FIXME comment.
+
+ * kjs/lexer.h: Added new states to distinguish \u escapes at the start of identifiers
+ from \u escapes inside identifiers.
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ - rolled scope chain optimization out; it was breaking the world
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16685
+ eliminate List::empty() to cut down on PIC branches
+
+ Also included one other speed-up -- remove the call to reserveCapacity from
+ FunctionBodyNode::processDeclarations in all but the most unusual cases.
+
+ Together these make SunSpider 1.016x as fast.
+
+ * JavaScriptCore.exp: Updated.
+ * kjs/ExecState.cpp:
+ (KJS::globalEmptyList): Added. Called only when creating global ExecState
+ instances.
+ (KJS::ExecState::ExecState): Broke constructor up into three separate functions,
+ for the three separate node types. Also went through each of the three and
+ streamlined as much as possible, removing dead code. This prevents us from having
+ to access the global in the function body version of the constructor.
+
+ * kjs/ExecState.h: Added emptyList(). Replaced the constructor with a set of
+ three that are specific to the different node types that can create new execution
+ state objects.
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFuncToLocaleString::callAsFunction): Use exec->emptyList() instead
+ of List::empty().
+ (KJS::ArrayProtoFuncConcat::callAsFunction): Ditto.
+ (KJS::ArrayProtoFuncSlice::callAsFunction): Ditto.
+ (KJS::ArrayProtoFuncSplice::callAsFunction): Ditto.
+ (KJS::ArrayProtoFuncFilter::callAsFunction): Ditto.
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction): Updated to call new ExecState constructor.
+ (KJS::GlobalFuncImp::callAsFunction): Ditto (for eval).
+ * kjs/function_object.cpp:
+ (FunctionObjectImp::construct): Use exec->emptyList() instead of List::empty().
+
+ * kjs/list.cpp: Removed List::empty.
+ * kjs/list.h: Ditto.
+
+ * kjs/nodes.cpp:
+ (KJS::ElementNode::evaluate): Use exec->emptyList() instead of List::empty().
+ (KJS::ArrayNode::evaluate): Ditto.
+ (KJS::ObjectLiteralNode::evaluate): Ditto.
+ (KJS::PropertyListNode::evaluate): Ditto.
+ (KJS::FunctionBodyNode::processDeclarations): Another speed-up. Check the capacity
+ before calling reserveCapacity, because it doesn't get inlined the local storage
+ vector is almost always big enough -- saving the function call overhead is a big
+ deal.
+ (KJS::FuncDeclNode::makeFunction): Use exec->emptyList() instead of List::empty().
+ (KJS::FuncExprNode::evaluate): Ditto.
+ * kjs/object.cpp:
+ (KJS::tryGetAndCallProperty): Ditto.
+ * kjs/property_slot.cpp:
+ (KJS::PropertySlot::functionGetter): Ditto.
+ * kjs/string_object.cpp:
+ (KJS::StringProtoFuncSplit::callAsFunction): Ditto.
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16648
+ REGRESSION (r28165): Yuku.com navigation prints "jsRegExpExecute failed with result -2"
+ <rdar://problem/5646486> REGRESSION (r28165): Layout test fast/regex/test1 fails intermittently
+
+ Fixes 34 failing test cases in the fast/regex/test1.html test.
+
+ Restored the stack which prevents infinite loops for brackets that match the empty
+ string; it had been removed as an optimization.
+
+ Unfortunately, restoring this stack causes the regular expression test in SunSpider
+ to be 1.095x as slow and the overall test to be 1.004x as slow. Maybe we can find
+ a correct optimization to restore the speed!
+
+ It's possible the original change was on the right track but just off by one.
+
+ * pcre/pcre_exec.cpp: Add back eptrblock, but name it BracketChainNode.
+ (MatchStack::pushNewFrame): Add back the logic needed here.
+ (startNewGroup): Ditto.
+ (match): Ditto.
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16683
+ speed up function calls by making ScopeChain::push cheaper
+
+ This gives a 1.019x speedup on SunSpider.
+
+ After doing this, I realized this probably will be obsolete when the optimization
+ to avoid creating an activation object is done. When we do that one we should check
+ if rolling this out will speed things up, since this does add overhead at the time
+ you copy the scope chain.
+
+ * kjs/object.h: Removed the ScopeChain::release function. It was
+ marked inline, and called in exactly one place, so moved it there.
+ No idea why it was in this header file!
+
+ * kjs/scope_chain.cpp: Removed the overload of the ScopeChain::push
+ function that takes another ScopeChain. It was unused. I think we used
+ it over in WebCore at one point, but not any more.
+
+ * kjs/scope_chain.h: Changed ScopeChainNode into a struct rather than
+ a class, got rid of its constructor so we can have one that's uninitialized,
+ and moved the refCount into a derived struct, ScopeChainHeapNode. Made _node
+ mutable so it can be changed in the moveToHeap function. Changed the copy
+ constructor and assignment operator to call moveToHeap, since the top node
+ can't be shared when it's embedded in another ScopeChain object. Updated
+ functions as needed to handle the case where the first object isn't on the
+ heap or to add casts for cases where it's guaranteed to be. Changed the push
+ function to always put the new node into the ScopeChain object; it will get
+ put onto the heap when needed later.
+
+2008-01-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed slight logic error in reserveCapacity, where we would reallocate
+ the storage buffer unnecessarily.
+
+ * wtf/Vector.h:
+ (WTF::::reserveCapacity): No need to grow the buffer if newCapacity is
+ equal to capacity().
+
+2008-01-01 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16684
+ eliminate debugger overhead from function body execution
+
+ Speeds SunSpider up 1.003x. That's a small amount, but measurable.
+
+ * JavaScriptCore.exp: Updated.
+ * kjs/Parser.h:
+ (KJS::Parser::parse): Create the node with a static member function named create() instead
+ of using new explicitly.
+
+ * kjs/grammar.y: Changed calls to new FunctionBodyNode to use FunctionBodyNode::create().
+
+ * kjs/nodes.cpp:
+ (KJS::ProgramNode::create): Added. Calls new.
+ (KJS::EvalNode::create): Ditto.
+ (KJS::FunctionBodyNode::create): Ditto, but creates FunctionBodyNodeWithDebuggerHooks
+ when a debugger is present.
+ (KJS::FunctionBodyNode::execute): Removed debugger hooks.
+ (KJS::FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks): Added.
+ (KJS::FunctionBodyNodeWithDebuggerHooks::execute): Calls the debugger, then the code,
+ then the debugger again.
+
+ * kjs/nodes.h: Added create functions, made the constructors private and protected.
+
+2007-12-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ More small cleanup to array_object.cpp
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFuncToString::callAsFunction):
+ (KJS::ArrayProtoFuncToLocaleString::callAsFunction):
+ (KJS::ArrayProtoFuncJoin::callAsFunction):
+ (KJS::ArrayProtoFuncConcat::callAsFunction):
+ (KJS::ArrayProtoFuncReverse::callAsFunction):
+ (KJS::ArrayProtoFuncShift::callAsFunction):
+ (KJS::ArrayProtoFuncSlice::callAsFunction):
+ (KJS::ArrayProtoFuncSort::callAsFunction):
+ (KJS::ArrayProtoFuncSplice::callAsFunction):
+ (KJS::ArrayProtoFuncUnShift::callAsFunction):
+ (KJS::ArrayProtoFuncFilter::callAsFunction):
+ (KJS::ArrayProtoFuncMap::callAsFunction):
+ (KJS::ArrayProtoFuncEvery::callAsFunction):
+
+2007-12-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Apply wkstyle to array_object.cpp
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayPrototype::ArrayPrototype):
+ (KJS::ArrayPrototype::getOwnPropertySlot):
+ (KJS::ArrayProtoFuncConcat::callAsFunction):
+ (KJS::ArrayProtoFuncPop::callAsFunction):
+ (KJS::ArrayProtoFuncReverse::callAsFunction):
+ (KJS::ArrayProtoFuncShift::callAsFunction):
+ (KJS::ArrayProtoFuncSlice::callAsFunction):
+ (KJS::ArrayProtoFuncSort::callAsFunction):
+ (KJS::ArrayProtoFuncSplice::callAsFunction):
+ (KJS::ArrayProtoFuncUnShift::callAsFunction):
+ (KJS::ArrayProtoFuncFilter::callAsFunction):
+ (KJS::ArrayProtoFuncMap::callAsFunction):
+ (KJS::ArrayProtoFuncEvery::callAsFunction):
+ (KJS::ArrayProtoFuncLastIndexOf::callAsFunction):
+ (KJS::ArrayObjectImp::ArrayObjectImp):
+ (KJS::ArrayObjectImp::implementsConstruct):
+ (KJS::ArrayObjectImp::construct):
+ (KJS::ArrayObjectImp::callAsFunction):
+
+2007-12-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Remove maxInt/minInt, replacing with std:max/min<int>()
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFuncSplice::callAsFunction):
+ * kjs/operations.cpp:
+ * kjs/operations.h:
+
+2007-12-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Update Number.toString to properly throw exceptions.
+ Cleanup code in Number.toString implementation.
+
+ * kjs/number_object.cpp:
+ (KJS::numberToString):
+ * kjs/object.cpp:
+ (KJS::Error::create): Remove bogus debug lines.
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ ASSERT when debugging via Drosera due to missed var lookup optimization.
+ http://bugs.webkit.org/show_bug.cgi?id=16634
+
+ No test case possible.
+
+ * kjs/nodes.cpp:
+ (KJS::BreakpointCheckStatement::optimizeVariableAccess):
+ * kjs/nodes.h:
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ Fix (-0).toFixed() and re-factor a little
+ Fix (-0).toExponential() and printing of trailing 0s in toExponential
+ Fix toPrecision(nan) handling
+ http://bugs.webkit.org/show_bug.cgi?id=16640
+
+ * kjs/number_object.cpp:
+ (KJS::numberToFixed):
+ (KJS::fractionalPartToString):
+ (KJS::numberToExponential):
+ (KJS::numberToPrecision):
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ More changes to make number code readable
+
+ * kjs/number_object.cpp:
+ (KJS::integer_part_noexp):
+ (KJS::numberToFixed):
+ (KJS::numberToExponential):
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ More small cleanups to toPrecision
+
+ * kjs/number_object.cpp:
+ (KJS::numberToPrecision):
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ More small attempts to make number code readable
+
+ * kjs/number_object.cpp:
+ (KJS::exponentialPartToString):
+ (KJS::numberToExponential):
+ (KJS::numberToPrecision):
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Break out callAsFunction implementations into static functions
+
+ * kjs/number_object.cpp:
+ (KJS::numberToString):
+ (KJS::numberToFixed):
+ (KJS::numberToExponential):
+ (KJS::numberToPrecision):
+ (KJS::NumberProtoFunc::callAsFunction):
+
+2007-12-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Apply wkstyle/astyle and fix placement of *
+
+ * kjs/number_object.cpp:
+ (KJS::NumberInstance::NumberInstance):
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::NumberProtoFunc::NumberProtoFunc):
+ (KJS::integer_part_noexp):
+ (KJS::intPow10):
+ (KJS::NumberProtoFunc::callAsFunction):
+ (KJS::NumberObjectImp::NumberObjectImp):
+ (KJS::NumberObjectImp::getOwnPropertySlot):
+ (KJS::NumberObjectImp::getValueProperty):
+ (KJS::NumberObjectImp::implementsConstruct):
+ (KJS::NumberObjectImp::construct):
+ (KJS::NumberObjectImp::callAsFunction):
+ * kjs/object.cpp:
+ (KJS::JSObject::put):
+
+2007-12-27 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ ASSERT in JavaScriptCore while viewing WICD test case
+ http://bugs.webkit.org/show_bug.cgi?id=16626
+
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::execute): move KJS_CHECK_EXCEPTION to proper place
+
+2007-12-26 Jan Michael Alonzo <jmalonzo@unpluggable.com>
+
+ Reviewed by Alp Toker.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16390
+ Use autotools or GNU make as the build system for the GTK port
+
+ * GNUmakefile.am: Added.
+
+2007-12-25 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - Remove unnecessary redundant check from property setting
+ http://bugs.webkit.org/show_bug.cgi?id=16602
+
+ 1.3% speedup on SunSpider.
+
+ * kjs/object.cpp:
+ (KJS::JSObject::put): Don't do canPut check when not needed; let
+ the PropertyMap handle it.
+ (KJS::JSObject::canPut): Don't check the static property
+ table. lookupPut does that already.
+
+2007-12-24 Alp Toker <alp@atoker.com>
+
+ Fix builds that don't use AllInOneFile.cpp following breakage
+ introduced in r28973.
+
+ * kjs/grammar.y:
+
+2007-12-24 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Eric.
+
+ - Optimize variable declarations
+ http://bugs.webkit.org/show_bug.cgi?id=16585
+
+ 3.5% speedup on SunSpider.
+
+ var statements now result in either assignments or empty statements.
+
+ This allows a couple of optimization opportunities:
+ - No need to branch at runtime to check if there is an initializer
+ - EmptyStatementNodes can be removed entirely (also done in this patch)
+ - Assignment expressions get properly optimized for local variables
+
+ This patch also includes some code cleanup:
+ - Most of the old VarStatement/VarDecl logic is now only used for const declarations,
+ thus it is renamed appropriately
+ - AssignExprNode is gone
+
+ * JavaScriptCore.exp:
+ * kjs/NodeInfo.h:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::SourceElements::append):
+ (KJS::ConstDeclNode::ConstDeclNode):
+ (KJS::ConstDeclNode::optimizeVariableAccess):
+ (KJS::ConstDeclNode::handleSlowCase):
+ (KJS::ConstDeclNode::evaluateSingle):
+ (KJS::ConstDeclNode::evaluate):
+ (KJS::ConstStatementNode::optimizeVariableAccess):
+ (KJS::ConstStatementNode::execute):
+ (KJS::VarStatementNode::optimizeVariableAccess):
+ (KJS::VarStatementNode::execute):
+ (KJS::ForInNode::ForInNode):
+ (KJS::ForInNode::optimizeVariableAccess):
+ (KJS::ForInNode::execute):
+ (KJS::FunctionBodyNode::initializeSymbolTable):
+ (KJS::ProgramNode::initializeSymbolTable):
+ (KJS::FunctionBodyNode::processDeclarations):
+ (KJS::ProgramNode::processDeclarations):
+ (KJS::EvalNode::processDeclarations):
+ * kjs/nodes.h:
+ (KJS::DeclarationStacks::):
+ (KJS::StatementNode::):
+ (KJS::ConstDeclNode::):
+ (KJS::ConstStatementNode::):
+ (KJS::EmptyStatementNode::):
+ (KJS::VarStatementNode::):
+ (KJS::ForNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::ConstDeclNode::streamTo):
+ (KJS::ConstStatementNode::streamTo):
+ (KJS::ScopeNode::streamTo):
+ (KJS::VarStatementNode::streamTo):
+ (KJS::ForNode::streamTo):
+ (KJS::ForInNode::streamTo):
+
+2007-12-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ * JavaScriptCore.exp: Remove unused symbol to prevent a weak external symbol
+ being generated in JavaScriptCore.framework.
+
+2007-12-21 Darin Adler <darin@apple.com>
+
+ Requested by Maciej.
+
+ * kjs/nodes.h: Use the new NEVER_INLINE here and eliminate the old
+ KJS_NO_INLINE. We don't want to have two, and we figured it was better
+ to keep the one that's in WTF.
+
+2007-12-21 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16561
+ remove debugger overhead from non-debugged JavaScript execution
+
+ 1.022x as fast on SunSpider.
+
+ * JavaScriptCore.exp: Updated.
+
+ * kjs/NodeInfo.h: Renamed SourceElementsStub to SourceElements,
+ since that more accurately describes the role of this object, which
+ is a reference-counted wrapper for a Vector.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::didFinishParsing): Changed parameter type to SourceElements,
+ and use plain assignment instead of set.
+ * kjs/Parser.h: Changed parameter type of didFinishParsing to a
+ SourceElements. Also changed m_sourceElements; we now use a RefPtr instead
+ of an OwnPtr as well.
+
+ * kjs/grammar.y: Got rid of all the calls to release() on SourceElements.
+ That's now handed inside the constructors for various node types, since we now
+ use vector swapping instead.
+
+ * kjs/nodes.cpp:
+ (KJS::Node::rethrowException): Added NEVER_INLINE, because this was getting inlined
+ and we want exception handling out of the normal code flow.
+ (KJS::SourceElements::append): Moved here from the header. This now handles
+ creating a BreakpointCheckStatement for each statement in the debugger case.
+ That way we can get breakpoint handling without having it in every execute function.
+ (KJS::BreakpointCheckStatement::BreakpointCheckStatement): Added.
+ (KJS::BreakpointCheckStatement::execute): Added. Contains the code that was formerly
+ in the StatementNode::hitStatement function and the KJS_BREAKPOINT macro.
+ (KJS::BreakpointCheckStatement::streamTo): Added.
+ (KJS::ArgumentListNode::evaluateList): Use KJS_CHECKEXCEPTIONVOID since the return
+ type is void.
+ (KJS::VarStatementNode::execute): Removed KJS_BREAKPOINT.
+ (KJS::BlockNode::BlockNode): Changed parameter type to SourceElements.
+ Changed code to use release since the class now contains a vector rather than
+ a vector point.
+ (KJS::BlockNode::optimizeVariableAccess): Updated since member is now a vector
+ rather than a vector pointer.
+ (KJS::BlockNode::execute): Ditto.
+ (KJS::ExprStatementNode::execute): Removed KJS_BREAKPOINT.
+ (KJS::IfNode::execute): Ditto.
+ (KJS::IfElseNode::execute): Ditto.
+ (KJS::DoWhileNode::execute): Ditto.
+ (KJS::WhileNode::execute): Ditto.
+ (KJS::ContinueNode::execute): Ditto.
+ (KJS::BreakNode::execute): Ditto.
+ (KJS::ReturnNode::execute): Ditto.
+ (KJS::WithNode::execute): Ditto.
+ (KJS::CaseClauseNode::optimizeVariableAccess): Updated since member is now a vector
+ rather than a vector pointer.
+ (KJS::CaseClauseNode::executeStatements): Ditto.
+ (KJS::SwitchNode::execute): Removed KJS_BREAKPOINT.
+ (KJS::ThrowNode::execute): Ditto.
+ (KJS::TryNode::execute): Ditto.
+ (KJS::ScopeNode::ScopeNode): Changed parameter type to SourceElements.
+ (KJS::ProgramNode::ProgramNode): Ditto.
+ (KJS::EvalNode::EvalNode): Ditto.
+ (KJS::FunctionBodyNode::FunctionBodyNode): Ditto.
+ (KJS::ScopeNode::optimizeVariableAccess): Updated since member is now a vector
+ rather than a vector pointer.
+
+ * kjs/nodes.h: Removed hitStatement. Renamed SourceElements to StatementVector.
+ Renamed SourceElementsStub to SourceElements and made it derive from
+ ParserRefCounted rather than from Node, hold a vector rather than a pointer to
+ a vector, and changed the release function to swap with another vector rather
+ than the pointer idiom. Updated BlockNode and CaseClauseNode to hold actual
+ vectors instead of pointers to vectors. Added BreakpointCheckStatement.
+
+ * kjs/nodes2string.cpp:
+ (KJS::statementListStreamTo): Changed to work on a vector instead of a pointer
+ to a vector.
+ (KJS::BlockNode::streamTo): Ditto.
+ (KJS::CaseClauseNode::streamTo): Ditto.
+
+ * wtf/AlwaysInline.h: Added NEVER_INLINE.
+ * wtf/PassRefPtr.h: Tweaked formatting. Added clear() function that matches the
+ ones in OwnPtr and auto_ptr.
+ * wtf/RefPtr.h: Ditto.
+
+2007-12-21 Darin Adler <darin@apple.com>
+
+ - fix broken regression tests
+
+ The broken tests were fast/js/do-while-expression-value.html and
+ fast/js/while-expression-value.html.
+
+ * kjs/nodes.cpp: Check in the correct version of this file. I had accidentally landed
+ an old version of my patch for bug 16471.
+ (KJS::statementListExecute): The logic here was backwards. Have to set the value
+ even for non-normal execution results.
+
+2007-12-20 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Copy npruntime_internal.h
+ to WebKitBuild.
+
+2007-12-20 Eric Seidel <eric@webkit.org>
+
+ Reviewed by mjs.
+
+ Split IfNode into IfNode and IfElseNode for speedup.
+ http://bugs.webkit.org/show_bug.cgi?id=16470
+
+ SunSpider claims this is 1.003x as fast as before.
+ (This required running with --runs 15 to get consistent enough results to tell!)
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::IfNode::optimizeVariableAccess):
+ (KJS::IfNode::execute):
+ (KJS::IfNode::getDeclarations):
+ (KJS::IfElseNode::optimizeVariableAccess):
+ (KJS::IfElseNode::execute):
+ (KJS::IfElseNode::getDeclarations):
+ * kjs/nodes.h:
+ (KJS::IfNode::):
+ (KJS::IfElseNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::IfNode::streamTo):
+ (KJS::IfElseNode::streamTo):
+
+2007-12-20 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ * wtf/OwnPtr.h:
+ (WTF::operator==): Added.
+ (WTF::operator!=): Added.
+
+2007-12-20 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ AST optimization: Avoid NULL-checking ForNode's child nodes.
+
+ 0.6% speedup on SunSpider.
+
+ This is a proof of concept patch that demonstrates how to optimize
+ grammar productions with optional components, like
+
+ for (optional; optional; optional) {
+ ...
+ }
+
+ The parser emits NULL for an optional component that is not present.
+
+ Instead of checking for a NULL child at execution time, a node that
+ expects an optional component to be present more often than not checks
+ for a NULL child at construction time, and substitutes a viable
+ alternative node in its place.
+
+ (We'd like the parser to start emitting NULL a lot more once we teach
+ it to emit NULL for certain no-op productions like EmptyStatement and
+ VariableStatement, so, as a foundation, it's important for nodes with
+ NULL optional components to be fast.)
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::didFinishParsing): Check for NULL SourceElements. Also,
+ moved didFinishParsing into the .cpp file because adding a branch while
+ it was in the header file caused a substantial and inexplicable
+ performance regression. (Did I mention that GCC is crazy?)
+
+ * kjs/grammar.y:
+
+ * kjs/nodes.cpp:
+ (KJS::BlockNode::BlockNode): Check for NULL SourceElements.
+ (KJS::ForNode::optimizeVariableAccess): No need to check for NULL here.
+ (KJS::ForNode::execute): No need to check for NULL here.
+ * kjs/nodes.h:
+ (KJS::ForNode::): Check for NULL SourceElements. Substitute a TrueNode
+ because it's semantically harmless, and it evaluates to boolean in an
+ efficient manner.
+
+2007-12-20 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Slight logic reordering in JSImmediate::from(double)
+
+ This gives a 0.6% improvement in SunSpider.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::from):
+
+2007-12-20 Eric Seidel <eric@webkit.org>
+
+ Reviewed by mjs.
+
+ Fix major Array regression introduced by 28899.
+
+ SunSpider claims this is at least 1.37x as fast as pre-regression. :)
+
+ * kjs/array_instance.cpp: make Arrays fast again!
+
+2007-12-20 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Geoff, then re-rubber-stamped by Geoff after final search/replace and testing.
+
+ Small reworking of Date code for 4% speedup on Date tests (0.2% overall)
+ http://bugs.webkit.org/show_bug.cgi?id=16537
+
+ Make msToYear human-readable
+ Make msToDayInMonth slightly more readable and avoid recalculating msToYear
+ Remove use of isInLeapYear to avoid calling msToYear
+ Remove dayInYear call by changing msToDayInMonth to dayInMonthFromDayInYear
+ Remove more duplicate calls to dayInYear and getUTCOffset for further speedup
+
+ * kjs/DateMath.cpp:
+ (KJS::daysFrom1970ToYear):
+ (KJS::msToYear):
+ (KJS::monthFromDayInYear):
+ (KJS::checkMonth):
+ (KJS::dayInMonthFromDayInYear):
+ (KJS::dateToDayInYear):
+ (KJS::getDSTOffsetSimple):
+ (KJS::getDSTOffset):
+ (KJS::gregorianDateTimeToMS):
+ (KJS::msToGregorianDateTime):
+
+2007-12-20 Rodney Dawes <dobey@wayofthemonkey.com>
+
+ Reviewed by Darin Adler.
+
+ Proxy includes of npruntime.h or npapi.h through npruntime_internal.h
+ Include stdio.h in npapi.h for the use of FILE with XP_UNIX defined
+ This is for building with X11, as some type and enum names conflict
+ with #define names in X11 headers.
+ http://bugs.webkit.org/show_bug.cgi?id=15669
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bindings/NP_jsobject.h:
+ * bindings/npapi.h:
+ * bindings/npruntime.cpp:
+ * bindings/npruntime_impl.h:
+ * bindings/npruntime_priv.h:
+ * bindings/npruntime_internal.h:
+ * bindings/testbindings.cpp:
+ * bindings/c/c_class.h:
+ * bindings/c/c_runtime.h:
+ * bindings/c/c_utility.h:
+
+2007-12-20 Darin Adler <darin@apple.com>
+
+ - re-fix http://bugs.webkit.org/show_bug.cgi?id=16471
+ Completions need to be smaller (or not exist at all)
+
+ Same patch as last time with the test failures problem fixed.
+
+ * kjs/function.cpp:
+ (KJS::GlobalFuncImp::callAsFunction): Make sure to check the completion
+ type from newExec to see if the execute raised an exception.
+
+2007-12-20 Darin Adler <darin@apple.com>
+
+ - roll out that last change -- it was causing test failures;
+ I'll check it back in after fixing them
+
+2007-12-20 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16471
+ Completions need to be smaller (or not exist at all)
+
+ SuSpider shows 2.4% speedup.
+
+ Stop using completions in the execution engine.
+ Instead, the completion type and label target are both
+ stored in the ExecState.
+
+ * API/JSContextRef.cpp: Removed unneeded include of "completion.h".
+ * bindings/runtime_method.cpp: Removed unused execute function.
+ * bindings/runtime_method.h: Ditto.
+
+ * kjs/ExecState.h: Added completionType, breakOrContinueTarget,
+ setCompletionType, setNormalCompletion, setBreakCompletion,
+ setContinueCompletion, setReturnValueCompletion, setThrowCompletion,
+ setInterruptedCompletion, m_completionType, and m_breakOrContinueTarget.
+
+ * kjs/completion.h: Removed constructor and getter for target
+ for break and continue from Completion. This class is now only
+ used for the public API to Interpreter and such.
+
+ * kjs/date_object.h: Removed unused execute function.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction): Removed some unneeded
+ exception processing. Updated to call the new execute function
+ and to get the completion type from the ExecState. Merged in
+ the execute function, which repeated some of the same logic and
+ was called only from here.
+ (KJS::GlobalFuncImp::callAsFunction): More of the same for eval.
+ * kjs/function.h: Removed execute.
+
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate): Added code to convert the result of
+ execut into a Completion.
+
+ * kjs/nodes.cpp:
+ (KJS::Node::setErrorCompletion): Renamed from createErrorCompletion.
+ Now sets the completion type in the ExecState.
+ (KJS::Node::rethrowException): Now sets the completion type in the
+ ExecState.
+ (KJS::StatementNode::hitStatement): Now sets the completion type in
+ the ExecState.
+ (KJS::VarStatementNode::execute): Updated to put completion type in
+ the ExecState instead of a Completion object.
+ (KJS::statementListExecute): Ditto. Also changed the for loop to use
+ indices instead of iterators.
+ (KJS::BlockNode::execute): Updated return type.
+ (KJS::EmptyStatementNode::execute): Updated to put completion type in
+ the ExecState instead of a Completion object.
+ (KJS::ExprStatementNode::execute): Ditto.
+ (KJS::IfNode::execute): Ditto.
+ (KJS::DoWhileNode::execute): Ditto. Also streamlined the logic a little
+ to make the normal case a little faster and moved the end outside the
+ loop so that "break" can do a break.
+ (KJS::WhileNode::execute): Ditto.
+ (KJS::ForNode::execute): Ditto.
+ (KJS::ForInNode::execute): Ditto.
+ (KJS::ContinueNode::execute): Updated to put completion type in
+ the ExecState instead of a Completion object.
+ (KJS::BreakNode::execute): Ditto.
+ (KJS::ReturnNode::execute): Ditto.
+ (KJS::WithNode::execute): Ditto.
+ (KJS::CaseClauseNode::executeStatements): Ditto. Also renamed to have
+ execute in its name to reflect the fact that it's a member of the same
+ family of functions.
+ (KJS::CaseBlockNode::executeBlock): Ditto.
+ (KJS::SwitchNode::execute): Ditto.
+ (KJS::LabelNode::execute): Ditto.
+ (KJS::ThrowNode::execute): Ditto.
+ (KJS::TryNode::execute): Ditto.
+ (KJS::ProgramNode::execute): Ditto.
+ (KJS::EvalNode::execute): Ditto.
+ (KJS::FunctionBodyNode::execute): Ditto.
+ (KJS::FuncDeclNode::execute): Ditto.
+
+ * kjs/nodes.h: Renamed setErrorCompletion to createErrorCompletion, made
+ hitStatement protected, changed return value of execute to a JSValue,
+ renamed evalStatements to executeStatements, and evalBlock to executeBlock.
+
+ * kjs/number_object.h: Removed unused execute function.
+
+2007-12-20 Geoffrey Garen <ggaren@apple.com>
+
+ Added Radar number.
+
+ * kjs/nodes.cpp:
+ (KJS::ProgramNode::processDeclarations):
+
+2007-12-20 Geoffrey Garen <ggaren@apple.com>
+
+ Linux build fix: config.h has to come first.
+
+ * kjs/error_object.cpp:
+
+2007-12-19 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Optimized global access to global variables, using a symbol table.
+
+ SunSpider reports a 1.5% overall speedup, a 6.2% speedup on 3d-morph,
+ and a whopping 33.1% speedup on bitops-bitwise-and.
+
+ * API/JSCallbackObjectFunctions.h: Replaced calls to JSObject:: with
+ calls to Base::, since JSObject is not always our base class. This
+ was always a bug, but the bug is even more apparent after some of my
+ changes.
+
+ (KJS::::staticFunctionGetter): Replaced use of getDirect with call to
+ getOwnPropertySlot. Global declarations are no longer stored in the
+ property map, so a call to getDirect is insufficient for finding
+ override properties.
+
+ * API/testapi.c:
+ * API/testapi.js: Added test for the getDirect change mentioned above.
+
+ * kjs/ExecState.cpp:
+ * kjs/ExecState.h: Dialed back the optimization to store a direct
+ pointer to the localStorage buffer. One ExecState can grow the global
+ object's localStorage without another ExecState's knowledge, so
+ ExecState can't store a direct pointer to the localStorage buffer
+ unless/until we invent a way to update all the relevant ExecStates.
+
+ * kjs/JSGlobalObject.cpp: Inserted the symbol table into get and put
+ operations.
+ (KJS::JSGlobalObject::reset): Reset the symbol table and local storage,
+ too. Also, clear the property map here, removing the need for a
+ separate call.
+
+ * kjs/JSVariableObject.cpp:
+ * kjs/JSVariableObject.h: Added support for saving localStorage and the
+ symbol table to the back/forward cache, and restoring them.
+
+ * kjs/function.cpp:
+ (KJS::GlobalFuncImp::callAsFunction): Renamed progNode to evalNode
+ because it's an EvalNode, not a ProgramNode.
+
+ * kjs/lookup.h:
+ (KJS::cacheGlobalObject): Replaced put with faster putDirect, since
+ that's how the rest of lookup.h works. putDirect is safe here because
+ cacheGlobalObject is only used for objects whose names are not valid
+ identifiers.
+
+ * kjs/nodes.cpp: The good stuff!
+
+ (KJS::EvalNode::processDeclarations): Replaced hasProperty with
+ the new hasOwnProperty, which is slightly faster.
+
+ * kjs/object.h: Nixed clearProperties because clear() does this job now.
+
+ * kjs/property_map.cpp:
+ * kjs/property_map.h: More back/forward cache support.
+
+ * wtf/Vector.h:
+ (WTF::::grow): Added fast non-branching grow function. I used it in
+ an earlier version of this patch, even though it's not used anymore.
+
+2007-12-09 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Build fix for non-Mac platforms. Move NodeInfo into its own header so that the YYTYPE
+ declaration in grammar.h is able to declare members of that type.
+
+ * kjs/NodeInfo.h: Added.
+ (KJS::createNodeInfo):
+ (KJS::mergeDeclarationLists):
+ (KJS::appendToVarDeclarationList):
+ * kjs/grammar.y:
+ * kjs/lexer.cpp:
+
+2007-12-19 Oliver Hunt <oliver@apple.com>
+
+ Make appendToVarDeclarationList static
+
+ RS=Weinig.
+
+ * kjs/grammar.y:
+
+2007-12-18 Oliver Hunt <oliver@apple.com>
+
+ Remove dead code due to removal of post-parse declaration discovery.
+
+ RS=Geoff.
+
+ Due to the removal of the declaration discovery pass after parsing we
+ no longer need any of the logic used for that discovery.
+
+ * kjs/nodes.cpp:
+ (KJS::Node::Node):
+ (KJS::VarDeclNode::VarDeclNode):
+ (KJS::BlockNode::BlockNode):
+ (KJS::ForInNode::ForInNode):
+ (KJS::CaseBlockNode::CaseBlockNode):
+ * kjs/nodes.h:
+ (KJS::VarStatementNode::):
+ (KJS::IfNode::):
+ (KJS::DoWhileNode::):
+ (KJS::WhileNode::):
+ (KJS::WithNode::):
+ (KJS::LabelNode::):
+ (KJS::TryNode::):
+ (KJS::FuncDeclNode::):
+ (KJS::CaseClauseNode::):
+ (KJS::ClauseListNode::):
+ (KJS::SwitchNode::):
+
+2007-12-18 Oliver Hunt <oliver@apple.com>
+
+ Replace post-parse pass to find declarations with logic in the parser itself
+
+ Reviewed by Geoff.
+
+ Instead of finding declarations in a pass following the initial parsing of
+ a program, we incorporate the logic directly into the parser. This lays
+ the groundwork for further optimisations (such as improving performance in
+ declaration expressions -- var x = y; -- to match that of standard assignment)
+ in addition to providing a 0.4% performance improvement in SunSpider.
+
+ * JavaScriptCore.exp:
+ * kjs/Parser.cpp:
+ (KJS::Parser::parse):
+ * kjs/Parser.h:
+ (KJS::Parser::didFinishParsing):
+ (KJS::Parser::parse):
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ParserTracked::ParserTracked):
+ (KJS::ParserTracked::~ParserTracked):
+ (KJS::ParserTracked::ref):
+ (KJS::ParserTracked::deref):
+ (KJS::ParserTracked::refcount):
+ (KJS::ParserTracked::clearNewTrackedObjects):
+ (KJS::Node::Node):
+ (KJS::ScopeNode::ScopeNode):
+ (KJS::ProgramNode::ProgramNode):
+ (KJS::EvalNode::EvalNode):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::FunctionBodyNode::initializeSymbolTable):
+ (KJS::FunctionBodyNode::processDeclarations):
+ * kjs/nodes.h:
+ (KJS::ParserTracked::):
+ (KJS::Node::):
+ (KJS::ScopeNode::):
+
+2007-12-18 Xan Lopez <xan@gnome.org>
+
+ Reviewed by Geoff.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=14521
+ Bug 14521: JavaScriptCore fails to build on Linux/PPC gcc 4.1.2
+
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::Unlock):
+
+ Use less strict memory operand constraint on inline asm generation.
+ PLATFORM(DARWIN) left unpatched due to Apple's GCC bug.
+
+ Patch by David Kilzer <ddkilzer@webkit.org>
+
+2007-12-18 Mark Rowe <mrowe@apple.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Remove outdated and non-functioning project files for the Apollo port.
+
+ * JavaScriptCore.apolloproj: Removed.
+
+2007-12-18 Darin Adler <darin@apple.com>
+
+ - fix Windows build
+
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute): Change back from false/true to 0/1 -- I probably should not have
+ deleted MATCH_MATCH and MATCH_NOMATCH, but I'm going to leave them out.
+
+2007-12-18 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16458
+ REGRESSION (r28164): regular expressions can now hang due to lack of a match limit
+ <rdar://problem/5636067>
+
+ Test: fast/regex/slow.html
+
+ Slows down SunSpider a bit (about 1.01x); filed a bug to follow up on that:
+ http://bugs.webkit.org/show_bug.cgi?id=16503
+
+ * pcre/pcre.h: Changed name of error code to not specifically mention "recursion".
+ * pcre/pcre_exec.cpp:
+ (match): Replaced the depth limit, MATCH_RECURSION_LIMIT, with a total match looping
+ limit, matchLimit. Also eliminated the constants for MATCH_MATCH and MATCH_NOMATCH,
+ since they are just true and false (1 and 0).
+ (jsRegExpExecute): More of the MATCH_MATCH change.
+
+2007-12-17 Darin Adler <darin@apple.com>
+
+ - speculative build fix for non-gcc platforms
+
+ * pcre/pcre_exec.cpp: (match): Remove unused cases from return switch.
+
+2007-12-16 Mark Rowe <mrowe@apple.com>
+
+ Speculative build fix for non-Mac platforms.
+
+ * pcre/pcre_compile.cpp: Include string.h for memset, memmove, etc.
+
+2007-12-16 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=16438
+ - removed some more unused code
+ - changed quite a few more names to WebKit-style
+ - moved more things out of pcre_internal.h
+ - changed some indentation to WebKit-style
+ - improved design of the functions for reading and writing
+ 2-byte values from the opcode stream (in pcre_internal.h)
+
+ * pcre/dftables.cpp:
+ (main): Added the kjs prefix a normal way in lieu of using macros.
+
+ * pcre/pcre_compile.cpp: Moved some definitions here from pcre_internal.h.
+ (errorText): Name changes, fewer typedefs.
+ (checkEscape): Ditto. Changed uppercase conversion to use toASCIIUpper.
+ (isCountedRepeat): Name change.
+ (readRepeatCounts): Name change.
+ (firstSignificantOpcode): Got rid of the use of OP_lengths, which is
+ very lightly used here. Hard-coded the length of OP_BRANUMBER.
+ (firstSignificantOpcodeSkippingAssertions): Ditto. Also changed to
+ use the advanceToEndOfBracket function.
+ (getOthercaseRange): Name changes.
+ (encodeUTF8): Ditto.
+ (compileBranch): Name changes. Removed unused after_manual_callout and
+ the code to handle it. Removed code to handle OP_ONCE since we never
+ emit this opcode. Changed to use advanceToEndOfBracket in more places.
+ (compileBracket): Name changes.
+ (branchIsAnchored): Removed code to handle OP_ONCE since we never emit
+ this opcode.
+ (bracketIsAnchored): Name changes.
+ (branchNeedsLineStart): More fo the same.
+ (bracketNeedsLineStart): Ditto.
+ (branchFindFirstAssertedCharacter): Removed OP_ONCE code.
+ (bracketFindFirstAssertedCharacter): More of the same.
+ (calculateCompiledPatternLengthAndFlags): Ditto.
+ (returnError): Name changes.
+ (jsRegExpCompile): Ditto.
+
+ * pcre/pcre_exec.cpp: Moved some definitions here from pcre_internal.h.
+ (matchRef): Updated names.
+ Improved macros to use the do { } while(0) idiom so they expand to single
+ statements rather than to blocks or multiple statements. And refeactored
+ the recursive match macros.
+ (MatchStack::pushNewFrame): Name changes.
+ (getUTF8CharAndIncrementLength): Name changes.
+ (match): Name changes. Removed the ONCE opcode.
+ (jsRegExpExecute): Name changes.
+
+ * pcre/pcre_internal.h: Removed quite a few unneeded includes. Rewrote
+ quite a few comments. Removed the macros that add kjs prefixes to the
+ functions with external linkage; instead renamed the functions. Removed
+ the unneeded typedefs pcre_uint16, pcre_uint32, and uschar. Removed the
+ dead and not-all-working code for LINK_SIZE values other than 2, although
+ we aim to keep the abstraction working. Removed the OP_LENGTHS macro.
+ (put2ByteValue): Replaces put2ByteOpcodeValueAtOffset.
+ (get2ByteValue): Replaces get2ByteOpcodeValueAtOffset.
+ (put2ByteValueAndAdvance): Replaces put2ByteOpcodeValueAtOffsetAndAdvance.
+ (putLinkValueAllowZero): Replaces putOpcodeValueAtOffset; doesn't do the
+ addition, since a comma is really no better than a plus sign. Added an
+ assertion to catch out of range values and changed the parameter type to
+ int rather than unsigned.
+ (getLinkValueAllowZero): Replaces getOpcodeValueAtOffset.
+ (putLinkValue): New function that most former callers of the
+ putOpcodeValueAtOffset function can use; asserts the value that is
+ being stored is non-zero and then calls putLinkValueAllowZero.
+ (getLinkValue): Ditto.
+ (putLinkValueAndAdvance): Replaces putOpcodeValueAtOffsetAndAdvance. No
+ caller was using an offset, which makes sense given the advancing behavior.
+ (putLinkValueAllowZeroAndAdvance): Ditto.
+ (isBracketOpcode): Added. For use in an assertion.
+ (advanceToEndOfBracket): Renamed from moveOpcodePtrPastAnyAlternateBranches,
+ and removed comments about how it's not well designed. This function takes
+ a pointer to the beginning of a bracket and advances to the end of the
+ bracket.
+
+ * pcre/pcre_tables.cpp: Updated names.
+ * pcre/pcre_ucp_searchfuncs.cpp:
+ (kjs_pcre_ucp_othercase): Ditto.
+ * pcre/pcre_xclass.cpp:
+ (getUTF8CharAndAdvancePointer): Ditto.
+ (kjs_pcre_xclass): Ditto.
+ * pcre/ucpinternal.h: Ditto.
+
+ * wtf/ASCIICType.h:
+ (WTF::isASCIIAlpha): Added an int overload, like the one we already have for
+ isASCIIDigit.
+ (WTF::isASCIIAlphanumeric): Ditto.
+ (WTF::isASCIIHexDigit): Ditto.
+ (WTF::isASCIILower): Ditto.
+ (WTF::isASCIISpace): Ditto.
+ (WTF::toASCIILower): Ditto.
+ (WTF::toASCIIUpper): Ditto.
+
+2007-12-16 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16459
+ REGRESSION: assertion failure with regexp with \B in a case-ignoring character range
+ <rdar://problem/5646361>
+
+ The problem was that \B was not handled properly in character classes.
+
+ Test: fast/js/regexp-overflow.html
+
+ * pcre/pcre_compile.cpp:
+ (check_escape): Added handling of ESC_b and ESC_B in character classes here.
+ Allows us to get rid of the handling of \b in character classes from all the
+ call sites that handle it separately and to handle \B properly as well.
+ (compileBranch): Remove the ESC_b handling, since it's not needed any more.
+ (calculateCompiledPatternLengthAndFlags): Ditto.
+
+2007-12-16 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=16448
+ Bug 16448: [GTK] Celtic Kane JavaScript performance on Array test is slow relative to Mac
+
+ * kjs/array_instance.cpp:
+ (KJS::compareByStringPairForQSort):
+ (KJS::ArrayInstance::sort): Convert JSValue's to strings once up front and then sort the
+ results. This avoids calling toString twice per comparison, but requires a temporary buffer
+ so we only use this approach in cases where the array being sorted is not too large.
+
+2007-12-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler and Maciej Stachowiak.
+
+ More refactoring to support global variable optimization.
+
+ Changed SymbolTable to use RefPtr<UString::Rep> as its key instead of
+ UString::Rep*. With globals, the symbol table can outlast the
+ declaration node for any given symbol, so the symbol table needs to ref
+ its symbol names.
+
+ In support, specialized HashMaps with RefPtr keys to allow lookup
+ via raw pointer, avoiding refcount churn.
+
+ SunSpider reports a .6% speedup (prolly just noise).
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj: Added new file: wtf/RefPtrHashMap.h
+ * JavaScriptCore.xcodeproj/project.pbxproj: ditto
+
+ * kjs/JSVariableObject.cpp:
+ (KJS::JSVariableObject::getPropertyNames): Symbol table keys are RefPtrs now.
+
+ * kjs/SymbolTable.h: Modified key traits to match RefPtr. Added a
+ static Rep* for null, which helps compute the deletedValue() trait.
+
+ * wtf/HashMap.h: #include the RefPtr specialization so everyone can use it.
+
+ * wtf/RefPtrHashMap.h: Copied from wtf/HashMap.h. Added overloaded versions
+ of find(), contains(), get(), set(), add(), remove(), and take() that take
+ raw pointers as keys.
+
+2007-12-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16162
+ Problems with float parsing on Linux (locale-dependent parsing was used).
+
+ * kjs/dtoa.cpp: Removed USE_LOCALE to reduce future confusion.
+ * kjs/lexer.cpp: (KJS::Lexer::lex): Parse with kjs_strtod, not the system one.
+
+2007-12-14 Alp Toker <alp@atoker.com>
+
+ Reviewed by Mark Rowe.
+
+ Enable the AllInOneFile.cpp optimization for the GTK+ port.
+
+ * JavaScriptCore.pri:
+
+2007-12-14 Mark Rowe <mrowe@apple.com>
+
+ Unreviewed. Remove commented out fprintf's that were for debugging purposes only.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::IncrementalScavenge):
+
+2007-12-14 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Don't use the MADV_DONTNEED code path for now as it has no effect on Mac OS X and is
+ currently untested on other platforms.
+
+ * wtf/TCSystemAlloc.cpp:
+ (TCMalloc_SystemRelease): Return after releasing memory rather than potentially falling
+ through into another mechanism if multiple are supported.
+
+2007-12-14 Alp Toker <alp@atoker.com>
+
+ Build fix for GTK+/Qt and ports that don't use AllInOneFile.cpp.
+
+ Include UnusedParam.h.
+
+ * wtf/TCSystemAlloc.cpp:
+
+2007-12-14 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Stephanie.
+
+ Fix build on windows
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::IncrementalScavenge):
+
+2007-12-14 Dan Bernstein <mitz@apple.com>
+
+ - try again to fix the Windows build
+
+ * wtf/TCSystemAlloc.cpp:
+ (TCMalloc_SystemRelease):
+
+2007-12-14 Dan Bernstein <mitz@apple.com>
+
+ - try to fix the Windows build
+
+ * wtf/TCSystemAlloc.cpp:
+ (TCMalloc_SystemRelease):
+
+2007-12-14 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej and Oliver.
+
+ Add final changes to make TCMalloc release memory to the system.
+ This results in a 0.4% regression against ToT, but this is offset
+ against the gains made by the original TCMalloc r38 merge - in fact
+ we retain around 0.3-0.4% progression overall.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::InitSizeClasses):
+ (WTF::TCMalloc_PageHeap::IncrementalScavenge):
+ * wtf/TCSystemAlloc.cpp:
+ (TCMalloc_SystemRelease):
+
+2007-12-14 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - removed unnecessary includes of "Vector.h"
+
+ * wtf/HashMap.h:
+ (WTF::copyKeysToVector): Make the type of the vector be a template parameter.
+ This allows copying keys into a vector of a base class or one with an inline capacity.
+ (WTF::copyValuesToVector): Ditto.
+ * wtf/HashSet.h:
+ (WTF::copyToVector): Ditto.
+
+2007-12-14 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin and Geoff.
+
+ <rdar://problem/5619295>
+ REGRESSION: 303-304: Embedded YouTube video fails to render- JS errors (16150) (Flash 9)
+
+ Get rid of unnecessary and incorrect security checks for plug-ins accessing JavaScript objects.
+
+ The way this used to work was that each NPObject that wrapped a JSObject would have a root object
+ corresponding to the frame object (used for managing the lifecycle) and an origin root object (used for
+ doing security checks).
+
+ This would prevent a plug-in from accessing a frame's window object if it's security origin was different
+ (some parts of the window, such as the location object, can be accessed from frames with different security
+ origins, and those checks are being done in WebCore).
+
+ Also, if a plug-in were to access a window object of a frame that later went away, it could lead to that
+ Window JSObject being garbage collected and the NPObject pointing to freed memory.
+
+ How this works now is that there is no origin root object anymore, and all NPObject wrappers that are created
+ for a plug-in will have the root object of the containing frame of that plug-in.
+
+ * bindings/NP_jsobject.cpp:
+ (jsDeallocate):
+ Don't free the origin root object.
+
+ (_NPN_CreateScriptObject):
+ Remove the origin root object parameter.
+
+ (_NPN_InvokeDefault):
+ (_NPN_Invoke):
+ (_NPN_Evaluate):
+ (_NPN_GetProperty):
+ (_NPN_SetProperty):
+ (_NPN_RemoveProperty):
+ (_NPN_HasProperty):
+ (_NPN_HasMethod):
+ (_NPN_Enumerate):
+ Get rid of all security checks.
+
+ * bindings/NP_jsobject.h:
+ Remove originRootObject from the JavaScriptObject struct.
+
+ * bindings/c/c_utility.cpp:
+ (KJS::Bindings::convertValueToNPVariant):
+ Always use the root object from the ExecState.
+
+2007-12-13 Steve Falkenburg <sfalken@apple.com>
+
+ Move source file generation into its own vcproj to fix build dependencies.
+
+ Reviewed by Adam.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.sln:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: Added.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj: Added.
+ * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln:
+
+2007-12-13 Alp Toker <alp@atoker.com>
+
+ http://bugs.webkit.org/show_bug.cgi?id=16406
+ [Gtk] JavaScriptCore needs -lpthread
+
+ Build fix for Debian and any other platforms that don't implicitly
+ link to pthread.
+
+ Link to pthread on non-Windows platforms until this dependency is
+ removed from JSC.
+
+2007-12-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Build fix: Note some variables that are used only for ASSERTs.
+
+ * API/testapi.c:
+ (Base_finalize):
+ (globalObject_initialize):
+ (testInitializeFinalize):
+
+2007-12-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed: All JS tests crash on Windows.
+
+ NDEBUG wasn't defined when compiling testkjs in release builds, so the
+ HashTable definition in HashTable.h included an extra data member.
+
+ The solution was to add NDEBUG to the release testkjs configuration on
+ Windows and Mac.
+
+ For giggles, I also added other missing #defines to testkjs on Windows.
+
+ * Configurations/Base.xcconfig:
+ * Configurations/JavaScriptCore.xcconfig:
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/testkjs.cpp:
+ (main):
+
+2007-12-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Removed bogus ASSERT.
+
+ ASSERT should only be used when we know that a code path will not be
+ taken. This code path is taken often during the jsFunFuzz test.
+
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute):
+
+2007-12-11 Darin Adler <darin@apple.com>
+
+ * wtf/unicode/qt4/UnicodeQt4.h: Try to fix Qt build by adding U16_IS_SINGLE.
+
+2007-12-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16379
+ REGRESSION(r28525): Failures in http/tests/xmlhttprequest/response-encoding.html and
+ fast/dom/xmlhttprequest-html-response-encoding.html
+ and <rdar://problem/5640230> REGRESSION (306A4-ToT): Access violation in PCRE function
+ find_firstassertedchar
+
+ Test: fast/js/regexp-find-first-asserted.html
+
+ * pcre/pcre_compile.cpp:
+ (compileBracket): Take out unnecessary initialization of out parameters.
+ (branchFindFirstAssertedCharacter): Added. Broke out the half of the function that handles
+ a branch.
+ (bracketFindFirstAssertedCharacter): Renamed from find_firstassertedchar. Also removed the
+ options parameter -- the caller can handle the options.
+ (jsRegExpCompile): Changed call site to call the appropriate bracket or branch version of
+ the find_firstassertedchar function. Also put the REQ_IGNORE_CASE code here instead of
+ passing in the options.
+
+2007-12-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Split this:
+
+ FunctionBodyNode
+ ^
+ |
+ ProgramNode
+
+ into this:
+
+ ScopeNode
+ ^ ^ ^
+ | | |
+ FunctionBodyNode ProgramNode EvalNode
+
+ in preparation for specializing each class more while optimizing global
+ variable access.
+
+ Also removed some cruft from the FunctionBodyNode interface to simplify
+ things.
+
+ SunSpider says this patch is a .8% speedup, which seems reasonable,
+ since it eliminates a few branches and adds KJS_FAST_CALL in a few
+ places.
+
+ Layout tests and JS tests pass. Also, this baby builds on Windows! (Qt
+ mileage may vary...)
+
+2007-12-10 Geoffrey Garen <ggaren@apple.com>
+
+ RS by Mark Rowe.
+
+ Mac build fix: added some exported symbols, now that Parser::parse is
+ defined in the header.
+
+ * JavaScriptCore.exp:
+
+2007-12-10 Sam Weinig <sam@webkit.org>
+
+ Build fix.
+
+ Template methods need to be in the header.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * kjs/Parser.cpp:
+ * kjs/Parser.h:
+ (KJS::Parser::parse):
+
+2007-12-10 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Merged different implementations of Parser::parse into a single,
+ templatized implementation, in preparation for adding yet another
+ implementation for "eval" code.
+
+ JS and layout tests pass.
+
+2007-12-10 Timothy Hatcher <timothy@apple.com>
+
+ Reviewed by Mark Rowe
+
+ <rdar://problem/5639463> Bundle versions on Tiger should be 4523.x not 523.x
+
+ * Configurations/Version.xcconfig: Some Tiger versions of Xcode don't set MAC_OS_X_VERSION_MAJOR,
+ so assume Tiger and use a 4 for the SYSTEM_VERSION_PREFIX.
+
+2007-12-10 Mark Rowe <mrowe@apple.com>
+
+ Tiger build fix.
+
+ * kjs/grammar.y: Use @1 and @0 in place of @$ where Tiger's bison chokes.
+
+2007-12-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16375
+ REGRESSION: Safari crashes on quit
+
+ Probably a debug-only issue.
+
+ * kjs/Parser.cpp:
+ (KJS::parser): Create the parser and never destroy it by using a pointer instead
+ of a global object.
+
+2007-12-09 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16369
+ REGRESSION (r28525): regular expression tests failing due to bad firstByte optimization
+
+ * pcre/pcre_compile.cpp: Changed some names to use interCaps intead of under_scores.
+ (branchIsAnchored): Broke is_anchored into two separate functions; this one works on a
+ branch and the other on an anchor. The old function would only work on a bracket.
+ Also removed unneeded parameters; the anchored check does not require the bracket
+ map or the options any more because we have a reduced set of features.
+ (bracketIsAnchored): Ditto.
+ (branchNeedsLineStart): Broke canApplyFirstCharOptimization into two functions and gave
+ both a better name. This is the function that was returning the wrong value. The failure
+ was beacuse the old function would only work on a bracket.
+ (bracketNeedsLineStart): Ditto.
+ (jsRegExpCompile): Changed to call the appropriate branch or bracket flavor of the
+ functions based on whether we compiled an outer bracket. Also removed inaccurate comments
+ and unneeded parameters.
+
+ - other small changes
+
+ * pcre/pcre.h: Renumbered error codes, in a logical order. First, normal failure, then
+ the recursion limit, then running out of memory, and finally an unexpected internal error.
+
+ * pcre/pcre_exec.cpp: Fixed indentation.
+ (jsRegExpExecute): Corrected an inaccurate comment.
+
+2007-12-09 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16370
+ REGRESSION (r28540): source URL and line number no longer set for outer function/programs
+
+ Test: fast/js/exception-linenums-in-html-1.html
+ Test: fast/js/exception-linenums-in-html-2.html
+ Test: fast/js/exception-linenums.html
+
+ By the time the ProgramNode was constructed, the source URL was empty.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::parseProgram): Added code to set and clear m_sourceURL, which is now
+ handled here instead of in the lexer; it needs to still be set when we create the
+ program node. Call setLoc to set the first and last line number.
+ (KJS::Parser::parseFunctionBody): Ditto, but for the body.
+ (KJS::Parser::parse): Removed the sourceURL argument.
+
+ * kjs/Parser.h: Added sourceURL(), m_sourceURL, and m_lastLine. Added a lastLine
+ parameter to didFinishParsing, since the bison grammar knows the last line number
+ and we otherwise do not know it. Removed the sourceURL parameter from parse, since
+ that's now handled at a higher level.
+
+ * kjs/grammar.y: Pass the last line number to didFinishParsing.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::setCode): Removed the sourceURL argument and the code to set m_sourceURL.
+ (KJS::Lexer::clear): Ditto.
+ * kjs/lexer.h: More of the same.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::FunctionBodyNode): Get the source URL from the parser rather
+ than from the lexer. Removed unneeded call to setLoc, since the line numbers already
+ both default to -1.
+
+2007-12-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Sam W.
+
+ Split the ENABLE_SVG_EXPERIMENTAL_FEATURES flag into separate flags.
+
+ Fixes <rdar://problem/5620249> Must disable SVG animation
+ <rdar://problem/5612772> Disable SVG filters on Mac to match Windows behavior
+
+ Minor config changes.
+
+ * Configurations/JavaScriptCore.xcconfig:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-12-07 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin.
+
+ - Rename isSafeScript to allowsAccessFrom.
+
+ * bindings/NP_jsobject.cpp:
+ (_isSafeScript):
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::allowsAccessFrom): Reverse caller/argument of allowsAccessFrom to match
+ the new call.
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Refactored variable access optimization: Removed the assumption that
+ the FunctionBodyNode holds the symbol table.
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/nodes.cpp:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/interpreter.cpp:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/grammar.y:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/function_object.cpp:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed crash seen running layout tests.
+
+ Reverted a change I made earlier today. Added a comment to try to
+ discourage myself from making this mistake a third time.
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::mark):
+ * kjs/function.h:
+ (KJS::ActivationImp::ActivationImpData::ActivationImpData):
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Refactored parsing of global code: Removed the assumption that
+ ProgramNode inherits from FunctionBodyNode from the parser.
+
+ * kjs/Parser.cpp:
+ (KJS::Parser::parseProgram):
+ (KJS::Parser::parseFunctionBody):
+ (KJS::Parser::parse):
+ * kjs/Parser.h:
+ (KJS::Parser::didFinishParsing):
+ * kjs/function.cpp:
+ * kjs/grammar.y:
+ * kjs/nodes.h:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added JSVariableObject.cpp to the .pri file.
+
+ * JavaScriptCore.pri:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/function.cpp:
+
+2007-12-07 Steve Falkenburg <sfalken@apple.com>
+
+ Re-named our B&I flag from BUILDBOT to PRODUCTION.
+
+ Reviewed by Sam Weinig.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.make:
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj:
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: removed stray name qualification.
+
+ * kjs/function.h:
+ (KJS::ActivationImp::ActivationImp):
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: moved functions with qualified names outside of class
+ declaration.
+
+ * kjs/JSVariableObject.h:
+ (KJS::JSVariableObject::symbolTableGet):
+ (KJS::JSVariableObject::symbolTablePut):
+
+2007-12-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Next step in refactoring JSGlobalObject: Added JSVariableObject class,
+ and factored symbol-table-related code into it. (JSGlobalObject doesn't
+ use the symbol table code yet, though.)
+
+ Layout and JS tests, and testapi, pass. SunSpider reports no regression.
+
+2007-12-07 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16185
+ jsRegExpCompile should not add implicit non-capturing bracket
+
+ While this does not make SunSpider faster, it will make many regular
+ expressions a bit faster.
+
+ * pcre/pcre_compile.cpp: Moved CompileData struct in here from the
+ header since it's private to this file.
+ (compile_branch): Updated for function name change.
+ (compile_bracket): Renamed from compile_regex, since, for one thing,
+ this does not compile an entire regular expression.
+ (calculateCompiledPatternLengthAndFlags): Removed unused item_count
+ local variable. Renamed CompileData to cd instead of compile_block
+ to be consistent with other functions. Added code to set the
+ needOuterBracket flag if there's at least one "|" at the outer level.
+ (jsRegExpCompile): Renamed CompileData to cd instead of compile_block
+ to be consistent with other functions. Removed unneeded "size" field
+ from the compiled regular expression. If no outer bracket is needed,
+ then use compile_branch to compile the regular expression.
+
+ * pcre/pcre_internal.h: Removed the CompileData struct, which is now
+ private to pcre_compile.cpp. Removed the size member from JSRegExp.
+
+2007-12-06 Kevin Ollivier <kevino@theolliviers.com>
+
+ MSVC7 build fix due to a compiler bug with placement new and/or
+ templates and casting.
+
+ Reviewed by Darin Adler.
+
+ * wtf/Vector.h:
+ (WTF::::append):
+
+2007-12-06 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16321
+ new RegExp("[\u0097]{4,6}", "gmy") crashes in DEBUG builds
+ <rdar://problem/5632992>
+
+ Test: fast/js/regexp-oveflow.html
+
+ * pcre/pcre_compile.cpp:
+ (calculateCompiledPatternLengthAndFlags): In the case where a single character
+ character class is optimized to not use a character class at all, the preflight
+ code was not setting the lastitemlength variable.
+
+2007-12-05 Mark Rowe <mrowe@apple.com>
+
+ Qt Windows build fix. Include the time-related headers in the correct place.
+
+ * kjs/JSGlobalObject.cpp:
+ * kjs/interpreter.cpp:
+
+2007-12-05 Darin Adler <darin@apple.com>
+
+ Not reviewed; just undoing a previous commit.
+
+ - remove earlier incorrect fix for http://bugs.webkit.org/show_bug.cgi?id=16220
+ <rdar://problem/5625221> Crash opening www.news.com (CNet)
+
+ The real bug was the backwards ?: in the compile function, which Geoff just
+ fixed. Rolling out the incorrect earlier fix.
+
+ * pcre/pcre_compile.cpp: (calculateCompiledPatternLengthAndFlags): Take out
+ the unneeded preflight change. The regression test proves this is still working
+ fine, so the bug remains fixed.
+
+2007-12-01 Mark Rowe <mrowe@apple.com>
+
+ Build fix. Include headers before trying to use the things that they declare.
+
+ * kjs/JSImmediate.cpp:
+ * kjs/nodes.cpp:
+ * kjs/object.cpp:
+ * kjs/object_object.cpp:
+ * kjs/regexp_object.cpp:
+ * kjs/string_object.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added some #includes.
+
+ * kjs/JSImmediate.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added some #includes.
+
+ * kjs/JSGlobalObject.cpp:
+ * kjs/JSImmediate.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: Fixed #include spelling.
+
+ * kjs/debugger.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added #include.
+
+ * kjs/debugger.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added a forward declaration.
+
+ * kjs/debugger.h:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added an #include.
+
+ * kjs/error_object.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added an #include.
+
+ * kjs/bool_object.cpp:
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Third step in refactoring JSGlobalObject: Moved data members and
+ functions accessing data members from Interpreter to JSGlobalObject.
+ Changed Interpreter member functions to static functions.
+
+ This resolves a bug in global object bootstrapping, where the global
+ ExecState could be used when uninitialized.
+
+ This is a big change, but it's mostly code motion and renaming.
+
+ Layout and JS tests, and testjsglue and testapi, pass. SunSpider reports
+ a .7% regression, but Shark sees no difference related to this patch,
+ and SunSpider reported a .7% speedup from an earlier step in this
+ refactoring, so I think it's fair to call that a wash.
+
+2007-12-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler. (Or vice versa.)
+
+ Fixed ASSERT during run-javascriptcore-tests. (Darin just added the
+ ASSERT, but the bug wasn't new.)
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch): The ?: operator here was backwards, causing us to
+ execute the loop too many times, adding stray KET opcodes to the
+ compiled regular expression.
+
+2007-12-05 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Geoff.
+
+ - Wait until local variable data is fully constructed before notifying the debugger of entering
+ or leaving a call frame.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::execute):
+
+2007-12-05 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Oliver.
+
+ Build fix for GCC 4.2. Cast via a union to avoid strict-aliasing issues.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::):
+ (WTF::getPageHeap):
+
+2007-12-05 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Darin.
+
+ Fix testkjs in 64-bit.
+
+ When built for 64-bit the TCMalloc spin lock uses pthread mutexes rather than a custom spin lock
+ implemented in assembly. If we fail to initialize the pthread mutex, attempts to lock or unlock
+ it will fail and trigger a call to abort.
+
+ * wtf/FastMalloc.cpp: Initialize the spin lock so that we can later lock and unlock it.
+ * wtf/TCSpinLock.h: Add an Init method to the optimised spin lock.
+
+2007-12-04 Oliver Hunt <oliver@apple.com>
+
+ Fix gtk build.
+
+ * wtf/TCSystemAlloc.cpp:
+
+2007-12-03 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Mark Rowe and Geoff Garen.
+
+ Merge TCMalloc r38
+
+ It also result in a performance progression between 0.5% and
+ 0.9% depending on the test, however most if not all of this
+ gain will be consumed by the overhead involved in the later
+ change to release memory to the system.
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * wtf/FastMalloc.cpp:
+ (WTF::KernelSupportsTLS):
+ (WTF::CheckIfKernelSupportsTLS):
+ (WTF::):
+ (WTF::ClassIndex):
+ (WTF::SLL_Next):
+ (WTF::SLL_SetNext):
+ (WTF::SLL_Push):
+ (WTF::SLL_Pop):
+ (WTF::SLL_PopRange):
+ (WTF::SLL_PushRange):
+ (WTF::SLL_Size):
+ (WTF::SizeClass):
+ (WTF::ByteSizeForClass):
+ (WTF::NumMoveSize):
+ (WTF::InitSizeClasses):
+ (WTF::AllocationSize):
+ (WTF::TCMalloc_PageHeap::GetSizeClassIfCached):
+ (WTF::TCMalloc_PageHeap::CacheSizeClass):
+ (WTF::TCMalloc_PageHeap::init):
+ (WTF::TCMalloc_PageHeap::New):
+ (WTF::TCMalloc_PageHeap::AllocLarge):
+ (WTF::TCMalloc_PageHeap::Carve):
+ (WTF::TCMalloc_PageHeap::Delete):
+ (WTF::TCMalloc_PageHeap::IncrementalScavenge):
+ (WTF::PagesToMB):
+ (WTF::TCMalloc_PageHeap::Dump):
+ (WTF::TCMalloc_PageHeap::GrowHeap):
+ (WTF::TCMalloc_PageHeap::Check):
+ (WTF::ReleaseFreeList):
+ (WTF::TCMalloc_PageHeap::ReleaseFreePages):
+ (WTF::TCMalloc_ThreadCache_FreeList::Push):
+ (WTF::TCMalloc_ThreadCache_FreeList::PushRange):
+ (WTF::TCMalloc_ThreadCache_FreeList::PopRange):
+ (WTF::TCMalloc_ThreadCache_FreeList::Pop):
+ (WTF::TCMalloc_Central_FreeList::length):
+ (WTF::TCMalloc_Central_FreeList::tc_length):
+ (WTF::TCMalloc_Central_FreeList::Init):
+ (WTF::TCMalloc_Central_FreeList::ReleaseListToSpans):
+ (WTF::TCMalloc_Central_FreeList::EvictRandomSizeClass):
+ (WTF::TCMalloc_Central_FreeList::MakeCacheSpace):
+ (WTF::TCMalloc_Central_FreeList::ShrinkCache):
+ (WTF::TCMalloc_Central_FreeList::InsertRange):
+ (WTF::TCMalloc_Central_FreeList::RemoveRange):
+ (WTF::TCMalloc_Central_FreeList::FetchFromSpansSafe):
+ (WTF::TCMalloc_Central_FreeList::Populate):
+ (WTF::TCMalloc_ThreadCache::Init):
+ (WTF::TCMalloc_ThreadCache::Cleanup):
+ (WTF::TCMalloc_ThreadCache::Allocate):
+ (WTF::TCMalloc_ThreadCache::Deallocate):
+ (WTF::TCMalloc_ThreadCache::FetchFromCentralCache):
+ (WTF::TCMalloc_ThreadCache::ReleaseToCentralCache):
+ (WTF::TCMalloc_ThreadCache::Scavenge):
+ (WTF::TCMalloc_ThreadCache::PickNextSample):
+ (WTF::TCMalloc_ThreadCache::NewHeap):
+ (WTF::TCMalloc_ThreadCache::GetThreadHeap):
+ (WTF::TCMalloc_ThreadCache::GetCache):
+ (WTF::TCMalloc_ThreadCache::GetCacheIfPresent):
+ (WTF::TCMalloc_ThreadCache::InitTSD):
+ (WTF::TCMalloc_ThreadCache::CreateCacheIfNecessary):
+ (WTF::TCMallocStats::ExtractStats):
+ (WTF::TCMallocStats::DumpStats):
+ (WTF::TCMallocStats::DumpStackTraces):
+ (WTF::TCMallocStats::TCMallocImplementation::MarkThreadIdle):
+ (WTF::TCMallocStats::TCMallocImplementation::ReleaseFreeMemory):
+ (WTF::TCMallocStats::TCMallocGuard::TCMallocGuard):
+ (WTF::TCMallocStats::TCMallocGuard::~TCMallocGuard):
+ (WTF::TCMallocStats::DoSampledAllocation):
+ (WTF::TCMallocStats::CheckCachedSizeClass):
+ (WTF::TCMallocStats::CheckedMallocResult):
+ (WTF::TCMallocStats::SpanToMallocResult):
+ (WTF::TCMallocStats::do_malloc):
+ (WTF::TCMallocStats::do_free):
+ (WTF::TCMallocStats::do_memalign):
+ (WTF::TCMallocStats::do_malloc_stats):
+ (WTF::TCMallocStats::do_mallopt):
+ (WTF::TCMallocStats::do_mallinfo):
+ (WTF::TCMallocStats::realloc):
+ (WTF::TCMallocStats::cpp_alloc):
+ (WTF::TCMallocStats::operator new):
+ (WTF::TCMallocStats::):
+ (WTF::TCMallocStats::operator new[]):
+ (WTF::TCMallocStats::malloc_stats):
+ (WTF::TCMallocStats::mallopt):
+ (WTF::TCMallocStats::mallinfo):
+ * wtf/TCPackedCache.h: Added.
+ (PackedCache::PackedCache):
+ (PackedCache::Put):
+ (PackedCache::Has):
+ (PackedCache::GetOrDefault):
+ (PackedCache::Clear):
+ (PackedCache::EntryToValue):
+ (PackedCache::EntryToUpper):
+ (PackedCache::KeyToUpper):
+ (PackedCache::UpperToPartialKey):
+ (PackedCache::Hash):
+ (PackedCache::KeyMatch):
+ * wtf/TCPageMap.h:
+ (TCMalloc_PageMap2::PreallocateMoreMemory):
+ * wtf/TCSystemAlloc.cpp:
+ (TCMalloc_SystemRelease):
+ * wtf/TCSystemAlloc.h:
+
+2007-12-04 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam.
+
+ Make isSafeScript const.
+
+ * kjs/JSGlobalObject.h:
+ (KJS::JSGlobalObject::isSafeScript):
+
+2007-12-04 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix first part of http://bugs.webkit.org/show_bug.cgi?id=16220
+ <rdar://problem/5625221> Crash opening www.news.com (CNet)
+
+ Test: fast/js/regexp-overflow.html
+
+ * pcre/pcre_compile.cpp:
+ (calculateCompiledPatternLengthAndFlags): Add room for the additional BRA/KET that
+ was generated in the compile code but not taken into account here.
+
+2007-12-03 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15618
+ <rdar://problem/5619353> REGRESSION: Stack overflow/crash in KJS::equal (15618)
+
+ Test: fast/js/recursion-limit-equal.html
+
+ * kjs/operations.cpp: (KJS::equal): Check the exception from toPrimitive.
+
+2007-12-03 Dan Bernstein <mitz@apple.com>
+
+ - fix a copy-and-paste-o
+
+ * bindings/npruntime.cpp:
+ (_NPN_GetIntIdentifier):
+
+2007-12-03 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ - fix an ASSERT when getIntIdentifier is called with 0 or -1
+
+ * bindings/npruntime.cpp:
+ (_NPN_GetIntIdentifier): We cannot use the hashmap for 0 and -1 since
+ they are the empty value and the deleted value. Instead, keep the
+ identifiers for those two integers in a static array.
+
+2007-12-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Mitz.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15848
+ <rdar://problem/5619330> REGRESSION: Assertion failure viewing comments page on digg.com
+
+ Test: fast/js/sparse-array.html
+
+ * kjs/array_instance.cpp:
+ (KJS::ArrayInstance::inlineGetOwnPropertySlot): Check sparse array cutoff before looking
+ in hash map. Can't avoid the branch because we can't look for 0 in the hash.
+ (KJS::ArrayInstance::deleteProperty): Ditto.
+
+2007-12-02 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: added an #include.
+
+ * kjs/collector.cpp:
+
+2007-12-02 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Second step in refactoring JSGlobalObject: moved virtual functions from
+ Interpreter to JSGlobalObject.
+
+ Layout and JS tests pass. SunSpider reports a .7% speedup -- don't
+ believe his lies.
+
+2007-12-01 Alp Toker <alp@atoker.com>
+
+ Reviewed by Adam Roben.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16228
+ kJSClassDefinitionEmpty is not exported with JS_EXPORT
+
+ Add JS_EXPORT to kJSClassDefinitionEmpty.
+
+ Make the gcc compiler check take precedence over the WIN32||_WIN32
+ check to ensure that symbols are exported on Windows when using gcc.
+
+ Add a TODO referencing the bug about JS_EXPORT in the Win build
+ (http://bugs.webkit.org/show_bug.cgi?id=16227)
+
+ Don't define JS_EXPORT as 'extern' when the compiler is unknown since
+ it would result in the incorrect expansion:
+
+ extern extern const JSClassDefinition kJSClassDefinitionEmpty;
+
+ (This was something we inherited from CFBase.h that doesn't make sense
+ for JSBase.h)
+
+ * API/JSBase.h:
+ * API/JSObjectRef.h:
+
+2007-11-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Reversed the ownership relationship between Interpreter and JSGlobalObject.
+ Now, the JSGlobalObject owns the Interpreter, and top-level objects
+ that need the two to persist just protect the JSGlobalObject from GC.
+
+ Global object bootstrapping looks a little odd right now, but it will
+ make much more sense soon, after further rounds of refactoring.
+
+ * bindings/runtime_root.h: Made this class inherit from RefCounted,
+ to avoid code duplication.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect): No need to give special GC treatment to
+ Interpreters, since we mark their global objects, which mark them.
+
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::mark): No need to mark our global object, since it
+ marks us.
+ * kjs/interpreter.h: Don't inherit from RefCounted -- JSGlobalObject
+ owns us directly.
+
+ * kjs/testkjs.cpp: Modified to follow the new rules.
+ (createGlobalObject):
+ (runWithScripts):
+
+2007-11-30 Brent Fulgham <bfulgham@gmail.com>
+
+ Reviewed by Eric.
+
+ * ChangeLog:
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+
+2007-11-30 Eric Seidel <eric@webkit.org>
+
+ No review, build fix only.
+
+ Fix uninitialized var warnings in release build.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * pcre/pcre_compile.cpp:
+ (compile_regex):
+
+2007-11-30 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam Roben.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16207
+ JavaScript regular expressions should match UTF-16 code units rather than characters
+
+ SunSpider says this is 5.5% faster on the regexp test, 0.4% faste overall.
+
+ Test: fast/js/regexp-non-bmp.html
+
+ Renamed ANY_CHAR to NOT_NEWLINE to more-accurately reflect its meaning.
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch): Removed calls to the UTF-16 character accessor functions, replacing
+ them with simple pointer dereferences in some cases, and no code at all in others.
+ (calculateCompiledPatternLengthAndFlags): Ditto.
+
+ * pcre/pcre_exec.cpp:
+ (match): Fixed indentation of some case labels (including all the BEGIN_OPCODE).
+ Removed calls to the UTF-16 character accessor functions, replacing them with simple
+ pointer dereferences in some cases, and no code at all in others. Also removed some
+ explicit UTF-16 support code in a few cases. Removed the unneeded "UTF-8" code path
+ in the ANY_CHAR repeat code, and in another case, eliminated the code to check against
+ end_subject in because it is already done outside the loop.
+ (jsRegExpExecute):
+
+ * pcre/pcre_internal.h: Removed all the UTF-16 helper functions.
+
+2007-11-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ PCRE crashes under GuardMalloc
+ http://bugs.webkit.org/show_bug.cgi?id=16127
+ check against patternEnd to make sure we don't walk off the end of the string
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (calculateCompiledPatternLengthAndFlags):
+
+2007-11-30 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Fix layout test regressions caused by r28186
+ http://bugs.webkit.org/show_bug.cgi?id=16195
+ change first_byte and req_byte back to shorts instead of chars
+ (I think PCRE stuffs information in the high bits)
+
+ * pcre/pcre_internal.h:
+
+2007-11-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej and Darin.
+
+ Make the JS collector work with multiple threads
+
+ Under heavy contention it was possible the GC to suspend other
+ threads inside the pthread spinlock, which could lead to the GC
+ thread blocking on the pthread spinlock itself.
+
+ We now determine and store each thread's stack base when it is
+ registered, thus removing the need for any calls to pthread_get_stackaddr_np
+ that needed the pthread spinlock.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::Thread::Thread):
+ (KJS::Collector::registerThread):
+ (KJS::Collector::markOtherThreadConservatively):
+
+2007-11-29 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ Removed some unreachable code (ironically, the code was some
+ ASSERT_NOT_REACHED()s).
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ * pcre/pcre_exec.cpp:
+ (match):
+
+2007-11-29 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Fix for --guard crash of fast/js/regexp-charclass-crash introduced by r28151.
+
+ * pcre/pcre_compile.cpp:
+ (is_anchored):
+
+2007-11-28 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix. Rubber-stamped by Eric.
+
+ * pcre/pcre_exec.cpp:
+ (match): Add braces around the body of the case statement to prevent
+ wanings about jumps across the initialization of a variable.
+
+2007-11-29 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Mark Rowe.
+
+ Attempt to fix non-mac builds after PCRE cleanup.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCoreSources.bkl:
+ * pcre/pcre.pri:
+
+2007-11-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Centralize code for subjectPtr adjustments using inlines, only ever check for a single
+ trailing surrogate (as UTF16 only allows one), possibly fix PCRE bugs involving char
+ classes and garbled UTF16 strings.
+
+ * pcre/pcre_exec.cpp:
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+ (getPreviousChar):
+ (movePtrToPreviousChar):
+ (movePtrToNextChar):
+ (movePtrToStartOfCurrentChar):
+
+2007-11-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ change getChar* functions to return result and push 'c' into local scopes for clarity
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (calculateCompiledPatternLengthAndFlags):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+ (getChar):
+ (getCharAndAdvance):
+ (getCharAndLength):
+ (getCharAndAdvanceIfSurrogate):
+
+2007-11-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Comment cleanup
+
+ * pcre/pcre_exec.cpp:
+ (match):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Further cleanups to calculateCompiledPatternLengthAndFlags
+
+ * pcre/pcre_compile.cpp:
+ (calculateCompiledPatternLengthAndFlags):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Give consistent naming to the RegExp options/compile flags
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (is_anchored):
+ (find_firstassertedchar):
+ (printCompiledRegExp):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Pull first_byte and req_byte optimizations out into separate static funtions, SunSpider reported this as a win.
+
+ * pcre/pcre_exec.cpp:
+ (tryFirstByteOptimization):
+ (tryRequiredByteOptimization):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ give PCRE_MULTILINE a better name: OptionMatchAcrossMultipleLines
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (is_anchored):
+ (printCompiledRegExp):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ Deprecate jsRegExpExecute's offset-vector fallback code
+
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Make cur_is_word and prev_is_word locals, and change OP_ANY to OP_ANY_CHAR for clarity
+
+ * pcre/pcre_compile.cpp:
+ (find_fixedlength):
+ (compile_branch):
+ (canApplyFirstCharOptimization):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Mitz & Maciej.
+
+ Change _NC operators to use _IGNORING_CASE for clarity
+
+ * pcre/pcre_compile.cpp:
+ (find_fixedlength):
+ (compile_branch):
+ (find_firstassertedchar):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Mitz.
+
+ Remove branch from return
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ * pcre/pcre_exec.cpp:
+ (match):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Add repeatInformationFromInstructionOffset inline
+
+ * pcre/pcre_exec.cpp:
+ (repeatInformationFromInstructionOffset):
+ (match):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Remove no longer used error code JSRegExpErrorMatchLimit
+
+ * kjs/regexp.cpp:
+ (KJS::RegExp::match):
+ * pcre/pcre.h:
+ * pcre/pcre_internal.h:
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Make i locally scoped for better code clarity
+
+ * pcre/pcre_exec.cpp:
+ (match):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Give subjectPtr and instructionPtr sane names, reduce size of MatchFrame for a 0.2% speedup.
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (calculateCompiledPatternLengthAndFlags):
+ * pcre/pcre_exec.cpp:
+ (match_ref):
+ (MatchStack::pushNewFrame):
+ (getUTF8CharAndIncrementLength):
+ (match):
+ * pcre/pcre_internal.h:
+ (getChar):
+ (getCharAndAdvance):
+ (getCharAndLength):
+ (getCharAndAdvanceIfSurrogate):
+ * pcre/pcre_xclass.cpp:
+ (getUTF8CharAndAdvancePointer):
+
+2007-11-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Small speedup (0.7%) by simplifying canUseStackBufferForNextFrame() check
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::MatchStack):
+ (MatchStack::popCurrentFrame):
+
+2007-11-25 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Lower MATCH_LIMIT_RECURSION to more sane levels to prevent hangs on run-javascriptcore-tests
+
+ * pcre/pcre_internal.h:
+
+2007-11-25 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Remove match_is_group variable for another 5% speedup
+
+ * pcre/pcre_compile.cpp:
+ * pcre/pcre_exec.cpp:
+ (startNewGroup):
+ (match):
+
+2007-11-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Abstract frame variables into locals and args
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+
+2007-11-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Section off MatchData arguments into args struct
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::pushNewFrame):
+ (match):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Remove redundant eptrblock struct
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::pushNewFrame):
+ (match):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Remove redundant match_call_count and move recursion check out of super-hot code path
+ SunSpider says this is at least an 8% speedup for regexp.
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::MatchStack):
+ (MatchStack::pushNewFrame):
+ (MatchStack::popCurrentFrame):
+ (MatchStack::popAllFrames):
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Get rid of GETCHAR* macros, replacing them with better named inlines
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (calculateCompiledPatternLengthAndFlags):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+ (getCharAndAdvance):
+ (getCharAndLength):
+ (getCharAndAdvanceIfSurrogate):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Further cleanup GET/PUT inlines
+
+ * pcre/pcre_internal.h:
+ (putOpcodeValueAtOffset):
+ (getOpcodeValueAtOffset):
+ (putOpcodeValueAtOffsetAndAdvance):
+ (put2ByteOpcodeValueAtOffset):
+ (get2ByteOpcodeValueAtOffset):
+ (put2ByteOpcodeValueAtOffsetAndAdvance):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Give GET, PUT better names, and add (poor) moveOpcodePtrPastAnyAlternateBranches
+
+ * pcre/pcre_compile.cpp:
+ (firstSignificantOpCodeSkippingAssertions):
+ (find_fixedlength):
+ (complete_callout):
+ (compile_branch):
+ (compile_regex):
+ (is_anchored):
+ (canApplyFirstCharOptimization):
+ (find_firstassertedchar):
+ * pcre/pcre_exec.cpp:
+ (match):
+ * pcre/pcre_internal.h:
+ (putOpcodeValueAtOffset):
+ (getOpcodeValueAtOffset):
+ (putOpcodeValueAtOffsetAndAdvance):
+ (put2ByteOpcodeValueAtOffset):
+ (get2ByteOpcodeValueAtOffset):
+ (moveOpcodePtrPastAnyAlternateBranches):
+ * pcre/pcre_ucp_searchfuncs.cpp:
+ (_pcre_ucp_othercase):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Add inlines for toLowerCase, isWordChar, isSpaceChar for further regexp speedup
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+ (toLowerCase):
+ (flipCase):
+ (classBitmapForChar):
+ (charTypeForChar):
+ (isWordChar):
+ (isSpaceChar):
+ (CompileData::CompileData):
+ * pcre/pcre_xclass.cpp:
+ (_pcre_xclass):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ cleanup _pcre_ucp_othercase
+
+ * pcre/pcre_ucp_searchfuncs.cpp:
+ (_pcre_ucp_othercase):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Use better variable names for case ignoring options
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (find_firstassertedchar):
+ (printCompiledRegExp):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (match_ref):
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ split first_significant_code into two simpler functions
+
+ * pcre/pcre_compile.cpp:
+ (firstSignificantOpCode):
+ (firstSignificantOpCodeSkippingAssertions):
+ (is_anchored):
+ (canApplyFirstCharOptimization):
+ (find_firstassertedchar):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ clean up is_counted_repeat
+
+ * pcre/pcre_compile.cpp:
+ (is_counted_repeat):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ clean up check_escape
+
+ * pcre/pcre_compile.cpp:
+ (check_escape):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Reformat find_fixedlength
+
+ * pcre/pcre_compile.cpp:
+ (find_fixedlength):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ reformat is_anchored
+
+ * pcre/pcre_compile.cpp:
+ (is_anchored):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Remove unused function could_be_empty_branch
+
+ * pcre/pcre_compile.cpp:
+ (first_significant_code):
+ (find_fixedlength):
+ (compile_branch):
+ (canApplyFirstCharOptimization):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Pass around MatchData objects by reference
+
+ * pcre/pcre_exec.cpp:
+ (pchars):
+ (match_ref):
+ (match):
+ (jsRegExpExecute):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ give PCRE_STARTLINE a better name and rename match_data to MatchData
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (canApplyFirstCharOptimization):
+ (find_firstassertedchar):
+ (printCompiledRegExp):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (pchars):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Clean up find_firstassertedchar
+
+ * pcre/pcre_compile.cpp:
+ (get_othercase_range):
+ (find_firstassertedchar):
+ (calculateCompiledPatternLengthAndFlags):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Tim Hatcher.
+
+ Pass around CompileData& instead of CompileData*
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+ (jsRegExpCompile):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Clean up compile_branch, move _pcre_ord2utf8, and rename CompileData
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * pcre/pcre_compile.cpp:
+ (_pcre_ord2utf8):
+ (calculateCompiledPatternLengthAndFlags):
+ (jsRegExpCompile):
+ * pcre/pcre_internal.h:
+ * pcre/pcre_ord2utf8.cpp: Removed.
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ removing more macros
+
+ * pcre/pcre_compile.cpp:
+ (could_be_empty_branch):
+ (compile_branch):
+ (calculateCompiledPatternLengthAndFlags):
+ * pcre/pcre_exec.cpp:
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+ * pcre/pcre_xclass.cpp:
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ clean up formating in compile_branch
+
+ * pcre/pcre_compile.cpp:
+ (compile_branch):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Fix spacing for read_repeat_counts
+
+ * pcre/pcre_compile.cpp:
+ (read_repeat_counts):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Get rid of PCRE custom char types
+
+ * pcre/pcre_compile.cpp:
+ (check_escape):
+ (complete_callout):
+ (compile_branch):
+ (compile_regex):
+ (calculateCompiledPatternLengthAndFlags):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (match_ref):
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ reformat get_othercase_range
+
+ * pcre/pcre_compile.cpp:
+ (get_othercase_range):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Remove register keyword and more cleanup
+
+ * pcre/pcre_compile.cpp:
+ (find_fixedlength):
+ (compile_branch):
+ (is_anchored):
+ (is_startline):
+ (find_firstassertedchar):
+ (calculateCompiledPatternLengthAndFlags):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (MatchStack::canUseStackBufferForNextFrame):
+ (MatchStack::allocateNextFrame):
+ (MatchStack::pushNewFrame):
+ (MatchStack::frameIsStackAllocated):
+ (MatchStack::popCurrentFrame):
+ (MatchStack::unrollAnyHeapAllocatedFrames):
+ (getUTF8CharAndIncrementLength):
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+ (PUT2INC):
+ (isLeadingSurrogate):
+ (isTrailingSurrogate):
+ (decodeSurrogatePair):
+ (getChar):
+ * pcre/pcre_ord2utf8.cpp:
+ (_pcre_ord2utf8):
+ * pcre/pcre_xclass.cpp:
+ (getUTF8CharAndAdvancePointer):
+ (_pcre_xclass):
+
+2007-11-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Clean up jsRegExpExecute
+
+ * pcre/pcre_compile.cpp:
+ (returnError):
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+
+2007-11-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoff.
+
+ Merging updated system alloc and spinlock code from r38 of TCMalloc.
+
+ This is needed as a precursor to the merge of TCMalloc proper.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::GrowHeap):
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::TCMalloc_SpinLock):
+ (TCMalloc_SpinLock::):
+ (TCMalloc_SpinLock::Lock):
+ (TCMalloc_SpinLock::Unlock):
+ (TCMalloc_SpinLock::IsHeld):
+ * wtf/TCSystemAlloc.cpp:
+ (TrySbrk):
+ (TryMmap):
+ (TryVirtualAlloc):
+ (TryDevMem):
+ (TCMalloc_SystemAlloc):
+ * wtf/TCSystemAlloc.h:
+
+2007-11-28 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Geoff
+
+ Add copyKeysToVector utility, mirroring copyValuesToVector
+ Also change the copyValuesToVector implementation to be a little more attractive
+
+ * wtf/HashMap.h:
+ (WTF::copyKeysToVector):
+ (WTF::copyValuesToVector):
+
+2007-11-27 Alp Toker <alp@atoker.com>
+
+ Reviewed by Mark Rowe.
+
+ Add a list of public JavaScriptCore headers for installation.
+
+ This follows the convention used for the Qt and GTK+ header lists.
+
+ * headers.pri: Added.
+
+2007-11-27 Alp Toker <alp@atoker.com>
+
+ Prospective MSVC build fix.
+
+ Roll back dllexport/dllimport support for now.
+
+ * API/JSBase.h:
+
+2007-11-27 Alp Toker <alp@atoker.com>
+
+ Reviewed by Maciej.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15569
+ [gtk] GTK JavaScriptCore needs to export symbols for JSC API and WTF
+
+ Introduce JS_EXPORT to mark symbols to be exported as public API.
+
+ Export all public symbols in the JavaScriptCore C API.
+
+ This matches conventions for exporting symbols set by the CF and CG
+ frameworks.
+
+ * API/JSBase.h:
+ * API/JSContextRef.h:
+ * API/JSObjectRef.h:
+ * API/JSStringRef.h:
+ * API/JSStringRefBSTR.h:
+ * API/JSStringRefCF.h:
+ * API/JSValueRef.h:
+
+2007-11-27 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Adam.
+
+ Make PropertyNameArray and ScopeChain COMEnumVariant friendly.
+
+ * kjs/PropertyNameArray.cpp:
+ (KJS::PropertyNameArray::swap):
+ Implement PropertyNameArray::swap.
+
+ * kjs/PropertyNameArray.h:
+ Add ValueType typedef. Replace PropertyNameArrayIterator with
+ PropertyNameArray::const_iterator.
+
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::execute):
+ * kjs/scope_chain.cpp:
+ (KJS::ScopeChain::print):
+ Update for changes to PropertyNameArray.
+
+ * kjs/scope_chain.h:
+ Add const_iterator and ValueType typedef.
+
+2007-11-27 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin.
+
+ Add a ValueType typedef.
+
+ * wtf/Vector.h:
+
+2007-11-26 Darin Adler <darin@apple.com>
+
+ Reviewed by Mitz.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=16096
+ REGRESSION (r26653-r26699): Plaxo.com addressbook does not load in webkit nightlies
+
+ Test: fast/js/regexp-overflow.html
+
+ * pcre/pcre_compile.cpp: (calculateCompiledPatternLengthAndFlags):
+ Removed a stray "ptr++" that I added by accident when merging the
+ changes between PCRE 6.4 and 6.5.
+
+2007-11-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Kevin McCullough.
+
+ Fixed <rdar://problem/5597937> REGRESSION (r27126): Drosera does not
+ show variables (can't enumerate ActivationImp properties)
+
+ Implemented a custom ActivationImp::getPropertyNames, since
+ ActivationImp now uses a custom property storage mechanism for local
+ variables.
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getPropertyNames):
+ * kjs/function.h:
+
+2007-11-26 Alp Toker <alp@atoker.com>
+
+ GTK+/Qt/Wx build fix for breakage introduced in r28039.
+
+ * ForwardingHeaders/JavaScriptCore/JSRetainPtr.h: Added.
+
+2007-11-24 Laszlo Gombos <laszlo.gombos@gmail.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fix minor compiler warning (GCC 4.1.3)
+
+ * pcre/pcre_internal.h:
+ * pcre/pcre_ucp_searchfuncs.cpp:
+ (_pcre_ucp_othercase):
+
+2007-11-25 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Dan Bernstein.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=16129
+ Bug 16129: REGRESSION (r27761-r27811): malloc error while visiting http://mysit.es (crashes release build)
+
+ * pcre/pcre_compile.cpp: Change errorcode to be passed by reference so that any error code is propagated
+ to our caller like they expect.
+
+2007-11-23 Kevin Ollivier <kevino@theolliviers.com>
+
+ MSVC7 build fix. (rand_s doesn't exist there)
+
+ Reviewed by Adam Roben.
+
+ * kjs/config.h:
+ * wtf/MathExtras.h:
+
+2007-11-23 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix. Move WX_PYTHON logic into project build settings,
+ add WebKitLibraries dirs on Win, and explicitly include JSCore
+ headers in testkjs rather than getting them from a template.
+ (Include dir order of JSCore/WTF and ICU headers is important due
+ to wtf/unicode/utf8.h.)
+
+ * jscore.bkl:
+
+2007-11-23 Simon Hausmann <hausmann@webkit.org>
+
+ Reviewed by George Staikos <staikos@kde.org>.
+
+ Fix make (dist)clean on Windows.
+
+ OBJECTS_DIR_WTR does not exist anymore, use GENERATED_SOURCES_DIR.
+
+
+ * JavaScriptCore.pri:
+ * pcre/pcre.pri:
+
+2007-11-22 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by George.
+
+ Make the directory of where to put the generated sources configurable through the GENERATED_SOURCE_DIR variable
+
+ * JavaScriptCore.pri:
+ * pcre/pcre.pri:
+
+2007-11-22 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by George.
+
+ Centralize the setup for all the extra compilers in a addExtraCompiler function.
+
+ This allows adding a "generated_files" target that builds all generated files using "make generated_files".
+ For the build inside Qt we do not generate actual rules for the extra compilers but instead
+ do the variable substitution of compiler.output manually and add the generated sources to SOURCES.
+
+ * JavaScriptCore.pri:
+ * pcre/pcre.pri:
+
+2007-11-20 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Tim Hatcher.
+
+ <rdar://problem/5602936> Need to resolve new GCC 4.2 warnings
+
+ Fix all warnings emitted by GCC 4.2 when building JavaScriptCore. This allows builds with
+ -Werror to succeed. At present they will crash when executed due to code that is not safe
+ under strict aliasing (<rdar://problem/5536806>).
+
+ * Configurations/Base.xcconfig: Remove the -Wno-long-double flag.
+ * kjs/date_object.cpp:
+ (KJS::formatTime): Test whether the stack-allocated string is empty rather than at a non-null address.
+ * kjs/dtoa.cpp:
+ (Bigint::): Tweak formatting to silence warnings.
+ * pcre/pcre_exec.cpp:
+ (match): Tweak formatting to silence warnings
+ * wtf/Assertions.cpp: Add printf format attribute to functions that warrant it.
+ * wtf/Assertions.h: Ditto.
+
+2007-11-19 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx port build fix (wx headers include ctype functions).
+
+ * kjs/config.h:
+
+2007-11-19 Kevin Ollivier <kevino@theolliviers.com>
+
+ Remove outdated and unused Windows port files.
+
+ Reviewed by Adam Roben.
+
+ * Makefile.vc: Removed.
+ * README-Win32.txt: Removed.
+
+2007-11-18 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ * tests/mozilla/jsDriver.pl: exit non-0 when user aborts test run
+
+2007-11-17 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fix: <rdar://problem/5607032> REGRESSION: testapi exits with assertion failure in debug build
+ <rdar://problem/5440659> JSGlobalContextCreate throws away globalObjectClass's prototype
+ http://bugs.webkit.org/show_bug.cgi?id=16033
+
+ Split Interpreter's initialization into two distinct steps: the creation of the global prototypes
+ and constructors, and storing them on the global object. This allows JSClassRef's passed to
+ JSGlobalContextCreate to be instantiated with the correct prototype.
+
+ * API/JSCallbackObject.cpp: Assert at compile-time that the custom global object will fit in a collector cell.
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h:
+ (KJS::::JSCallbackObject):
+ (KJS::::init):
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreate): Construct and set the interpreter's global object separately. When globalObjectClass
+ is passed we need to set the interpreter's global object before doing the JSCallbackObject's initialization to
+ prevent any JSObjectInitializeCallback's being invoked before a global object is set.
+ * API/testapi.c:
+ (globalObject_initialize): Test the object passed in is correct and that it has the expected global properties.
+ (globalObject_get):
+ (globalObject_set):
+ (main):
+ * API/testapi.js: Test that any static properties exposed by the global object's custom class are found.
+ * JavaScriptCore.exp:
+ * bindings/testbindings.cpp:
+ (main): Update for changes in Interpreter method signatures.
+ * bindings/testbindings.mm:
+ (main): Ditto.
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ (KJS::ExecState::mark):
+ (KJS::ExecState::setGlobalObject):
+ * kjs/ExecState.h: Rename scope to m_scopeChain.
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::Interpreter):
+ (KJS::Interpreter::init):
+ (KJS::Interpreter::globalObject):
+ (KJS::Interpreter::setGlobalObject):
+ (KJS::Interpreter::resetGlobalObjectProperties):
+ (KJS::Interpreter::createObjectsForGlobalObjectProperties):
+ (KJS::Interpreter::setGlobalObjectProperties): Switch to using putDirect to ensure that the global object's put method
+ cannot interfere with setting of the global properties. This prevents a user-written JSClassRef from attempting to
+ call back into JavaScript from the initialization of the global object's members.
+ * kjs/interpreter.h:
+ * kjs/testkjs.cpp:
+ (setupInterpreter): Update for changes in Interpreter method signatures.
+
+2007-11-17 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Prevent testapi from reporting false leaks. Clear out local variables pointing at
+ JSObjectRefs to allow their values to be collected.
+
+ * API/testapi.c:
+ (main):
+
+2007-11-17 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Prevent testapi from crashing if testapi.js can not be found by nil-checking the result of createStringWithContentsOfFile.
+
+ * API/testapi.c:
+ (main):
+
+2007-11-17 Alp Toker <alp@atoker.com>
+
+ Reviewed by Eric.
+
+ http://bugs.webkit.org/show_bug.cgi?id=16032
+ JS minidom is not portable
+
+ Use a plain UTF-8 string instead of a CFString.
+
+ Print to stdout, not stderr like CFShow() would have done, since that
+ behaviour seems unintentional.
+
+ * API/minidom.c:
+ (main):
+
+2007-11-17 Steve Falkenburg <sfalken@apple.com>
+
+ Windows build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-11-16 Mark Rowe <mrowe@apple.com>
+
+ Windows build fix.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::record8):
+
+2007-11-16 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Eric.
+
+ Replace strings, identifier, buffer8 and buffer16 members of Lexer with vectors.
+ SunSpider claims this is a 0.7% speedup.
+
+ * kjs/lexer.cpp:
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::lex):
+ (KJS::Lexer::record8):
+ (KJS::Lexer::record16):
+ (KJS::Lexer::scanRegExp):
+ (KJS::Lexer::clear):
+ (KJS::Lexer::makeIdentifier):
+ (KJS::Lexer::makeUString):
+ * kjs/lexer.h:
+ * kjs/ustring.cpp:
+ (KJS::UString::UString): Add a convenience constructor that takes a const Vector<UChar>&.
+ * kjs/ustring.h:
+
+2007-11-16 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj: Add a new include path
+ and ignore the int -> bool conversion warning.
+
+2007-11-16 Alexey Proskuryakov <ap@webkit.org>
+
+ Fix Windows debug build.
+ Rubber-stamped by Eric
+
+ * pcre/pcre_exec.cpp: (match): Removed ASSERT_NOT_REACHED assertions that were making MSVC
+ complain about unreachable code.
+
+2007-11-15 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/Parser.cpp:
+
+2007-11-15 Mark Rowe <mrowe@apple.com>
+
+ Mac build and header search path sanity fix.
+
+ Reviewed by Sam Weinig and Tim Hatcher.
+
+ Move base setting for HEADER_SEARCH_PATHS into Base.xcconfig, and extend
+ it in JavaScriptCore.xcconfig. This removes the need to override it on a
+ per-target basis inside the .xcodeproj file.
+
+ * Configurations/Base.xcconfig:
+ * Configurations/JavaScriptCore.xcconfig:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-11-15 Mark Rowe <mrowe@apple.com>
+
+ Qt build fix.
+
+ * kjs/Parser.h:
+
+2007-11-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Another round of grammar / parsing cleanup.
+
+ 1. Created distinct parser calls for parsing function bodies vs
+ programs. This will help later with optimizing global variable access.
+
+ 2. Turned Parser into a singleton. Cleaned up Lexer's singleton
+ interface.
+
+ 3. Modified Lexer to free a little more memory when done lexing. (Added
+ FIXMEs for similar issues that I didn't fix.)
+
+ 4. Changed Lexer::makeIdentifier and Lexer::makeUString to start
+ respecting the arguments passed to them. (No behavior change, but this
+ problem could have caused serious problems for an unsuspecting user of
+ these functions.)
+
+ 5. Removed KJS_DEBUG_MEM because it was bit-rotted.
+
+ 6. Removed Parser::prettyPrint because the same work was simpler to do
+ at the call site.
+
+ 7. Some renames:
+
+ "Parser::accept" => "Parser::didFinishParsing"
+ "Parser::sid" => "Parser::m_sourceID"
+ "Lexer::doneParsing" => "Lexer::clear"
+ "sid" => "sourceId"
+ "lineno" => "lineNo"
+
+ * JavaScriptCore.exp:
+ * kjs/Parser.cpp:
+ (KJS::Parser::Parser):
+ (KJS::Parser::parseProgram):
+ (KJS::Parser::parseFunctionBody):
+ (KJS::Parser::parse):
+ (KJS::Parser::didFinishParsing):
+ (KJS::parser):
+ * kjs/Parser.h:
+ (KJS::Parser::sourceId):
+ * kjs/function.cpp:
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/function_object.cpp:
+ (FunctionObjectImp::construct):
+ * kjs/grammar.y:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::checkSyntax):
+ (KJS::Interpreter::evaluate):
+ * kjs/interpreter.h:
+ * kjs/lexer.cpp:
+ (kjsyylex):
+ (KJS::lexer):
+ (KJS::Lexer::Lexer):
+ (KJS::Lexer::~Lexer):
+ (KJS::Lexer::scanRegExp):
+ (KJS::Lexer::doneParsing):
+ (KJS::Lexer::makeIdentifier):
+ (KJS::Lexer::makeUString):
+ * kjs/lexer.h:
+ (KJS::Lexer::pattern):
+ (KJS::Lexer::flags):
+ (KJS::Lexer::sawError):
+ * kjs/nodes.cpp:
+ (KJS::Node::Node):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ * kjs/nodes.h:
+ * kjs/testkjs.cpp:
+ (prettyPrintScript):
+ (kjsmain):
+ * kjs/ustring.cpp:
+ * kjs/ustring.h:
+
+2007-11-15 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/5601548> REGRESSION: All SourceElements and their children leak after a syntax error
+
+ Add a stub node to maintain the Vector of SourceElements until assignment.
+
+ * kjs/grammar.y:
+ * kjs/nodes.h:
+ (KJS::SourceElementsStub::SourceElementsStub):
+ (KJS::SourceElementsStub::append):
+ (KJS::SourceElementsStub::release):
+ (KJS::SourceElementsStub::):
+ (KJS::SourceElementsStub::precedence):
+
+2007-11-15 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Abstract most of RMATCH into MatchStack functions.
+
+ SunSpider claims this, combined with the last 2 patches was a 1% speedup, 10% for dna-regexp.
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::canUseStackBufferForNextFrame):
+ (MatchStack::allocateNextFrame):
+ (MatchStack::pushNewFrame):
+ (MatchStack::frameIsStackAllocated):
+ (MatchStack::popCurrentFrame):
+ (MatchStack::unrollAnyHeapAllocatedFrames):
+ (match):
+
+2007-11-15 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Remove RETURN_ERROR, add MatchStack
+
+ * pcre/pcre_exec.cpp:
+ (MatchStack::MatchStack):
+ (MatchStack::unrollAnyHeapAllocatedFrames):
+ (matchError):
+ (match):
+
+2007-11-15 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Clean up match function to match WebKit style
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * pcre/pcre_exec.cpp:
+ (match):
+
+2007-11-15 Steve Falkenburg <sfalken@apple.com>
+
+ Windows build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.make:
+
+2007-11-14 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15982
+ Improve JSString UTF-8 decoding
+
+ * API/JSStringRef.cpp:
+ (JSStringCreateWithUTF8CString): Use strict decoding, return 0 on error.
+
+ * wtf/unicode/UTF8.cpp:
+ (WTF::Unicode::convertUTF16ToUTF8):
+ (WTF::Unicode::convertUTF8ToUTF16):
+ * wtf/unicode/UTF8.h:
+ Made these function names start with a lower case letter.
+
+ * kjs/ustring.cpp: (KJS::UString::UTF8String): Updated for the above renaming.
+
+ * bindings/c/c_utility.cpp:
+ (KJS::Bindings::convertUTF8ToUTF16WithLatin1Fallback): Renamed to highlight the difference
+ from convertUTF8ToUTF16 in wtf/unicode.
+ (KJS::Bindings::convertNPStringToUTF16): Updated for the above renaming.
+ (KJS::Bindings::identifierFromNPIdentifier): Ditto.
+ * bindings/c/c_utility.h: Made convertUTF8ToUTF16WithLatin1Fallback() a file static.
+
+2007-11-14 Sam Weinig <sam@webkit.org>
+
+ Rubber-stamped by Anders.
+
+ Fix the Xcode project file after it was messed up in r27402.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-11-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ More PCRE style cleanup.
+
+ * pcre/pcre_compile.cpp:
+ (compile_regex):
+
+2007-11-14 Adam Roben <aroben@apple.com>
+
+ Clean up the bison conflict checking script
+
+ Reviewed by Geoff.
+
+ * DerivedSources.make:
+
+2007-11-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Geoff.
+
+ Another round of PCRE cleanups: inlines
+
+ SunSpider claims that this, combined with my previous PCRE cleanup were a 0.7% speedup, go figure.
+
+ * pcre/pcre_compile.cpp:
+ (jsRegExpCompile):
+ * pcre/pcre_exec.cpp:
+ (match):
+ (jsRegExpExecute):
+ * pcre/pcre_internal.h:
+ (PUT):
+ (GET):
+ (PUT2):
+ (GET2):
+ (isNewline):
+
+2007-11-14 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Sam.
+
+ Give PCRE a (small) bath.
+ Fix some formating and break things off into separate functions
+ http://bugs.webkit.org/show_bug.cgi?id=15993
+
+ * pcre/pcre_compile.cpp:
+ (calculateCompiledPatternLengthAndFlags):
+ (printCompiledRegExp):
+ (returnError):
+ (jsRegExpCompile):
+ * pcre/pcre_internal.h:
+ (compile_data::compile_data):
+
+2007-11-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Cleaned up the JavaScript grammar a bit.
+
+ 1. Changed BlockNode to always hold a child vector (which may be empty),
+ eliminating a few NULL-check branches in the common execution case.
+
+ 2. Changed the Block production to correctly report its starting and
+ ending line numbers to the debugger. (It used to report its ending line
+ as its starting line.) Also, removed duplicate line-reporting code
+ inside the BlockNode constructor.
+
+ 3. Moved curly braces up from FunctionBody production into parent
+ productions. (I had to move the line number reporting code, too, since
+ it depends on the location of the curly braces.) This matches the ECMA
+ spec more closely, and makes some future changes I plan easier.
+
+ 4. Fixed statementList* convenience functions to deal appropriately with
+ empty Vectors.
+
+ SunSpider reports a small and statistically insignificant speedup.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::statementListPushFIFO):
+ (KJS::statementListGetDeclarations):
+ (KJS::statementListInitializeDeclarationStack):
+ (KJS::statementListInitializeVariableAccessStack):
+ (KJS::BlockNode::BlockNode):
+ (KJS::BlockNode::optimizeVariableAccess):
+ (KJS::BlockNode::getDeclarations):
+ (KJS::BlockNode::execute):
+ (KJS::FunctionBodyNode::initializeDeclarationStacks):
+ (KJS::FunctionBodyNode::optimizeVariableAccess):
+
+2007-11-13 Anders Carlsson <andersca@apple.com>
+
+ Add RefCounted.h (And remove Shared.h)
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+
+2007-11-13 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix.
+
+ * kjs/regexp.h:
+
+2007-11-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Anders Carlsson.
+
+ Renamed Shared to RefCounted.
+
+ * API/JSClassRef.h:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/interpreter.h:
+ * kjs/regexp.h:
+ * wtf/RefCounted.h: Copied from JavaScriptCore/wtf/Shared.h.
+ (WTF::RefCounted::RefCounted):
+ * wtf/Shared.h: Removed.
+
+2007-11-13 Adam Roben <aroben@apple.com>
+
+ Build fix
+
+ Reviewed by Geoff.
+
+ * kjs/regexp.h: Added a missing #include.
+
+2007-11-13 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Moved Shared.h into wtf so it could be used in more places. Deployed
+ Shared in places where JSCore previously had hand-rolled ref-counting
+ classes.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::OpaqueJSClass):
+ * API/JSClassRef.h:
+ * API/JSObjectRef.cpp:
+ (JSClassRetain):
+ (JSClassRelease):
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::init):
+ * kjs/interpreter.h:
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp):
+ * kjs/regexp.h:
+ * wtf/Shared.h: Copied from WebCore/platform/Shared.h.
+
+2007-11-13 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Add an ASSERT to getTruncatedInt32 to enforce proper usage.
+ Best part about this patch? It doesn't break the web!
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::getTruncatedInt32):
+ (KJS::JSImmediate::toDouble):
+ (KJS::JSImmediate::getUInt32):
+
+2007-11-13 Alexey Proskuryakov <ap@webkit.org>
+
+ Windows build fix.
+
+ * bindings/c/c_utility.cpp:
+ (KJS::Bindings::convertUTF8ToUTF16):
+ * kjs/ustring.cpp:
+ (KJS::UString::UTF8String):
+ * wtf/unicode/UTF8.cpp:
+ (WTF::Unicode::ConvertUTF8ToUTF16):
+
+2007-11-13 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=11231
+ RegExp bug when handling newline characters
+ and a number of other differences between PCRE behvior
+ and JavaScript regular expressions:
+
+ + single-digit sequences like \4 should be treated as octal
+ character constants, unless there is a sufficient number
+ of brackets for them to be treated as backreferences
+
+ + \8 turns into the character "8", not a binary zero character
+ followed by "8" (same for 9)
+
+ + only the first 3 digits should be considered part of an
+ octal character constant (the old behavior was to decode
+ an arbitrarily long sequence and then mask with 0xFF)
+
+ + if \x is followed by anything other than two valid hex digits,
+ then it should simply be treated a the letter "x"; that includes
+ not supporting the \x{41} syntax
+
+ + if \u is followed by anything less than four valid hex digits,
+ then it should simply be treated a the letter "u"
+
+ + an extra "+" should be a syntax error, rather than being treated
+ as the "possessive quantifier"
+
+ + if a "]" character appears immediately after a "[" character that
+ starts a character class, then that's an empty character class,
+ rather than being the start of a character class that includes a
+ "]" character
+
+ + a "$" should not match a terminating newline; we could have gotten
+ PCRE to handle this the way we wanted by passing an appropriate option
+
+ Test: fast/js/regexp-no-extensions.html
+
+ * pcre/pcre_compile.cpp:
+ (check_escape): Check backreferences against bracount to catch both
+ overflows and things that should be treated as octal. Rewrite octal
+ loop to not go on indefinitely. Rewrite both hex loops to match and
+ remove \x{} support.
+ (compile_branch): Restructure loops so that we don't special-case a "]"
+ at the beginning of a character class. Remove code that treated "+" as
+ the possessive quantifier.
+ (jsRegExpCompile): Change the "]" handling here too.
+
+ * pcre/pcre_exec.cpp: (match): Changed CIRC to match the DOLL implementation.
+ Changed DOLL to remove handling of "terminating newline", a Perl concept
+ which we don't need.
+
+ * tests/mozilla/expected.html: Two tests are fixed now:
+ ecma_3/RegExp/regress-100199.js and ecma_3/RegExp/regress-188206.js.
+ One test fails now: ecma_3/RegExp/perlstress-002.js -- our success before
+ was due to a bug (we treated all 1-character numeric escapes as backreferences).
+ The date tests also now both expect success -- whatever was making them fail
+ before was probably due to the time being close to a DST shift; maybe we need
+ to get rid of those tests.
+
+2007-11-13 Darin Adler <darin@apple.com>
+
+ * kjs/JSImmediate.h: (KJS::JSImmediate::getTruncatedInt32):
+ Remove too-strong assert that was firing constantly and preventing even basic
+ web browsing from working in a debug build. This function is used in many
+ cases where the immediate value is not a number; the assertion could perhaps
+ be added back later with a bit of reorganization.
+
+2007-11-13 Alp Toker <alp@atoker.com>
+
+ Build fix for breakage to non-Mac builds introduced in r27746.
+
+ * kjs/ustring.cpp:
+
+2007-11-13 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Clean up evaluateToBoolean functions to use inlines instead of copy/paste code
+
+ * kjs/JSImmediate.h:
+ * kjs/nodes.cpp:
+ (KJS::GreaterNode::inlineEvaluateToBoolean):
+ (KJS::GreaterNode::evaluate):
+ (KJS::LessEqNode::inlineEvaluateToBoolean):
+ (KJS::LessEqNode::evaluate):
+ (KJS::GreaterEqNode::inlineEvaluateToBoolean):
+ (KJS::GreaterEqNode::evaluate):
+ (KJS::InNode::evaluateToBoolean):
+ (KJS::EqualNode::inlineEvaluateToBoolean):
+ (KJS::EqualNode::evaluate):
+ (KJS::NotEqualNode::inlineEvaluateToBoolean):
+ (KJS::NotEqualNode::evaluate):
+ (KJS::StrictEqualNode::inlineEvaluateToBoolean):
+ (KJS::StrictEqualNode::evaluate):
+ (KJS::NotStrictEqualNode::inlineEvaluateToBoolean):
+ (KJS::NotStrictEqualNode::evaluate):
+ * kjs/nodes.h:
+
+2007-11-12 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15958
+ base64 spends 1.1% of total time checking for special Infinity case
+
+ Use a fast character test instead of calling strncmp.
+
+ 1.1% speedup on string-base64. SunSpider reports a .4% speedup overall;
+ Sharks reports only .1%. Who are you going to believe? Huh?
+
+ * kjs/ustring.cpp:
+ (KJS::UString::toDouble):
+
+2007-11-12 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ Add evaluateToInt32 and evaluateUInt32 methods and deploy them.
+ Fix a few missing evaluateToBoolean methods
+ Deploy all evaluateTo* functions to more nodes to avoid slowdowns
+ http://bugs.webkit.org/show_bug.cgi?id=15950
+
+ SunSpider claims this is at least a 1.4% speedup.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::getTruncatedInt32):
+ (KJS::JSImmediate::toDouble):
+ (KJS::JSImmediate::getUInt32):
+ * kjs/nodes.cpp:
+ (KJS::ExpressionNode::evaluateToNumber):
+ (KJS::ExpressionNode::evaluateToInt32):
+ (KJS::ExpressionNode::evaluateToUInt32):
+ (KJS::NumberNode::evaluateToInt32):
+ (KJS::NumberNode::evaluateToUInt32):
+ (KJS::ImmediateNumberNode::evaluateToInt32):
+ (KJS::ImmediateNumberNode::evaluateToUInt32):
+ (KJS::ResolveNode::evaluate):
+ (KJS::ResolveNode::evaluateToNumber):
+ (KJS::ResolveNode::evaluateToBoolean):
+ (KJS::ResolveNode::evaluateToInt32):
+ (KJS::ResolveNode::evaluateToUInt32):
+ (KJS::LocalVarAccessNode::evaluateToInt32):
+ (KJS::LocalVarAccessNode::evaluateToUInt32):
+ (KJS::BracketAccessorNode::evaluateToNumber):
+ (KJS::BracketAccessorNode::evaluateToBoolean):
+ (KJS::BracketAccessorNode::evaluateToInt32):
+ (KJS::BracketAccessorNode::evaluateToUInt32):
+ (KJS::DotAccessorNode::inlineEvaluate):
+ (KJS::DotAccessorNode::evaluate):
+ (KJS::DotAccessorNode::evaluateToNumber):
+ (KJS::DotAccessorNode::evaluateToBoolean):
+ (KJS::DotAccessorNode::evaluateToInt32):
+ (KJS::DotAccessorNode::evaluateToUInt32):
+ (KJS::NewExprNode::inlineEvaluate):
+ (KJS::NewExprNode::evaluate):
+ (KJS::NewExprNode::evaluateToNumber):
+ (KJS::NewExprNode::evaluateToBoolean):
+ (KJS::NewExprNode::evaluateToInt32):
+ (KJS::NewExprNode::evaluateToUInt32):
+ (KJS::FunctionCallResolveNode::inlineEvaluate):
+ (KJS::FunctionCallResolveNode::evaluate):
+ (KJS::FunctionCallResolveNode::evaluateToNumber):
+ (KJS::FunctionCallResolveNode::evaluateToBoolean):
+ (KJS::FunctionCallResolveNode::evaluateToInt32):
+ (KJS::FunctionCallResolveNode::evaluateToUInt32):
+ (KJS::LocalVarFunctionCallNode::evaluate):
+ (KJS::LocalVarFunctionCallNode::evaluateToNumber):
+ (KJS::LocalVarFunctionCallNode::evaluateToBoolean):
+ (KJS::LocalVarFunctionCallNode::evaluateToInt32):
+ (KJS::LocalVarFunctionCallNode::evaluateToUInt32):
+ (KJS::FunctionCallDotNode::evaluate):
+ (KJS::FunctionCallDotNode::evaluateToNumber):
+ (KJS::FunctionCallDotNode::evaluateToBoolean):
+ (KJS::FunctionCallDotNode::evaluateToInt32):
+ (KJS::FunctionCallDotNode::evaluateToUInt32):
+ (KJS::PostDecLocalVarNode::inlineEvaluateToNumber):
+ (KJS::PostDecLocalVarNode::evaluateToNumber):
+ (KJS::PostDecLocalVarNode::evaluateToBoolean):
+ (KJS::PostDecLocalVarNode::evaluateToInt32):
+ (KJS::PostDecLocalVarNode::evaluateToUInt32):
+ (KJS::typeStringForValue):
+ (KJS::UnaryPlusNode::evaluate):
+ (KJS::UnaryPlusNode::evaluateToBoolean):
+ (KJS::UnaryPlusNode::evaluateToNumber):
+ (KJS::UnaryPlusNode::evaluateToInt32):
+ (KJS::BitwiseNotNode::inlineEvaluateToInt32):
+ (KJS::BitwiseNotNode::evaluate):
+ (KJS::BitwiseNotNode::evaluateToNumber):
+ (KJS::BitwiseNotNode::evaluateToBoolean):
+ (KJS::BitwiseNotNode::evaluateToInt32):
+ (KJS::MultNode::evaluateToBoolean):
+ (KJS::MultNode::evaluateToInt32):
+ (KJS::MultNode::evaluateToUInt32):
+ (KJS::DivNode::evaluateToInt32):
+ (KJS::DivNode::evaluateToUInt32):
+ (KJS::ModNode::evaluateToBoolean):
+ (KJS::ModNode::evaluateToInt32):
+ (KJS::ModNode::evaluateToUInt32):
+ (KJS::AddNode::evaluateToNumber):
+ (KJS::AddNode::evaluateToInt32):
+ (KJS::AddNode::evaluateToUInt32):
+ (KJS::AddNumbersNode::evaluateToInt32):
+ (KJS::AddNumbersNode::evaluateToUInt32):
+ (KJS::SubNode::evaluateToInt32):
+ (KJS::SubNode::evaluateToUInt32):
+ (KJS::LeftShiftNode::inlineEvaluateToInt32):
+ (KJS::LeftShiftNode::evaluate):
+ (KJS::LeftShiftNode::evaluateToNumber):
+ (KJS::LeftShiftNode::evaluateToInt32):
+ (KJS::RightShiftNode::inlineEvaluateToInt32):
+ (KJS::RightShiftNode::evaluate):
+ (KJS::RightShiftNode::evaluateToNumber):
+ (KJS::RightShiftNode::evaluateToInt32):
+ (KJS::UnsignedRightShiftNode::inlineEvaluateToUInt32):
+ (KJS::UnsignedRightShiftNode::evaluate):
+ (KJS::UnsignedRightShiftNode::evaluateToNumber):
+ (KJS::UnsignedRightShiftNode::evaluateToInt32):
+ (KJS::LessNode::inlineEvaluateToBoolean):
+ (KJS::LessNode::evaluate):
+ (KJS::LessNode::evaluateToBoolean):
+ (KJS::LessNumbersNode::inlineEvaluateToBoolean):
+ (KJS::LessNumbersNode::evaluate):
+ (KJS::LessNumbersNode::evaluateToBoolean):
+ (KJS::LessStringsNode::inlineEvaluateToBoolean):
+ (KJS::LessStringsNode::evaluate):
+ (KJS::BitAndNode::evaluate):
+ (KJS::BitAndNode::inlineEvaluateToInt32):
+ (KJS::BitAndNode::evaluateToNumber):
+ (KJS::BitAndNode::evaluateToBoolean):
+ (KJS::BitAndNode::evaluateToInt32):
+ (KJS::BitXOrNode::inlineEvaluateToInt32):
+ (KJS::BitXOrNode::evaluate):
+ (KJS::BitXOrNode::evaluateToNumber):
+ (KJS::BitXOrNode::evaluateToBoolean):
+ (KJS::BitXOrNode::evaluateToInt32):
+ (KJS::BitOrNode::inlineEvaluateToInt32):
+ (KJS::BitOrNode::evaluate):
+ (KJS::BitOrNode::evaluateToNumber):
+ (KJS::BitOrNode::evaluateToBoolean):
+ (KJS::BitOrNode::evaluateToInt32):
+ (KJS::ConditionalNode::evaluateToNumber):
+ (KJS::ConditionalNode::evaluateToInt32):
+ (KJS::ConditionalNode::evaluateToUInt32):
+ (KJS::valueForReadModifyAssignment):
+ (KJS::AssignExprNode::evaluate):
+ (KJS::AssignExprNode::evaluateToBoolean):
+ (KJS::AssignExprNode::evaluateToNumber):
+ (KJS::AssignExprNode::evaluateToInt32):
+ (KJS::VarDeclNode::handleSlowCase):
+ * kjs/nodes.h:
+ (KJS::FunctionCallResolveNode::precedence):
+ (KJS::AddNode::precedence):
+ (KJS::AddNode::):
+ (KJS::LessNumbersNode::):
+ (KJS::LessStringsNode::):
+ * kjs/value.cpp:
+ (KJS::JSValue::toInt32SlowCase):
+ (KJS::JSValue::toUInt32SlowCase):
+ * kjs/value.h:
+ (KJS::JSValue::asCell):
+ (KJS::JSValue::toInt32):
+ (KJS::JSValue::toUInt32):
+
+2007-11-12 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15953
+ Add UTF-8 encoding/decoding to WTF
+
+ * kjs/ustring.h: Moved UTF8SequenceLength() and decodeUTF8Sequence() to wtf/unicode.
+ * kjs/ustring.cpp: (KJS::UString::UTF8String): Changed this function to take a strict/lenient
+ parameter. Callers are not interested in getting decoding results in strict mode, so
+ this allows for bailing out as soon as an error is seen.
+
+ * kjs/function.cpp:
+ (KJS::encode): Updated for new UString::UTF8String() signature.
+
+ * API/JSStringRef.cpp:
+ (JSStringCreateWithCharacters): Disambiguate UChar.
+ (JSStringCreateWithUTF8CString): Actually use UTF-8 when creating the string!
+ * bindings/c/c_utility.cpp: (KJS::Bindings::convertUTF8ToUTF16): Use ConvertUTF8ToUTF16().
+
+ * wtf/unicode/UTF8.cpp: Added.
+ (WTF::Unicode::inlineUTF8SequenceLengthNonASCII):
+ (WTF::Unicode::inlineUTF8SequenceLength):
+ (WTF::Unicode::UTF8SequenceLength):
+ (WTF::Unicode::decodeUTF8Sequence):
+ (WTF::Unicode::):
+ (WTF::Unicode::ConvertUTF16ToUTF8):
+ (WTF::Unicode::isLegalUTF8):
+ (WTF::Unicode::ConvertUTF8ToUTF16):
+ * wtf/unicode/UTF8.h: Added.
+ (WTF::Unicode::):
+ Some code moved from ustring.h, some adapted from unicode.org sources.
+
+ * JavaScriptCore.exp:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ Added UTF8.{h,cpp}
+
+2007-11-12 Josh Aas <joshmoz@gmail.com>
+
+ Reviewed by Darin.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15946
+ add NPPValue NPPVpluginDrawingModel (Mozilla bug 403418 compat)
+
+ * bindings/npapi.h:
+
+2007-11-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15951
+ REGRESSION: assertion failure in regexp match() when running JS tests
+
+ Test: fast/js/regexp-many-brackets.html
+
+ * pcre/pcre_exec.cpp: (match): Added back accidentally-removed case for
+ the BRANUMBER opcode.
+
+2007-11-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix use of prefix and config.h, got rid of a few unneeded things in
+ the PCRE code; no behavior changes
+
+ * API/JSBase.cpp: Added include of config.h.
+ * API/JSCallbackConstructor.cpp: Ditto.
+ * API/JSCallbackFunction.cpp: Ditto.
+ * API/JSCallbackObject.cpp: Ditto.
+ * API/JSClassRef.cpp: Ditto.
+ * API/JSContextRef.cpp: Ditto.
+ * API/JSObjectRef.cpp: Ditto.
+ * API/JSStringRef.cpp: Ditto.
+ * API/JSValueRef.cpp: Ditto.
+
+ * JavaScriptCorePrefix.h: Removed obsolete <ctype.h> workaround.
+ Moved new/delete macros after includes, as they are in WebCore's prefix.
+ Removed "config.h".
+
+ * pcre/dftables.cpp: (main): Changed back to not use a separate maketables
+ function. This is needed for PCRE, but not helpful for our use. Also changed
+ the tables to all be 128 entries long instead of 256, since only the first
+ 128 are ever used.
+
+ * pcre/pcre_compile.cpp: Added include of config.h. Eliminated digitab,
+ which was only being used to check hex digits. Changed all uses of TRUE and
+ FALSE to use the C++ true and false instead.
+ (check_escape): Just the TRUE/FALSE thing.
+ (is_counted_repeat): Ditto.
+ (could_be_empty_branch): Ditto.
+ (get_othercase_range): Ditto.
+ (compile_branch): Ditto.
+ (compile_regex): Ditto.
+ (is_anchored): Ditto.
+ (is_startline): Ditto.
+ (find_firstassertedchar): Ditto.
+ (jsRegExpCompile): Ditto.
+
+ * pcre/pcre_exec.cpp: Added include of config.h. Changed all uses of TRUE and
+ FALSE to use the C++ true and false instead.
+ (match_ref): Just the TRUE/FALSE thing.
+ (match): Ditto. Removed some unneeded braces.
+ (jsRegExpExecute): Just the TRUE/FALSE thing.
+
+ * pcre/pcre_internal.h: Moved the constants needed by dftables.cpp to the top
+ of the file instead of the bottom, so they can be used. Also changed the table
+ sizes to 128 instead of 256. Removed macro definitions of FALSE and TRUE.
+ Set array sizes for all the const arrays. Changed _pcre_utf8_table1_size to
+ be a macro instead of a extern int.
+
+ * pcre/pcre_maketables.cpp: Removed. It's all in dftables.cpp now.
+
+ * pcre/pcre_tables.cpp: Made table sizes explicit.
+
+ * pcre/pcre_xclass.cpp: Just the TRUE/FALSE thing.
+
+2007-11-12 Adam Roben <aroben@apple.com>
+
+ Build fix
+
+ * wtf/FastMalloc.h: Add missing using statement.
+
+2007-11-11 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Add special fastZeroedMalloc function to replace a
+ number of fastCalloc calls where one argument was 1.
+
+ This results in a 0.4% progression in SunSpider, more
+ than making up for the earlier regression caused by
+ additional overflow checks.
+
+ * JavaScriptCore.exp:
+ * kjs/array_instance.cpp:
+ * kjs/property_map.cpp:
+ * wtf/FastMalloc.cpp:
+ * wtf/FastMalloc.h:
+ * wtf/HashTable.h:
+
+2007-11-11 Adam Roben <aroben@apple.com>
+
+ Fix <rdar://5578982> ASSERT in HashTable::checkTableConsistencyExceptSize beneath WebNotificationCenter
+
+ The bug was due to a mismatch between HashMap::remove and
+ HashTable::checkTableConsistency. HashMap::remove can delete the value
+ stored in the HashTable (by derefing it), which is not normally
+ allowed by HashTable. It's OK in this case because the value is about
+ to be removed from the table, but HashTable wasn't aware of this.
+
+ HashMap::remove now performs the consistency check itself before
+ derefing the value.
+
+ Darin noticed that the same bug would occur in HashSet, so I've fixed
+ it there as well.
+
+ Reviewed by Darin.
+
+ * wtf/HashMap.h:
+ (WTF::HashMap::remove): Perform the HashTable consistency check
+ manually before calling deref.
+ * wtf/HashSet.h:
+ (WTF::HashSet::remove): Ditto.
+ * wtf/HashTable.h: Made checkTableConsistency public so that HashMap
+ and HashSet can call it.
+ (WTF::HashTable::removeAndInvalidateWithoutEntryConsistencyCheck):
+ Added.
+ (WTF::HashTable::removeAndInvalidate): Added.
+ (WTF::HashTable::remove):
+ (WTF::HashTable::removeWithoutEntryConsistencyCheck): Added.
+
+2007-11-11 Mark Rowe <mrowe@apple.com>
+
+ Build fix. Use the correct filename case.
+
+ * kjs/nodes.h:
+
+2007-11-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15902
+ 15% of string-validate-input.js is spent compiling the same regular expression
+
+ Store a compiled representation of the regular expression in the AST.
+
+ Only a .2% SunSpider speedup overall, but a 10.6% speedup on
+ string-validate-input.js.
+
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::RegExpNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::RegExpNode::streamTo):
+ * kjs/regexp.cpp:
+ (KJS::RegExp::flags):
+ * kjs/regexp.h:
+ (KJS::RegExp::pattern):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpObjectImp::construct):
+ (KJS::RegExpObjectImp::createRegExpImp):
+ * kjs/regexp_object.h:
+
+2007-11-11 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Eric.
+
+ Partial fix for <rdar://problem/5585334> numfuzz: integer overflows opening malformed SVG file in WebCore::ImageBuffer::create
+
+ Unfortunately this is a very slight regression, but is unavoidable.
+
+ * wtf/FastMalloc.cpp:
+
+2007-11-10 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Add simple type inferencing to the parser, and create custom
+ AddNode and LessNode subclasses based on inferred types.
+ http://bugs.webkit.org/show_bug.cgi?id=15884
+
+ SunSpider claims this is at least a 0.5% speedup.
+
+ * JavaScriptCore.exp:
+ * kjs/grammar.y:
+ * kjs/internal.cpp:
+ (KJS::NumberImp::getPrimitiveNumber):
+ (KJS::GetterSetterImp::getPrimitiveNumber):
+ * kjs/internal.h:
+ * kjs/lexer.cpp:
+ (KJS::Lexer::lex):
+ * kjs/nodes.cpp:
+ (KJS::Node::Node):
+ (KJS::StringNode::evaluate):
+ (KJS::StringNode::evaluateToNumber):
+ (KJS::StringNode::evaluateToBoolean):
+ (KJS::RegExpNode::evaluate):
+ (KJS::UnaryPlusNode::optimizeVariableAccess):
+ (KJS::AddNode::evaluate):
+ (KJS::AddNode::evaluateToNumber):
+ (KJS::AddNumbersNode::inlineEvaluateToNumber):
+ (KJS::AddNumbersNode::evaluate):
+ (KJS::AddNumbersNode::evaluateToNumber):
+ (KJS::AddStringsNode::evaluate):
+ (KJS::AddStringLeftNode::evaluate):
+ (KJS::AddStringRightNode::evaluate):
+ (KJS::lessThan):
+ (KJS::lessThanEq):
+ (KJS::LessNumbersNode::evaluate):
+ (KJS::LessStringsNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::RegExpNode::):
+ (KJS::RegExpNode::precedence):
+ (KJS::TypeOfResolveNode::):
+ (KJS::LocalVarTypeOfNode::):
+ (KJS::UnaryPlusNode::):
+ (KJS::UnaryPlusNode::precedence):
+ (KJS::AddNode::):
+ (KJS::AddNode::precedence):
+ (KJS::AddNumbersNode::):
+ (KJS::AddStringLeftNode::):
+ (KJS::AddStringRightNode::):
+ (KJS::AddStringsNode::):
+ (KJS::LessNode::):
+ (KJS::LessNode::precedence):
+ (KJS::LessNumbersNode::):
+ (KJS::LessStringsNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::StringNode::streamTo):
+ * kjs/object.cpp:
+ * kjs/object.h:
+ * kjs/value.h:
+ (KJS::JSValue::getPrimitiveNumber):
+
+2007-11-11 Darin Adler <darin@apple.com>
+
+ - try another way of fixing dftables builds -- refactor pcre_internal.h a bit
+
+ * pcre/pcre_internal.h: Make most of this header do nothing when DFTABLES is set.
+ Later we can break it into two files.
+
+ * JavaScriptCore.vcproj/dftables/dftables.vcproj: Take out now-unneeded include paths.
+ * pcre/dftables.cpp: Set DFTABLES. Use delete instead of free.
+ * pcre/dftables.pro: Take out now-unneeded include paths.
+ * pcre/pcre_maketables.cpp: Use new instead of malloc.
+
+2007-11-11 Darin Adler <darin@apple.com>
+
+ * pcre/dftables.pro: Try fixing Qt builds (I looked at qt-win) by adding
+ another include path.
+
+2007-11-11 Darin Adler <darin@apple.com>
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Try fixing Mac Tiger builds
+ by adding another include path.
+
+2007-11-11 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15924
+ next round of changes to JSRegExp (formerly PCRE)
+
+ This is a combination of converting to C++, tweaking the API, and adding
+ some additional optimizations.
+
+ Future steps will involve getting rid of the use of UTF-8 completely
+ (we'll use UTF-16 exclusively instead), eliminating more source files,
+ and some more speed-ups.
+
+ SunSpider says the current round is an 0.9% speed-up overall, and a
+ 5.3% speed-up for regexp.
+
+ * JavaScriptCore.exp: Updated for new entry points.
+
+ * JavaScriptCore.pri:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.vcproj/dftables/dftables.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * jscore.bkl:
+ Updated for new source file names and ForwardingHeaders.
+
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp): Changed to use the error message without calling
+ strdup on it and to pass the new types and options.
+ (KJS::RegExp::~RegExp): Removed the now-unneeded free of the error message.
+ (KJS::RegExp::match): Pass the new types and options.
+ * kjs/regexp.h: Update type of m_constructionError.
+
+ * pcre/AUTHORS: Update to reflect the status of the project -- we don't include
+ the Google parts, and this isn't the PCRE library, per se.
+ * pcre/COPYING: Ditto.
+
+ * pcre/dftables.cpp: Copied from JavaScriptCore/pcre/dftables.c.
+ (main): Removed unneeded ctype_digit.
+
+ * pcre/pcre.h: Convert to C++, tweak API a bit. Use UChar instead of JSRegExpChar.
+
+ * pcre/pcre_compile.cpp: Copied from JavaScriptCore/pcre/pcre_compile.c.
+ Moved a lot of private stuff used only within this file here from pcre_internal.h.
+ Renumbered the error codes.
+ (error_text): Use a single string with embedded nulls for the error text (I got
+ this idea from newer versions of PCRE).
+ (check_escape): Changed return type to be enum instead of int. Replaced ctype_digit
+ uses with isASCIIDigit.
+ (is_counted_repeat): Ditto.
+ (read_repeat_counts): Ditto.
+ (first_significant_code): Ditto.
+ (find_fixedlength): Ditto.
+ (could_be_empty_branch): Ditto.
+ (compile_branch): Ditto. Also removed some code that handles changing options.
+ JavaScript doesn't have any of the features that allow options to change.
+ (compile_regex): Updated for change to options parameter.
+ (is_anchored): Ditto.
+ (find_firstassertedchar): Ditto.
+ (jsRegExpCompile): Changed to take separate flags instead of an options int.
+ Also changed to call new/delete instead of pcre_malloc/free.
+ (jsRegExpFree): Ditto.
+
+ * pcre/pcre_exec.cpp: Copied from JavaScriptCore/pcre/pcre_exec.c.
+ Added a case that uses computed goto for the opcode loop, but did not turn it on.
+ Changed the RMATCH macro to handle returns more efficiently by putting the where
+ pointer in the new frame instead of the old one, allowing us to branch to the
+ return with a single statement. Switched to new/delete from pcre_malloc/free.
+ Changed many RRETURN callers to not set the return value since it's already
+ set correctly. Replaced the rrc variable with an is_match variable. Values other
+ than "match" and "no match" are now handled differently. This allows us to remove
+ the code to check for those cases in various rules.
+ (match): All the case statements use a macro BEGIN_OPCODE instead. And all the
+ continue statements, or break statements that break out of the outer case use
+ a macro NEXT_OPCODE instead. Replaced a few if statements with assertions.
+ (jsRegExpExecute): Use new/delete instead of pcre_malloc/free. Removed unused
+ start_match field from the match block.
+
+ * pcre/pcre_internal.h: Moved the last few configuration macros from pcre-config.h
+ in here. Removed various unused types. Converted from JSRegExpChar to UChar.
+ Eliminated pcre_malloc/free. Replaced the opcode enum with a macro that can be
+ used in multiple places. Unfortunately we lose the comments for each opcode; we
+ should find a place to put those back. Removed ctype_digit.
+
+ * pcre/pcre_maketables.cpp: Copied from JavaScriptCore/pcre/pcre_maketables.c.
+ (pcre_maketables): Got rid of the conditional code that allows this to be compiled
+ in -- it's only used for dftables now (and soon may be obsolete entirely).
+ Changed code for cbit_digit to not use isdigit, and took the "_" case out of the
+ loop. Removed ctype_digit.
+
+ * pcre/pcre_ord2utf8.cpp: Copied from JavaScriptCore/pcre/pcre_ord2utf8.c.
+
+ * pcre/pcre_tables.cpp: Copied from JavaScriptCore/pcre/pcre_tables.c.
+ Moved _pcre_OP_lengths out of here into pcre_exec.cpp.
+
+ * pcre/pcre_ucp_searchfuncs.cpp: Copied from JavaScriptCore/pcre/pcre_ucp_searchfuncs.c.
+ Updated for other file name changes.
+
+ * pcre/pcre_xclass.cpp: Copied from JavaScriptCore/pcre/pcre_xclass.c.
+
+ * pcre/ucpinternal.h: Updated header.
+
+ * pcre/ucptable.cpp: Copied from JavaScriptCore/pcre/ucptable.c.
+
+ * wtf/ASCIICType.h: (WTF::isASCIIDigit): Removed a branch by changing from && to
+ & for this operation. Also added an overload that takes an int because that's
+ useful for PCRE. Later we could optimize for int and overload other functions in
+ this file; stuck to this simple one for now.
+
+ * wtf/unicode/icu/UnicodeIcu.h: Removed unused isUpper.
+ * wtf/unicode/qt4/UnicodeQt4.h: Ditto.
+
+ * pcre/LICENCE: Removed.
+ * pcre/pcre-config.h: Removed.
+ * wtf/FastMallocPCRE.cpp: Removed.
+
+ * pcre/dftables.c: Renamed to cpp.
+ * pcre/pcre_compile.c: Ditto.
+ * pcre/pcre_exec.c: Ditto.
+ * pcre/pcre_maketables.c: Ditto.
+ * pcre/pcre_ord2utf8.c: Ditto.
+ * pcre/pcre_tables.c: Ditto.
+ * pcre/pcre_ucp_searchfuncs.c: Ditto.
+ * pcre/pcre_xclass.c: Ditto.
+ * pcre/ucptable.c: Ditto.
+
+2007-11-11 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Oliver.
+
+ Add KJS_CHECKEXCEPTIONBOOLEAN to match rest of nodes.cpp
+
+ * kjs/nodes.cpp:
+ (KJS::ExpressionNode::evaluateToBoolean):
+ (KJS::LessNode::evaluateToBoolean):
+ (KJS::GreaterNode::evaluateToBoolean):
+ (KJS::LessEqNode::evaluateToBoolean):
+ (KJS::GreaterEqNode::evaluateToBoolean):
+ (KJS::InstanceOfNode::evaluateToBoolean):
+ (KJS::InNode::evaluateToBoolean):
+ (KJS::EqualNode::evaluateToBoolean):
+ (KJS::NotEqualNode::evaluateToBoolean):
+ (KJS::StrictEqualNode::evaluateToBoolean):
+ (KJS::NotStrictEqualNode::evaluateToBoolean):
+ (KJS::LogicalAndNode::evaluateToBoolean):
+ (KJS::LogicalOrNode::evaluateToBoolean):
+ (KJS::ConditionalNode::evaluateToBoolean):
+
+2007-11-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15927
+ REGRESSION(r27487): delete a.c followed by __defineGetter__("c", ...) incorrectly deletes another property
+ and <rdar://problem/5586384> REGRESSION (r27487): Can't switch out of Edit HTML Source mode on Leopard Wiki
+
+ Test: fast/js/delete-then-put.html
+
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::put): Added a missing "- 1"; code to find an empty slot was not working.
+ (KJS::PropertyMap::checkConsistency): Added a missing range check that would have caught this
+ problem before.
+
+ - roll out a last-minute change to my evaluateToBoolean patch that was incorrect.
+
+ * kjs/nodes.h: (KJS::ExprStatementNode::ExprStatementNode): Take out call to
+ optimizeForUnnecessaryResult, since the result is used in some cases.
+
+2007-11-10 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ Roll out some changes that were (seemingly accidentally) checked in
+ with r27664.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-11-10 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15915
+ add an evaluation path for booleans like the one we have for numbers
+
+ Gives 1.1% on SunSpider.
+
+ * kjs/grammar.y: Create TrueNode and FalseNode instead of BooleanNode.
+
+ * kjs/nodes.h: Changed to use Noncopyable. Moved optimizeForUnnecessaryResult
+ down from Node to ExpressionNode. Changed some classes to not inherit from
+ ExpressionNode where not necessary, and removed unnneeded evaluate functions
+ as well as evaluate functions that need not be virtual. Call the
+ optimizeForUnnecessaryResult function on the start of a for loop too.
+ * kjs/nodes.cpp:
+ (KJS::ExpressionNode::evaluateToBoolean): Added.
+ (KJS::FalseNode::evaluate): Added.
+ (KJS::TrueNode::evaluate): Added.
+ (KJS::NumberNode::evaluateToBoolean): Added.
+ (KJS::StringNode::evaluateToBoolean): Added.
+ (KJS::LocalVarAccessNode::evaluateToBoolean): Added.
+ (KJS::BracketAccessorNode::evaluateToBoolean): Added.
+ (KJS::LogicalNotNode::evaluate): Changed to call evaluateToBoolean.
+ (KJS::LogicalNotNode::evaluateToBoolean): Added.
+ (KJS::lessThan): Changed to return bool.
+ (KJS::lessThanEq): Ditto.
+ (KJS::LessNode::evaluate): Changed since lessThan returns bool.
+ (KJS::LessNode::evaluateToBoolean): Added.
+ (KJS::GreaterNode::evaluate): Changed since lessThanEq returns bool.
+ (KJS::GreaterNode::evaluateToBoolean): Added.
+ (KJS::LessEqNode::evaluate): Changed since lessThanEq returns bool.
+ (KJS::LessEqNode::evaluateToBoolean): Added.
+ (KJS::GreaterEqNode::evaluate): Changed since lessThan returns bool.
+ (KJS::GreaterEqNode::evaluateToBoolean): Added.
+ (KJS::InstanceOfNode::evaluateToBoolean): Added.
+ (KJS::InNode::evaluateToBoolean): Added.
+ (KJS::EqualNode::evaluateToBoolean): Added.
+ (KJS::NotEqualNode::evaluateToBoolean): Added.
+ (KJS::StrictEqualNode::evaluateToBoolean): Added.
+ (KJS::NotStrictEqualNode::evaluateToBoolean): Added.
+ (KJS::ConditionalNode::evaluate): Changed to call evaluateToBoolean.
+ (KJS::IfNode::execute): Ditto.
+ (KJS::DoWhileNode::execute): Ditto.
+ (KJS::WhileNode::execute): Ditto.
+ (KJS::ForNode::execute): Ditto.
+
+ * kjs/nodes2string.cpp:
+ (KJS::FalseNode::streamTo): Added.
+ (KJS::TrueNode::streamTo): Added.
+
+2007-11-09 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ Reviewed by Darin.
+
+ * kjs/value.h:
+ (KJS::jsNumber): Add some explicit casts.
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ - fix build
+
+ * kjs/grammar.y:
+ * kjs/nodes.h:
+ * kjs/property_map.cpp:
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ - roll out accidentally-checked in changes
+
+ * kjs/nodes.cpp: Back to previous version.
+ * kjs/nodes.h: Ditto.
+ * kjs/grammar.y: Ditto.
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15912
+ fasta spends a lot of time in qsort
+
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::getEnumerablePropertyNames):
+ Use insertion sort instead of qsort for small sets of property names.
+ We can probably do some even-better speedups of for/in, but this nets
+ 0.6% overall and 6.7% on fasta.
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15906
+ getting characters by indexing into a string is very slow
+
+ This fixes one source of the slowness -- the conversion to an unused
+ Identifier as we call the get function from the slot -- but doesn't
+ fix others, such as the fact that we have to allocate a new UString::Rep
+ for every single character.
+
+ Speeds up string-base64 30%, and at least 0.5% overall.
+ But does slow down access-fannkuch quite a bit. Might be worth
+ revisiting in the future to see what we can do about that (although
+ I did look at a profile for a while).
+
+ * kjs/property_slot.h: Add a new marker for "numeric" property slots;
+ slots where we don't need to pass the identifier to the get function.
+ (KJS::PropertySlot::getValue): Added code to call the numeric get function.
+ (KJS::PropertySlot::setCustomNumeric): Added.
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::indexGetter): Changed to use substr() instead
+ of constructing a wholly new UString each time.
+ (KJS::stringInstanceNumericPropertyGetter): Added. Like indexGetter, but
+ takes advantage of setCustomNumeric to avoid creating an Identifier.
+ (KJS::StringInstance::getOwnPropertySlot): Changed to use setCustomNumeric.
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15904
+ more speed-ups possible by tightening up int version of JSImmediate
+
+ 1% improvement of SunSpider
+
+ * kjs/JSImmediate.h: Eliminate the now-unneeded FPBitValues struct template.
+ (KJS::JSImmediate::from): Overload for most numeric types; many types can
+ do fewer branches and checks.
+ (KJS::JSImmediate::getUInt32): Removed unneeded check for undefined.
+ (KJS::JSImmediate::getTruncatedInt32): Ditto.
+ (KJS::JSImmediate::getTruncatedUInt32): Ditto. There's no difference any more
+ between getUInt32 and getTruncatedUInt32, so that's worth a rename and merge later.
+
+ * kjs/grammar.y: Update since fromDouble is now just from.
+ * kjs/nodes.h: Ditto.
+
+ * kjs/value.h: (KJS::jsNumber): Overload for most numeric types.
+
+2007-11-08 Kevin Ollivier <kevino@theolliviers.com>
+
+ Bakefiles for building JavaScriptCore, needed by wx port.
+
+ Reviewed by Mark Rowe.
+
+ * JavaScriptCoreSources.bkl: Added.
+ * jscore.bkl: Added.
+
+2007-11-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Fix regression caused by earlier bitwise and optimisation. 1 & undefined != 1.
+
+ The implementation of JSImmediate::areBothImmediateNumbers relies on
+ (JSImmediate::getTag(immediate1) & JSImmediate::getTag(immediate2)) having
+ a unique result when both immediate values are numbers.
+
+ The regression was due to UndefinedType & NumberType returning NumberType (3 & 1).
+ By swapping the value of NumberType and UndefinedType this ceases to be a problem.
+
+ * kjs/JSType.h:
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ - fix build
+
+ * kjs/nodes.h: Add missing parameter name.
+
+2007-11-08 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Add ExpressionNode subclass of Node, use it.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ForInNode::ForInNode):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::NullNode::):
+ (KJS::NullNode::precedence):
+ (KJS::BooleanNode::):
+ (KJS::BooleanNode::precedence):
+ (KJS::RegExpNode::):
+ (KJS::RegExpNode::precedence):
+ (KJS::ThisNode::):
+ (KJS::ThisNode::precedence):
+ (KJS::ResolveNode::):
+ (KJS::ElementNode::):
+ (KJS::ArrayNode::):
+ (KJS::PropertyNode::):
+ (KJS::PropertyNode::precedence):
+ (KJS::PropertyNode::name):
+ (KJS::PropertyListNode::):
+ (KJS::ObjectLiteralNode::):
+ (KJS::ObjectLiteralNode::precedence):
+ (KJS::BracketAccessorNode::):
+ (KJS::DotAccessorNode::):
+ (KJS::DotAccessorNode::precedence):
+ (KJS::ArgumentListNode::):
+ (KJS::ArgumentsNode::):
+ (KJS::NewExprNode::):
+ (KJS::NewExprNode::precedence):
+ (KJS::FunctionCallValueNode::):
+ (KJS::FunctionCallValueNode::precedence):
+ (KJS::FunctionCallResolveNode::):
+ (KJS::FunctionCallBracketNode::):
+ (KJS::FunctionCallBracketNode::precedence):
+ (KJS::FunctionCallDotNode::):
+ (KJS::FunctionCallDotNode::precedence):
+ (KJS::PrePostResolveNode::):
+ (KJS::PostfixBracketNode::):
+ (KJS::PostfixBracketNode::precedence):
+ (KJS::PostIncBracketNode::):
+ (KJS::PostIncBracketNode::isIncrement):
+ (KJS::PostDecBracketNode::):
+ (KJS::PostDecBracketNode::isIncrement):
+ (KJS::PostfixDotNode::):
+ (KJS::PostfixDotNode::precedence):
+ (KJS::PostIncDotNode::):
+ (KJS::PostIncDotNode::isIncrement):
+ (KJS::PostDecDotNode::):
+ (KJS::PostDecDotNode::isIncrement):
+ (KJS::PostfixErrorNode::):
+ (KJS::PostfixErrorNode::precedence):
+ (KJS::DeleteResolveNode::):
+ (KJS::DeleteBracketNode::):
+ (KJS::DeleteBracketNode::precedence):
+ (KJS::DeleteDotNode::):
+ (KJS::DeleteDotNode::precedence):
+ (KJS::DeleteValueNode::):
+ (KJS::DeleteValueNode::precedence):
+ (KJS::VoidNode::):
+ (KJS::VoidNode::precedence):
+ (KJS::TypeOfResolveNode::):
+ (KJS::TypeOfValueNode::):
+ (KJS::PrefixBracketNode::):
+ (KJS::PrefixBracketNode::precedence):
+ (KJS::PreIncBracketNode::):
+ (KJS::PreIncBracketNode::isIncrement):
+ (KJS::PreDecBracketNode::):
+ (KJS::PreDecBracketNode::isIncrement):
+ (KJS::PrefixDotNode::):
+ (KJS::PrefixDotNode::precedence):
+ (KJS::PreIncDotNode::):
+ (KJS::PreIncDotNode::isIncrement):
+ (KJS::PreDecDotNode::):
+ (KJS::PreDecDotNode::isIncrement):
+ (KJS::PrefixErrorNode::):
+ (KJS::PrefixErrorNode::precedence):
+ (KJS::UnaryPlusNode::):
+ (KJS::UnaryPlusNode::precedence):
+ (KJS::NegateNode::):
+ (KJS::NegateNode::precedence):
+ (KJS::BitwiseNotNode::):
+ (KJS::BitwiseNotNode::precedence):
+ (KJS::LogicalNotNode::):
+ (KJS::LogicalNotNode::precedence):
+ (KJS::AddNode::):
+ (KJS::AddNode::precedence):
+ (KJS::LeftShiftNode::):
+ (KJS::LeftShiftNode::precedence):
+ (KJS::RightShiftNode::):
+ (KJS::RightShiftNode::precedence):
+ (KJS::UnsignedRightShiftNode::):
+ (KJS::UnsignedRightShiftNode::precedence):
+ (KJS::LessNode::):
+ (KJS::LessNode::precedence):
+ (KJS::GreaterNode::):
+ (KJS::GreaterNode::precedence):
+ (KJS::LessEqNode::):
+ (KJS::LessEqNode::precedence):
+ (KJS::GreaterEqNode::):
+ (KJS::GreaterEqNode::precedence):
+ (KJS::InstanceOfNode::):
+ (KJS::InstanceOfNode::precedence):
+ (KJS::InNode::):
+ (KJS::InNode::precedence):
+ (KJS::EqualNode::):
+ (KJS::EqualNode::precedence):
+ (KJS::NotEqualNode::):
+ (KJS::NotEqualNode::precedence):
+ (KJS::StrictEqualNode::):
+ (KJS::StrictEqualNode::precedence):
+ (KJS::NotStrictEqualNode::):
+ (KJS::NotStrictEqualNode::precedence):
+ (KJS::BitAndNode::):
+ (KJS::BitAndNode::precedence):
+ (KJS::BitOrNode::):
+ (KJS::BitOrNode::precedence):
+ (KJS::BitXOrNode::):
+ (KJS::BitXOrNode::precedence):
+ (KJS::LogicalAndNode::):
+ (KJS::LogicalAndNode::precedence):
+ (KJS::LogicalOrNode::):
+ (KJS::LogicalOrNode::precedence):
+ (KJS::ConditionalNode::):
+ (KJS::ConditionalNode::precedence):
+ (KJS::ReadModifyResolveNode::):
+ (KJS::ReadModifyResolveNode::precedence):
+ (KJS::AssignResolveNode::):
+ (KJS::AssignResolveNode::precedence):
+ (KJS::ReadModifyBracketNode::):
+ (KJS::ReadModifyBracketNode::precedence):
+ (KJS::AssignBracketNode::):
+ (KJS::AssignBracketNode::precedence):
+ (KJS::AssignDotNode::):
+ (KJS::AssignDotNode::precedence):
+ (KJS::ReadModifyDotNode::):
+ (KJS::ReadModifyDotNode::precedence):
+ (KJS::AssignErrorNode::):
+ (KJS::AssignErrorNode::precedence):
+ (KJS::CommaNode::):
+ (KJS::CommaNode::precedence):
+ (KJS::AssignExprNode::):
+ (KJS::AssignExprNode::precedence):
+ (KJS::ExprStatementNode::):
+ (KJS::IfNode::):
+ (KJS::DoWhileNode::):
+ (KJS::WhileNode::):
+ (KJS::ReturnNode::):
+ (KJS::WithNode::):
+ (KJS::ThrowNode::):
+ (KJS::ParameterNode::):
+ (KJS::CaseClauseNode::):
+ (KJS::CaseClauseNode::precedence):
+ (KJS::ClauseListNode::):
+ (KJS::SwitchNode::):
+
+2007-11-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Sam.
+
+ Add a fast path for bitwise-and of two immediate numbers for a 0.7% improvement in SunSpider (4% bitop improvement).
+
+ This only improves bitwise-and performance, as the additional logic required
+ for similar code paths on or, xor, and shifting requires additional operations
+ and branches that negate (and in certain cases, regress) any advantage we might
+ otherwise receive.
+
+ This improves performance on all bitop tests, the cryptography tests, as well as
+ the string-base64 and string-unpack-code tests. No significant degradation on
+ any other tests.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::areBothImmediateNumbers):
+ (KJS::JSImmediate::andImmediateNumbers):
+ * kjs/nodes.cpp:
+ (KJS::BitAndNode::evaluate):
+ * kjs/value.h:
+ (KJS::jsNumberFromAnd):
+
+2007-11-08 Adam Roben <aroben@apple.com>
+
+ Stop using KJS inside of MathExtras.h
+
+ Reviewed by Darin.
+
+ * wtf/MathExtras.h: Removed an unused header, and a now-unused
+ forward-declaration.
+ (wtf_atan2): Use std::numeric_limits intead of KJS.
+
+2007-11-08 Sam Weinig <sam@webkit.org>
+
+ Windows build fix.
+
+ * kjs/date_object.cpp:
+ (KJS::DateProtoFuncToLocaleString::callAsFunction): Fix unused arg warning.
+ (KJS::DateProtoFuncToLocaleDateString::callAsFunction): ditto
+ (KJS::DateProtoFuncToLocaleTimeString::callAsFunction): ditto
+
+2007-11-08 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/lookup.h: Add missing include.
+
+2007-11-08 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin.
+
+ Convert JavaScript internal function objects to use one class per
+ function. This avoids a switch statement inside what used to be
+ the shared function classes and will allow Shark to better analyze
+ the code.
+
+ To make this switch, the value property of the HashEntry was changed
+ to a union of an intptr_t (which is used to continue handle valueGetters)
+ and function pointer which points to a static constructor for the
+ individual new function objects.
+
+ SunSpider claims this is a 1.0% speedup.
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayPrototype::getOwnPropertySlot):
+ (KJS::getProperty):
+ (KJS::ArrayProtoFuncToString::callAsFunction):
+ (KJS::ArrayProtoFuncToLocaleString::callAsFunction):
+ (KJS::ArrayProtoFuncJoin::callAsFunction):
+ (KJS::ArrayProtoFuncConcat::callAsFunction):
+ (KJS::ArrayProtoFuncPop::callAsFunction):
+ (KJS::ArrayProtoFuncPush::callAsFunction):
+ (KJS::ArrayProtoFuncReverse::callAsFunction):
+ (KJS::ArrayProtoFuncShift::callAsFunction):
+ (KJS::ArrayProtoFuncSlice::callAsFunction):
+ (KJS::ArrayProtoFuncSort::callAsFunction):
+ (KJS::ArrayProtoFuncSplice::callAsFunction):
+ (KJS::ArrayProtoFuncUnShift::callAsFunction):
+ (KJS::ArrayProtoFuncFilter::callAsFunction):
+ (KJS::ArrayProtoFuncMap::callAsFunction):
+ (KJS::ArrayProtoFuncEvery::callAsFunction):
+ (KJS::ArrayProtoFuncForEach::callAsFunction):
+ (KJS::ArrayProtoFuncSome::callAsFunction):
+ (KJS::ArrayProtoFuncIndexOf::callAsFunction):
+ (KJS::ArrayProtoFuncLastIndexOf::callAsFunction):
+ * kjs/array_object.h:
+ (KJS::ArrayPrototype::classInfo):
+ * kjs/create_hash_table:
+ * kjs/date_object.cpp:
+ (KJS::DatePrototype::getOwnPropertySlot):
+ (KJS::DateProtoFuncToString::callAsFunction):
+ (KJS::DateProtoFuncToUTCString::callAsFunction):
+ (KJS::DateProtoFuncToDateString::callAsFunction):
+ (KJS::DateProtoFuncToTimeString::callAsFunction):
+ (KJS::DateProtoFuncToLocaleString::callAsFunction):
+ (KJS::DateProtoFuncToLocaleDateString::callAsFunction):
+ (KJS::DateProtoFuncToLocaleTimeString::callAsFunction):
+ (KJS::DateProtoFuncValueOf::callAsFunction):
+ (KJS::DateProtoFuncGetTime::callAsFunction):
+ (KJS::DateProtoFuncGetFullYear::callAsFunction):
+ (KJS::DateProtoFuncGetUTCFullYear::callAsFunction):
+ (KJS::DateProtoFuncToGMTString::callAsFunction):
+ (KJS::DateProtoFuncGetMonth::callAsFunction):
+ (KJS::DateProtoFuncGetUTCMonth::callAsFunction):
+ (KJS::DateProtoFuncGetDate::callAsFunction):
+ (KJS::DateProtoFuncGetUTCDate::callAsFunction):
+ (KJS::DateProtoFuncGetDay::callAsFunction):
+ (KJS::DateProtoFuncGetUTCDay::callAsFunction):
+ (KJS::DateProtoFuncGetHours::callAsFunction):
+ (KJS::DateProtoFuncGetUTCHours::callAsFunction):
+ (KJS::DateProtoFuncGetMinutes::callAsFunction):
+ (KJS::DateProtoFuncGetUTCMinutes::callAsFunction):
+ (KJS::DateProtoFuncGetSeconds::callAsFunction):
+ (KJS::DateProtoFuncGetUTCSeconds::callAsFunction):
+ (KJS::DateProtoFuncGetMilliSeconds::callAsFunction):
+ (KJS::DateProtoFuncGetUTCMilliseconds::callAsFunction):
+ (KJS::DateProtoFuncGetTimezoneOffset::callAsFunction):
+ (KJS::DateProtoFuncSetTime::callAsFunction):
+ (KJS::DateProtoFuncSetMilliSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMilliseconds::callAsFunction):
+ (KJS::DateProtoFuncSetSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetUTCSeconds::callAsFunction):
+ (KJS::DateProtoFuncSetMinutes::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMinutes::callAsFunction):
+ (KJS::DateProtoFuncSetHours::callAsFunction):
+ (KJS::DateProtoFuncSetUTCHours::callAsFunction):
+ (KJS::DateProtoFuncSetDate::callAsFunction):
+ (KJS::DateProtoFuncSetUTCDate::callAsFunction):
+ (KJS::DateProtoFuncSetMonth::callAsFunction):
+ (KJS::DateProtoFuncSetUTCMonth::callAsFunction):
+ (KJS::DateProtoFuncSetFullYear::callAsFunction):
+ (KJS::DateProtoFuncSetUTCFullYear::callAsFunction):
+ (KJS::DateProtoFuncSetYear::callAsFunction):
+ (KJS::DateProtoFuncGetYear::callAsFunction):
+ * kjs/date_object.h:
+ * kjs/lookup.cpp:
+ (KJS::Lookup::find):
+ * kjs/lookup.h:
+ (KJS::HashEntry::):
+ (KJS::staticFunctionGetter):
+ (KJS::staticValueGetter):
+ (KJS::getStaticPropertySlot):
+ (KJS::getStaticFunctionSlot):
+ (KJS::lookupPut):
+ * kjs/math_object.cpp:
+ (KJS::MathObjectImp::getOwnPropertySlot):
+ (KJS::MathProtoFuncAbs::callAsFunction):
+ (KJS::MathProtoFuncACos::callAsFunction):
+ (KJS::MathProtoFuncASin::callAsFunction):
+ (KJS::MathProtoFuncATan::callAsFunction):
+ (KJS::MathProtoFuncATan2::callAsFunction):
+ (KJS::MathProtoFuncCeil::callAsFunction):
+ (KJS::MathProtoFuncCos::callAsFunction):
+ (KJS::MathProtoFuncExp::callAsFunction):
+ (KJS::MathProtoFuncFloor::callAsFunction):
+ (KJS::MathProtoFuncLog::callAsFunction):
+ (KJS::MathProtoFuncMax::callAsFunction):
+ (KJS::MathProtoFuncMin::callAsFunction):
+ (KJS::MathProtoFuncPow::callAsFunction):
+ (KJS::MathProtoFuncRandom::callAsFunction):
+ (KJS::MathProtoFuncRound::callAsFunction):
+ (KJS::MathProtoFuncSin::callAsFunction):
+ (KJS::MathProtoFuncSqrt::callAsFunction):
+ (KJS::MathProtoFuncTan::callAsFunction):
+ * kjs/math_object.h:
+ (KJS::MathObjectImp::classInfo):
+ (KJS::MathObjectImp::):
+ * kjs/string_object.cpp:
+ (KJS::StringPrototype::getOwnPropertySlot):
+ (KJS::StringProtoFuncToString::callAsFunction):
+ (KJS::StringProtoFuncValueOf::callAsFunction):
+ (KJS::StringProtoFuncCharAt::callAsFunction):
+ (KJS::StringProtoFuncCharCodeAt::callAsFunction):
+ (KJS::StringProtoFuncConcat::callAsFunction):
+ (KJS::StringProtoFuncIndexOf::callAsFunction):
+ (KJS::StringProtoFuncLastIndexOf::callAsFunction):
+ (KJS::StringProtoFuncMatch::callAsFunction):
+ (KJS::StringProtoFuncSearch::callAsFunction):
+ (KJS::StringProtoFuncReplace::callAsFunction):
+ (KJS::StringProtoFuncSlice::callAsFunction):
+ (KJS::StringProtoFuncSplit::callAsFunction):
+ (KJS::StringProtoFuncSubstr::callAsFunction):
+ (KJS::StringProtoFuncSubstring::callAsFunction):
+ (KJS::StringProtoFuncToLowerCase::callAsFunction):
+ (KJS::StringProtoFuncToUpperCase::callAsFunction):
+ (KJS::StringProtoFuncToLocaleLowerCase::callAsFunction):
+ (KJS::StringProtoFuncToLocaleUpperCase::callAsFunction):
+ (KJS::StringProtoFuncLocaleCompare::callAsFunction):
+ (KJS::StringProtoFuncBig::callAsFunction):
+ (KJS::StringProtoFuncSmall::callAsFunction):
+ (KJS::StringProtoFuncBlink::callAsFunction):
+ (KJS::StringProtoFuncBold::callAsFunction):
+ (KJS::StringProtoFuncFixed::callAsFunction):
+ (KJS::StringProtoFuncItalics::callAsFunction):
+ (KJS::StringProtoFuncStrike::callAsFunction):
+ (KJS::StringProtoFuncSub::callAsFunction):
+ (KJS::StringProtoFuncSup::callAsFunction):
+ (KJS::StringProtoFuncFontcolor::callAsFunction):
+ (KJS::StringProtoFuncFontsize::callAsFunction):
+ (KJS::StringProtoFuncAnchor::callAsFunction):
+ (KJS::StringProtoFuncLink::callAsFunction):
+ * kjs/string_object.h:
+
+2007-11-08 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ Reviewed by Sam and Ada.
+
+ * wtf/MathExtras.h: Get rid of a circular #include dependency to fix
+ the build.
+
+2007-11-08 Adam Roben <aroben@apple.com>
+
+ Fix a precedence warning on Windows
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::toBoolean):
+
+2007-11-08 Mark Rowe <mrowe@apple.com>
+
+ Build fix for JavaScriptGlue.
+
+ * wtf/MathExtras.h: Include stdlib.h for srand and RAND_MAX.
+
+2007-11-08 Darin Adler <darin@apple.com>
+
+ - Windows build fix
+
+ * kjs/JSImmediate.h: Include MathExtras.h rather than math.h since this file uses "signbit".
+
+2007-11-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Replace the use of floats for immediate values with the use of integers for a 4.5% improvement in SunSpider.
+
+ Unfortunately this change results in NaN, +Inf, -Inf, and -0 being heap allocated now, but
+ we should now have faster array access, faster immediate to double conversion, and the
+ potential to further improve bitwise operators in future.
+
+ This also removes the need for unions to avoid strict aliasing problems when extracting
+ a value from immediates.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::trueImmediate):
+ (KJS::JSImmediate::falseImmediate):
+ (KJS::JSImmediate::undefinedImmediate):
+ (KJS::JSImmediate::nullImmediate):
+ (KJS::JSImmediate::toBoolean):
+ * kjs/value.h:
+ (KJS::jsNaN):
+
+2007-11-07 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Darin and Oliver.
+
+ Add evaluateToNumber parallel evaluation tree to speed up number operations.
+ Make ImmediateNumberNode a subclass of NumberNode.
+ Share evaluate logic between evaluate and evaluateToNumber using inline functions
+ There is still a lot of improvement to be made here.
+
+ SunSpider claims this is a 1.0% speedup overall (nbody 7.9%), base64 slowing 2.0%
+ Given the huge win that this prepares us for with simple type inferencing I see the small
+ regression in base64 being worth the substantial overall improvement.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::Node::evaluateToNumber):
+ (KJS::NumberNode::evaluate):
+ (KJS::NumberNode::evaluateToNumber):
+ (KJS::StringNode::evaluateToNumber):
+ (KJS::LocalVarAccessNode::inlineEvaluate):
+ (KJS::LocalVarAccessNode::evaluate):
+ (KJS::LocalVarAccessNode::evaluateToNumber):
+ (KJS::BracketAccessorNode::inlineEvaluate):
+ (KJS::BracketAccessorNode::evaluate):
+ (KJS::BracketAccessorNode::evaluateToNumber):
+ (KJS::NegateNode::evaluate):
+ (KJS::NegateNode::evaluateToNumber):
+ (KJS::MultNode::inlineEvaluateToNumber):
+ (KJS::MultNode::evaluate):
+ (KJS::MultNode::evaluateToNumber):
+ (KJS::DivNode::inlineEvaluateToNumber):
+ (KJS::DivNode::evaluate):
+ (KJS::DivNode::evaluateToNumber):
+ (KJS::ModNode::inlineEvaluateToNumber):
+ (KJS::ModNode::evaluate):
+ (KJS::ModNode::evaluateToNumber):
+ (KJS::throwOutOfMemoryErrorToNumber):
+ (KJS::addSlowCaseToNumber):
+ (KJS::add):
+ (KJS::addToNumber):
+ (KJS::AddNode::evaluateToNumber):
+ (KJS::SubNode::inlineEvaluateToNumber):
+ (KJS::SubNode::evaluate):
+ (KJS::SubNode::evaluateToNumber):
+ (KJS::valueForReadModifyAssignment):
+ (KJS::ReadModifyLocalVarNode::evaluate):
+ (KJS::ReadModifyResolveNode::evaluate):
+ (KJS::ReadModifyDotNode::evaluate):
+ (KJS::ReadModifyBracketNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::Node::):
+ (KJS::NumberNode::):
+ (KJS::ImmediateNumberNode::):
+ (KJS::AddNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::NumberNode::streamTo):
+
+2007-11-07 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Eric.
+
+ Fix up initialization after being mangled in r27572, and remove the
+ ternary expression as extraCost will always be zero for the numeric
+ heap.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+
+2007-11-07 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/regexp_object.cpp:
+
+2007-11-07 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Beth Dakin.
+
+ Eliminated a bogus (though compiled-out) branch in the collector.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+
+2007-11-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed part of http://bugs.webkit.org/show_bug.cgi?id=15861
+ 5.8% of string-validate-input.js is spent creating RegExpImps
+
+ Put RegExpImp properties into a static hashtable to avoid a slew of
+ PropertyMap churn when creating a RegExpImp.
+
+ Factored important bits of regular expression implementation out of
+ RegExpImp (the JS object) and into RegExp (the PCRE wrapper class),
+ making RegExp a ref-counted class. (This will help later.)
+
+ Removed PCRE_POSIX support because I didn't quite know how to test it
+ and keep it working with these changes.
+
+ 1.1% SunSpider speedup. 5.8% speedup on string-validate-input.js.
+
+ * kjs/regexp.h: A few interface changes:
+ 1. Renamed "subpatterns()" => "numSubpatterns()"
+ 2. Made flag enumeration private and replaced it with public getters for
+ specific flags.
+ 3. Made RegExp ref-counted so RegExps can be shared by RegExpImps.
+ 4. Made RegExp take a string of flags instead of an int, eliminating
+ duplicated flag parsing code elsewhere.
+
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpProtoFunc::callAsFunction): For RegExp.compile:
+ - Fixed a bug where compile(undefined) would throw an exception.
+ - Removed some now-redundant code.
+ - Used RegExp sharing to eliminate an allocation and a bunch of
+ PropertyMap thrash. (Not a big win since compile is a deprecated
+ function. I mainly did this to test the plubming.)
+
+2007-11-07 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by nobody, Qt/Windows build fix.
+
+ JavaScriptCore.pri expects OBJECTS_DIR to be set, so set it in
+ testkjs.pro, too, where it's included from.
+
+ * kjs/testkjs.pro:
+
+2007-11-07 Simon Hausmann <shausman@trolltech.com>
+
+ Reviewed by Lars.
+
+ Fix "nmake clean" for the Qt/Windows build by replacing tmp/ with a variable that ends with the correct type of slash/backslash depending on the choice of compiler/make tool.
+
+ * JavaScriptCore.pri:
+ * pcre/pcre.pri:
+
+2007-11-07 Lars Knoll <lars@trolltech.com>
+
+ Reviewed by Simon.
+
+ fix umemcasecmp
+
+ Pretty embarrassing bug. Has the potential to fix quite a few test failures.
+
+ * wtf/unicode/qt4/UnicodeQt4.h:
+ (WTF::Unicode::umemcasecmp):
+
+2007-11-06 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Eric.
+
+ - only collect when the heap is full, unless we have lots of extra cost garbage
+
+ 1.1% SunSpider speedup.
+
+ This shouldn't hit memory use much since the extra space in those
+ blocks hangs around either way.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+ (KJS::Collector::collect): Fix logic error that reversed the sense of collect's
+ return value.
+
+2007-11-06 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Avoid unnecessarily boxing the result from post inc/decrement for 0.3% gain in sunspider
+
+ We now convert the common 'for (...; ...; <var>++) ...' to the semantically identical
+ 'for (...; ...; ++<var>) ...'.
+
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::optimizeForUnnecessaryResult):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostIncLocalVarNode::optimizeForUnnecessaryResult):
+ (KJS::PostDecResolveNode::optimizeForUnnecessaryResult):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostDecLocalVarNode::optimizeForUnnecessaryResult):
+ * kjs/nodes.h:
+ (KJS::PrePostResolveNode::):
+ (KJS::PostIncResolveNode::):
+ (KJS::PostIncLocalVarNode::):
+ (KJS::PostDecResolveNode::):
+ (KJS::PostDecLocalVarNode::):
+ (KJS::PreIncResolveNode::):
+ (KJS::PreDecResolveNode::):
+ (KJS::ForNode::ForNode):
+
+2007-11-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ This fixes a regressed layout test for string + object
+
+ SunSpider claims this was an overall 0.3% speedup, although some individual tests were slower.
+
+ * kjs/nodes.cpp:
+ (KJS::add): remove erroneous "fast path" for string + *
+
+2007-11-06 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Added toJSNumber, a fast path for converting a JSValue to a JS number,
+ and deployed it in postfix expressions. In the fast case this
+ eliminates a call to jsNumber.
+
+ 0.4% speedup on SunSpider.
+
+ * ChangeLog:
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::UnaryPlusNode::evaluate):
+ * kjs/value.h:
+ (KJS::JSValue::toJSNumber):
+
+2007-11-06 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15846
+ REGRESSION (r27387): Memory corruption when running fast/js/kde/delete.html
+
+ There was a mistake in the algorithm used to find an empty slot in the property
+ map entries vector; when we were putting in a new property value and not overwriting
+ an existing deleted sentinel, we would enlarge the entries vector, but would not
+ overwrite the stale data that's in the new part. It was easy to pin this down by
+ turning on property map consistency checks -- I never would have landed with this
+ bug if I had run the regression tests once with consistency checks on!
+
+ * kjs/property_map.cpp: (KJS::PropertyMap::put): Changed logic for the case where
+ foundDeletedElement is false to always use the item at the end of the entries vector.
+ Also allowed me to merge with the logic for the "no deleted sentinels at all" case.
+
+2007-11-06 Oliver Hunt <oliver@apple.com>
+
+ RS=Darin.
+
+ Fix previous patch to use a 3 bit shift, a 16 bit shift causes a regression in sunspider.
+
+ * kjs/nodes.cpp:
+ (KJS::add):
+
+2007-11-06 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Replace boolean comparisons in AddNode with mask
+ comparisons for a 0.2% improvement in sunspider.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/nodes.cpp:
+ (KJS::add):
+
+2007-11-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ SunSpider claims this is a 1.1% speedup.
+
+ * kjs/nodes.cpp:
+ (KJS::throwOutOfMemoryError): Added, non inline.
+ (KJS::addSlowCase): renamed from add(), non inline.
+ (KJS::add): add fast path for String + String, Number + Number and String + *
+
+2007-11-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by mjs.
+
+ Avoid more UString creation.
+
+ SunSpider claims this is a 0.4% speedup.
+
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpObjectImp::construct): use UString::find(UChar)
+
+2007-11-05 Mark Rowe <mrowe@apple.com>
+
+ Mac build fix.
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFunc::callAsFunction):
+
+2007-11-05 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * kjs/list.h:
+
+2007-11-05 Mark Rowe <mrowe@apple.com>
+
+ Build fix. Add missing #include.
+
+ * kjs/operations.cpp:
+
+2007-11-05 Eric Seidel <eric@webkit.org>
+
+ Reviewed by mjs.
+
+ Remove another call to toString(exec)
+
+ SunSpider claims this is a 0.5% speedup.
+
+ * kjs/operations.cpp:
+ (KJS::equal): remove another toString
+
+2007-11-05 Eric Seidel <eric@webkit.org>
+
+ * kjs/operations.cpp:
+ (KJS::equal): correct broken change.
+
+2007-11-05 Eric Seidel <eric@webkit.org>
+
+ Reviewed by mjs.
+
+ Remove one more call to toString(exec).
+
+ SunSpider claims this is a 0.7% speedup.
+
+ * kjs/operations.cpp:
+ (KJS::equal): remove a call to toString()
+
+2007-11-05 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * pcre/pcre.pri:
+
+2007-11-05 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/list.cpp:
+
+2007-11-05 Geoffrey Garen <ggaren@apple.com>
+
+ Touched a file to test my new HTTP access.
+
+ * kjs/scope_chain.cpp:
+
+2007-11-05 Alp Toker <alp@atoker.com>
+
+ Unreviewed build fix for qmake-based ports.
+
+ Someone with a better understanding of qmake still needs to sort out
+ the INCLUDEPATH/DEPENDPATH mess.
+
+ * JavaScriptCore.pri:
+
+2007-11-05 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15835
+
+ Switched List implementation from a custom heap allocator to an inline
+ Vector, for a disappointing .5% SunSpider speedup.
+
+ Also renamed List::slice to List::getSlice because "get" is the
+ conventional prefix for functions returning a value through an out
+ parameter.
+
+ * kjs/array_object.cpp:
+ (KJS::ArrayProtoFunc::callAsFunction): Removed some redundant function
+ calls and memory accesses.
+
+ * kjs/bool_object.cpp:
+ (BooleanObjectImp::construct): Removed questionable use of iterator.
+
+ * kjs/list.cpp:
+ * kjs/list.h: New List class, implemented in terms of Vector. Two
+ interesting differences:
+ 1. The inline capacity is 8, not 5. Many of the Lists constructed
+ during a SunSpider run are larger than 5; almost none are larger
+ than 8.
+
+ 2. The growth factor is 4, not 2. Since we can guarantee that Lists
+ aren't long-lived, we can grow them more aggressively, to avoid
+ excessive copying.
+
+ * kjs/regexp_object.cpp:
+ (RegExpObjectImp::construct): Removed redundant function calls.
+
+ * kjs/string_object.cpp:
+ (KJS::StringObjectImp::construct): Removed questionable use of iterator.
+
+ * wtf/Vector.h:
+ (WTF::::uncheckedAppend): Added a fast, unchecked version of append.
+
+2007-11-05 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Alp Toker.
+
+ Add DEPENDPATH to JavaScriptCore and pcre to help qmake with dependencies.
+
+ * JavaScriptCore.pri:
+ * pcre/pcre.pri:
+
+2007-11-04 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15826
+ optimize opcode loop and case insensitive ASCII compares for a 30% speedup
+
+ SunSpider says it's 2.6% faster overall, 32.5% in the regular expression tests.
+
+ * pcre/pcre_internal.h: Added OP_ASCII_CHAR and OP_ASCII_LETTER_NC.
+
+ * pcre/pcre_compile.c:
+ (find_fixedlength): Added cases for OP_ASCII_CHAR and OP_ASCII_LETTER_NC. Also
+ added OP_NOT since there was no reason it should not be in here.
+ (could_be_empty_branch): Ditto.
+ (compile_branch): Streamlined all the single-character cases; there was a bit of
+ duplicate code. Added cases for OP_ASCII_CHAR and OP_ASCII_LETTER_NC as needed.
+ But in particular, compile to those opcodes when the single character match is
+ ASCII.
+ (find_firstassertedchar): Added cases for OP_ASCII_CHAR and OP_ASCII_LETTER_NC.
+
+ * pcre/pcre_exec.c: (match): Removed the "min", "minimize", and "op" fields from
+ the matchframe, after I discovered that none of them needed to be saved and restored
+ across recursive match calls. Also eliminated the ignored result field from the
+ matchframe, since I discovered that rrc ("recursive result code") was already the
+ exact same thing. Moved the handling of opcodes higher than OP_BRA into the default
+ statement of the switch instead of doing them before the switch. This removes a
+ branch from each iteration of the opcode interpreter, just as removal of "op"
+ removed at least one store from each iteration. Last, but not least, add the
+ OP_ASCII_CHAR and OP_ASCII_LETTER_NC functions. Neither can ever match a
+ surrogate pair and the letter case can be handled efficiently.
+
+2007-11-04 Darin Adler <darin@apple.com>
+
+ * pcre/pcre_exec.c: (match): Try to fix the Windows build by removing unreachable code.
+
+2007-11-03 Darin Adler <darin@apple.com>
+
+ - fix non-Mac builds; remove some more unused PCRE stuff
+
+ * pcre/pcre_compile.c:
+ (compile_branch): Removed branch chain and some unused ESC values.
+ (compile_regex): Ditto.
+ (jsRegExpCompile): Ditto.
+ * pcre/pcre_exec.c:
+ (match): Removed unused branch targets. Don't use macros any more.
+ (jsRegExpExecute): More of the same.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Update for removed files.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Ditto.
+ * pcre/pcre.pri: Ditto.
+
+ * pcre/MERGING: Removed.
+ * pcre/pcre_fullinfo.c: Removed.
+ * pcre/pcre_get.c: Removed.
+ * pcre/pcre_internal.h:
+ * pcre/ucp.h: Removed.
+
+2007-11-03 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15821
+ remove unused PCRE features for speed
+
+ A first step toward removing the PCRE features we don't use.
+ This gives a 0.8% speedup on SunSpider, and a 6.5% speedup on
+ the SunSpider regular expression test.
+
+ Replaced the public interface with one that doesn't use the
+ name PCRE. Removed code we don't need for JavaScript and various
+ configurations we don't use. This is in preparation for still
+ more changes in the future. We'll probably switch to C++ and
+ make some even more significant changes to the regexp engine
+ to get some additional speed.
+
+ There's probably additional unused stuff that I haven't
+ deleted yet.
+
+ This does mean that our PCRE is now a fork, but I think that's
+ not really a big deal.
+
+ * JavaScriptCore.exp: Remove the 5 old entry points and add
+ the 3 new entry points for WebCore's direct use of the regular
+ expression engine.
+
+ * kjs/config.h: Remove the USE(PCRE16) define. I decided to flip
+ its sense and now there's a USE(POSIX_REGEX) instead, which should
+ probably not be set by anyone. Maybe later we'll just get rid of it
+ altogether.
+
+ * kjs/regexp.h:
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp): Switch to new jsRegExp function names and
+ defines. Cut down on the number of functions used.
+ (KJS::RegExp::~RegExp): Ditto.
+ (KJS::RegExp::match): Ditto.
+
+ * pcre/dftables.c: (main): Get rid of ctype_letter and ctype_meta,
+ which are unused.
+
+ * pcre/pcre-config.h: Get rid of EBCIDIC, PCRE_DATA_SCOPE, const,
+ size_t, HAVE_STRERROR, HAVE_MEMMOVE, HAVE_BCOPY, NEWLINE,
+ POSIX_MALLOC_THRESHOLD, NO_RECURSE, SUPPORT_UCP, SUPPORT_UTF8,
+ and JAVASCRIPT. These are all no longer configurable in our copy
+ of the library.
+
+ * pcre/pcre.h: Remove the macro-based kjs prefix hack, the PCRE
+ version macros, PCRE_UTF16, the code to set up PCRE_DATA_SCOPE,
+ the include of <stdlib.h>, and most of the constants and
+ functions defined in this header. Changed the naming scheme to
+ use a JSRegExp prefix rather than a pcre prefix. In the future,
+ we'll probably change this to be a C++ header.
+
+ * pcre/pcre_compile.c: Removed all unused code branches,
+ including many whole functions and various byte codes.
+ Kept changes outside of removal to a minimum.
+ (check_escape):
+ (first_significant_code):
+ (find_fixedlength):
+ (find_recurse):
+ (could_be_empty_branch):
+ (compile_branch):
+ (compile_regex):
+ (is_anchored):
+ (is_startline):
+ (find_firstassertedchar):
+ (jsRegExpCompile): Renamed from pcre_compile2 and changed the
+ parameters around a bit.
+ (jsRegExpFree): Added.
+
+ * pcre/pcre_exec.c: Removed many unused opcodes and variables.
+ Also started tearing down the NO_RECURSE mechanism since it's
+ now the default. In some cases there were things in the explicit
+ frame that could be turned into plain old local variables and
+ other small like optimizations.
+ (pchars):
+ (match_ref):
+ (match): Changed parameters quite a bit since it's now not used
+ recursively.
+ (jsRegExpExecute): Renamed from pcre_exec.
+
+ * pcre/pcre_internal.h: Get rid of PCRE_DEFINITION, PCRE_SPTR,
+ PCRE_IMS, PCRE_ICHANGED, PCRE_NOPARTIAL, PCRE_STUDY_MAPPED,
+ PUBLIC_OPTIONS, PUBLIC_EXEC_OPTIONS, PUBLIC_DFA_EXEC_OPTIONS,
+ PUBLIC_STUDY_OPTIONS, MAGIC_NUMBER, 16 of the opcodes,
+ _pcre_utt, _pcre_utt_size, _pcre_try_flipped, _pcre_ucp_findprop,
+ and _pcre_valid_utf8. Also moved pcre_malloc and pcre_free here.
+
+ * pcre/pcre_maketables.c: Changed to only compile in dftables.
+ Also got rid of many of the tables that we don't use.
+
+ * pcre/pcre_tables.c: Removed the unused Unicode property tables.
+
+ * pcre/pcre_ucp_searchfuncs.c: Removed everything except for
+ _pcre_ucp_othercase.
+
+ * pcre/pcre_xclass.c: (_pcre_xclass): Removed uneeded support
+ for classes based on Unicode properties.
+
+ * wtf/FastMallocPCRE.cpp: Removed unused bits. It would be good
+ to eliminate this completely, but we need the regular expression
+ code to be C++ first.
+
+ * pcre/pcre_fullinfo.c:
+ * pcre/pcre_get.c:
+ * pcre/ucp.h:
+ Files that are no longer needed. I didn't remove them with this
+ check-in, because I didn't want to modify all the project files.
+
+2007-11-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam.
+
+ - remove NaN check from JSImmediate::fromDouble for 0.5% SunSpider speedup
+
+ It turns out that doing this check costs more than it saves.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::fromDouble):
+
+2007-11-03 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Oliver.
+
+ Remove dummy variable from ClassInfo reducing the size of the struct by 1 word.
+ The variable had been kept around for binary compatibility, but since nothing
+ else is there is no point in continuing to keep it around.
+
+ * API/JSCallbackConstructor.cpp:
+ * API/JSCallbackFunction.cpp:
+ * API/JSCallbackObject.cpp:
+ * bindings/objc/objc_runtime.mm:
+ * bindings/runtime_array.cpp:
+ * bindings/runtime_object.cpp:
+ * kjs/array_instance.cpp:
+ * kjs/array_object.cpp:
+ * kjs/bool_object.cpp:
+ * kjs/date_object.cpp:
+ * kjs/error_object.cpp:
+ * kjs/function.cpp:
+ * kjs/internal.cpp:
+ * kjs/lookup.h:
+ * kjs/math_object.cpp:
+ * kjs/number_object.cpp:
+ * kjs/object.h:
+ * kjs/regexp_object.cpp:
+ * kjs/string_object.cpp:
+
+2007-11-03 Kevin McCullough <kmccullough@apple.com>
+
+ - Updated testkjs results to make the build bots green until we
+ can fix the tests that are failing. The new failures are in DST.
+
+ * tests/mozilla/expected.html:
+
+2007-11-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Adam.
+
+ - don't print the var twice for ForInNodes with a var declaration
+
+ * kjs/nodes2string.cpp:
+ (KJS::ForInNode::streamTo):
+
+2007-11-03 Darin Adler <darin@apple.com>
+
+ * pcre/pcre_compile.c: (check_escape): Windows build fix. Get rid of
+ C-incompatible declaration.
+
+2007-11-03 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/nodes.cpp: Add missing include.
+
+2007-11-03 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15814
+ <rdar://problem/5536644> fast/js/kde/encode_decode_uri.html fails
+
+ These changes cause us to match the JavaScript specification and pass the
+ fast/js/kde/encode_decode_uri.html test.
+
+ * kjs/function.cpp: (KJS::encode): Call the UTF-8 string conversion in its
+ new strict mode, throwing an exception if there are malformed UTF-16 surrogate
+ pairs in the text.
+
+ * kjs/ustring.h: Added a strict version of the UTF-8 string conversion.
+ * kjs/ustring.cpp:
+ (KJS::decodeUTF8Sequence): Removed code to disallow U+FFFE and U+FFFF; while
+ those might be illegal in some sense, they aren't supposed to get any special
+ handling in the place where this function is currently used.
+ (KJS::UString::UTF8String): Added the strictness.
+
+2007-11-03 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15812
+ some JavaScript tests (from the Mozilla test suite) are failing
+
+ Two or three fixes get 7 more of the Mozilla tests passing.
+ This gets us down from 61 failing tests to 54.
+
+ * kjs/interpreter.h: (KJS::Interpreter::builtinRegExp):
+ Made this inline and gave it a more specific type. Some day we should
+ probably do that for all of these -- might even get a bit of a speed
+ boost from it.
+ * kjs/interpreter.cpp: Removed Interpreter::builtinRegExp now that it's
+ inline in the header.
+
+ * kjs/regexp_object.h:
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpProtoFunc::callAsFunction): Moved test and exec out of the
+ switch statement into the RegExpImp object, so they can be shared with
+ RegExpImp::callAsFunction.
+ (KJS::RegExpImp::match): Added. Common code used by both test and exec.
+ (KJS::RegExpImp::test): Added.
+ (KJS::RegExpImp::exec): Added.
+ (KJS::RegExpImp::implementsCall): Added.
+ (KJS::RegExpImp::callAsFunction): Added.
+ (KJS::RegExpObjectImpPrivate::RegExpObjectImpPrivate): Initialize
+ lastInput to null rather than empty string -- we take advantage of the
+ difference in RegExpImp::match.
+ (KJS::RegExpObjectImp::input): Added. No reason to go through hash tables
+ just to get at a field like this.
+
+ * pcre/pcre_compile.c: (check_escape): Changed the \u handling to match
+ the JavaScript specification. If there are not 4 hex digits after the \u,
+ then it's processed as if it wasn't an escape sequence at all.
+
+ * pcre/pcre_internal.h: Added IS_NEWLINE, with the appropriate definition
+ for JavaScript (4 specific Unicode values).
+ * pcre/pcre_exec.c:
+ (match): Changed all call sites to use IS_NEWLINE.
+ (pcre_exec): Ditto.
+
+ * tests/mozilla/expected.html: Updated to expect 7 more successful tests.
+
+2007-11-03 David D. Kilzer <ddkilzer@webkit.org>
+
+ Sort files(...); sections of Xcode project files.
+
+ Rubber-stamped by Darin.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-11-03 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - remove VarDeclListNode and simplify VarDeclNode evaluation for 0.4% SunSpider speedup
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::VarDeclNode::optimizeVariableAccess):
+ (KJS::VarDeclNode::getDeclarations):
+ (KJS::VarDeclNode::handleSlowCase):
+ (KJS::VarDeclNode::evaluateSingle):
+ (KJS::VarDeclNode::evaluate):
+ (KJS::VarStatementNode::execute):
+ * kjs/nodes.h:
+ (KJS::VarDeclNode::):
+ (KJS::VarStatementNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::VarDeclNode::streamTo):
+
+2007-11-03 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15800
+ REGRESSION (r27303): RegExp leaks
+
+ * kjs/regexp_object.h:
+ (KJS::RegExpImp::setRegExp):
+ (KJS::RegExpImp::regExp):
+ (KJS::RegExpImp::classInfo):
+ * kjs/regexp_object.cpp:
+ (RegExpImp::RegExpImp):
+ (RegExpImp::~RegExpImp):
+ Renamed reg member variable to m_regExp, changed it to use OwnPtr.
+
+2007-11-02 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - add SourceElements as a typedef for Vector<RefPtr<StatementNode> >.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::statementListPushFIFO):
+ (KJS::statementListGetDeclarations):
+ (KJS::statementListInitializeDeclarationStacks):
+ (KJS::statementListInitializeVariableAccessStack):
+ (KJS::statementListExecute):
+ (KJS::BlockNode::BlockNode):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::ProgramNode::ProgramNode):
+ * kjs/nodes.h:
+ (KJS::CaseClauseNode::):
+
+2007-11-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15791
+ change property map data structure for less memory use, better speed
+
+ The property map now has an array of indices and a separate array of
+ property map entries. This slightly slows down lookup because of a second
+ memory acess, but makes property maps smaller and faster to iterate in
+ functions like mark().
+
+ SunSpider says this is 1.2% faster, although it makes the bitwise-end test
+ more than 10% slower. To fix that we'll need to optimize global variable lookup.
+
+ * kjs/property_map.cpp:
+ (KJS::PropertyMapEntry::PropertyMapEntry):
+ (KJS::PropertyMapHashTable::entries):
+ (KJS::PropertyMapHashTable::allocationSize):
+ (KJS::SavedProperties::SavedProperties):
+ (KJS::SavedProperties::~SavedProperties):
+ (KJS::PropertyMap::checkConsistency):
+ (KJS::PropertyMap::~PropertyMap):
+ (KJS::PropertyMap::clear):
+ (KJS::PropertyMap::get):
+ (KJS::PropertyMap::getLocation):
+ (KJS::PropertyMap::put):
+ (KJS::PropertyMap::insert):
+ (KJS::PropertyMap::createTable):
+ (KJS::PropertyMap::rehash):
+ (KJS::PropertyMap::remove):
+ (KJS::PropertyMap::mark):
+ (KJS::comparePropertyMapEntryIndices):
+ (KJS::PropertyMap::containsGettersOrSetters):
+ (KJS::PropertyMap::getEnumerablePropertyNames):
+ (KJS::PropertyMap::save):
+ (KJS::PropertyMap::restore):
+ * kjs/property_map.h:
+
+2007-11-02 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15807
+ HashMap needs a take() function that combines get and remove
+
+ * wtf/HashMap.h: Added take function. Simplistic implementation for now,
+ but still does only one hash table lookup.
+
+ * kjs/array_instance.cpp: (KJS::ArrayInstance::put): Use take rather than
+ a find followed by a remove.
+
+2007-11-02 David Carson <dacarson@gmail.com>
+
+ Reviewed by Darin.
+
+ Fix compiler warning "warning: suggest parentheses around && within ||"
+ http://bugs.webkit.org/show_bug.cgi?id=15764
+
+ * kjs/value.h: (KJS::JSValue::isNumber): Add parentheses.
+
+2007-11-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ In preparation for making List a simple stack-allocated Vector:
+
+ Removed all instances of List copying and/or assignment, and made List
+ inherit from Noncopyable.
+
+ Functions that used to return a List by copy now take List& out
+ parameters.
+
+ Layout tests and JS tests pass.
+
+ * kjs/list.cpp:
+ (KJS::List::slice): Replaced copyTail with a more generic slice
+ alternative. (JavaScriptCore only calls slice(1), but WebCore calls
+ slice(2)).
+
+2007-11-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15785
+ REGRESSION(r27344): Crash on load at finance.yahoo.com
+
+ Reverted a small portion of my last check-in. (The speedup and the List
+ removal are still there, though.)
+
+ ActivationImp needs to hold a pointer to its function, and mark that
+ pointer (rather than accessing its function through its ExecState, and
+ counting on the active scope to mark its function) because a closure
+ can cause an ActivationImp to outlive its ExecState along with any
+ active scope.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::~FunctionImp):
+ (KJS::ActivationImp::ActivationImp):
+ * kjs/function.h:
+ (KJS::ActivationImp::ActivationImpPrivate::ActivationImpPrivate):
+
+ Also made HashTable a little more crash-happy in debug builds, so
+ problems like this will show up earlier:
+
+ * wtf/HashTable.h:
+ (WTF::HashTable::~HashTable):
+
+2007-11-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Addressed some of Darin's review comments.
+
+ Used perl -p, which is the shorthand while(<>) {}.
+
+ Made sure not to suppress bison's output.
+
+ Added line to removed bison_out.txt, since this script removes other
+ intermediate files, too.
+
+ * DerivedSources.make:
+
+2007-11-01 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Removed List from ActivationImp, in preparation for making all lists
+ stack-allocated.
+
+ Tests pass.
+
+ 1.0% speedup on SunSpider, presumably due to reduced List refcount thrash.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ (KJS::ExecState::~ExecState):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::ActivationImp):
+ (KJS::ActivationImp::createArgumentsObject):
+ * kjs/function.h:
+ (KJS::ActivationImp::ActivationImpPrivate::ActivationImpPrivate):
+
+2007-11-01 Adam Roben <aroben@apple.com>
+
+ Use jsNumberCell instead of jsNumber when converting double constants to JSValues
+
+ This fixes fast/js/math.html, ecma/Date/15.9.5.10-1.js, and
+ ecma/Date/15.9.5.12-1.js, which were suffering from a bug in MSVC.
+
+ It also gets rid of an MSVC warning that we previously had to silence.
+
+ Reviewed by Geoff.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Turn
+ back on the "overflow in constant arithmetic" warning.
+ * kjs/number_object.cpp:
+ (NumberObjectImp::getValueProperty): Use jsNumberCell instead of
+ jsNumber.
+
+2007-10-31 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * kjs/ExecState.h:
+
+2007-10-31 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - shave some cycles off of local storage access for a 1% SunSpider speedup
+
+ Keep the LocalStorage pointer in the ExecState, instead of getting
+ it from the ActivationImp all the time.
+
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::updateLocalStorage):
+ * kjs/ExecState.h:
+ (KJS::ExecState::localStorage):
+ * kjs/nodes.cpp:
+ (KJS::LocalVarAccessNode::evaluate):
+ (KJS::LocalVarFunctionCallNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::LocalVarTypeOfNode::evaluate):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::ReadModifyLocalVarNode::evaluate):
+ (KJS::AssignLocalVarNode::evaluate):
+ (KJS::FunctionBodyNode::processDeclarationsForFunctionCode):
+
+2007-10-31 Adam Roben <aroben@apple.com>
+
+ Fix a crash on launch due to a static initializer race
+
+ We now use fast inline assembler spinlocks which can be statically
+ initialized at compile time.
+
+ As a side benefit, this speeds up SunSpider by 0.4%.
+
+ Reviewed by Oliver.
+
+ * wtf/FastMalloc.cpp:
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::Lock):
+ (TCMalloc_SpinLock::Unlock):
+ (TCMalloc_SlowLock):
+ * wtf/TCSystemAlloc.cpp:
+
+2007-10-31 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Sam.
+
+ - Corrected spelling.
+
+ * wtf/HashTraits.h:
+
+2007-10-31 Mark Rowe <mrowe@apple.com>
+
+ Further Gtk build fixage.
+
+ * kjs/regexp_object.cpp:
+
+2007-10-31 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/regexp.h:
+
+2007-10-31 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15749
+ RegExp/RegExpObjectImp cause needless UString creation
+
+ Speeds things up 0.4% according to SunSpider.
+
+ * kjs/config.h: Define USE(PCRE16) instead of HAVE(PCREPOSIX),
+ because this library doesn't use the real PCRE -- it uses its
+ own PCRE that works on UTF-16.
+
+ * kjs/regexp.h: Removed a few unused functions. Changed the ifdef.
+ Use Noncopyable. Change the return value of match.
+ * kjs/regexp.cpp:
+ (KJS::RegExp::RegExp): Call pcre_compile2, for a slight speed boost.
+ (KJS::RegExp::~RegExp): PCRE16 rather than PCREPOSIX.
+ (KJS::RegExp::match): Change to return the position as an int and the
+ ovector as a OwnArrayPtr<int> for efficiency and clearer storage management.
+
+ * kjs/regexp_object.h: Change performMatch and arrayOfMatches to no longer
+ require a result string.
+ * kjs/regexp_object.cpp:
+ (RegExpProtoFunc::callAsFunction): Update for new signature of performMatch.
+ (RegExpObjectImp::performMatch): Change so it doesn't return a string.
+ (RegExpObjectImp::arrayOfMatches): Simplify by unifying the handling of
+ the main result with the backreferences; now it doesn't need to take
+ a result parameter.
+ (RegExpObjectImp::getBackref): Minor tweaks.
+ (RegExpObjectImp::getLastParen): Ditto.
+ (RegExpObjectImp::getLeftContext): Ditto.
+ (RegExpObjectImp::getRightContext): Ditto.
+ (RegExpObjectImp::getValueProperty): Change LastMatch case to call
+ getBackref(0) so we don't need a separate getLastMatch function.
+
+ * kjs/string_object.cpp:
+ (KJS::replace): Update to use new performMatch, including merging the
+ matched string section with the other substrings.
+ (KJS::StringProtoFunc::callAsFunction): Update functions to use the
+ new performMatch and match. Also change to use OwnArrayPtr.
+
+2007-10-31 Oliver Hunt <oliver@apple.com>
+
+ * kjs/nodes.h: include OwnPtr.h
+
+2007-10-31 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Remove SourceCodeElement class and replaced with a Vector for a 0.8% gain on sunspider
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::statementListPushFIFO):
+ (KJS::statementListGetDeclarations):
+ (KJS::statementListInitializeDeclarationStacks):
+ (KJS::statementListInitializeVariableAccessStack):
+ (KJS::statementListExecute):
+ (KJS::BlockNode::optimizeVariableAccess):
+ (KJS::BlockNode::BlockNode):
+ (KJS::BlockNode::getDeclarations):
+ (KJS::BlockNode::execute):
+ (KJS::CaseClauseNode::optimizeVariableAccess):
+ (KJS::CaseClauseNode::getDeclarations):
+ (KJS::CaseClauseNode::evalStatements):
+ (KJS::FunctionBodyNode::initializeDeclarationStacks):
+ (KJS::FunctionBodyNode::optimizeVariableAccess):
+ * kjs/nodes.h:
+ * kjs/nodes2string.cpp:
+ (KJS::statementListStreamTo):
+ (KJS::BlockNode::streamTo):
+ (KJS::CaseClauseNode::streamTo):
+
+2007-10-30 Mark Rowe <mrowe@apple.com>
+
+ * kjs/property_map.cpp: Added a missing using directive to fix the build
+ for non-Mac ports. Mac worked only because it does the AllInOneFile compile.
+
+2007-10-31 Maciej Stachowiak <mjs@apple.com>
+
+ * kjs/property_map.cpp: Include HashTable.h the right way to fix the build
+ for non-Mac ports.
+
+2007-10-31 Alexey Proskuryakov <ap@webkit.org>
+
+ Reviewed by Darin.
+
+ http://bugs.webkit.org/show_bug.cgi?id=11001
+ WebKit doesn't support RegExp.compile method
+
+ Test: fast/js/regexp-compile.html
+
+ * kjs/regexp_object.cpp:
+ (RegExpPrototype::RegExpPrototype):
+ (RegExpProtoFunc::callAsFunction):
+ * kjs/regexp_object.h:
+ (KJS::RegExpProtoFunc::):
+ Added RegExp.compile.
+
+ * tests/mozilla/expected.html: js1_2/regexp/compile.js now passes.
+
+2007-10-31 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - get rid of integer divide in PropertyMap and HashTable for 1% SunSpider speedup
+
+ Integer divide sucks. Fortunately, a bunch of shifts and XORs
+ biased towards the high bits is sufficient to provide a good
+ double hash. Besides the SunSpider win, I used the dump statistics
+ mode for both to verify that collisions did not increase and that
+ the longest collision chain is not any longer.
+
+ * kjs/property_map.cpp:
+ (KJS::doubleHash):
+ (KJS::PropertyMap::get):
+ (KJS::PropertyMap::getLocation):
+ (KJS::PropertyMap::put):
+ (KJS::PropertyMap::insert):
+ (KJS::PropertyMap::remove):
+ (KJS::PropertyMap::checkConsistency):
+ * wtf/HashTable.h:
+ (WTF::doubleHash):
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+ (WTF::::add):
+
+2007-10-30 Adam Roben <aroben@apple.com>
+
+ * kjs/collector.h: Make HeapType public so it can be used for non-member
+ things like the HeapConstants struct template. Fixes the build on Windows.
+
+2007-10-30 Adam Roben <aroben@apple.com>
+
+ Change ALWAYS_INLINE and WTF_PRIVATE_INLINE to use __forceinline on Windows
+
+ Speeds up SunSpider by 0.4%.
+
+ Reviewed by Steve and Maciej.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Disable
+ a warning during LTCG in release builds about double -> float
+ conversion.
+ * wtf/AlwaysInline.h:
+ * wtf/FastMalloc.h:
+
+2007-10-30 Adam Roben <aroben@apple.com>
+
+ Use GetCurrentThreadId instead of pthread_self in FastMalloc
+
+ Speeds up SunSpider by 0.3%.
+
+ Reviewed by Steve.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_ThreadCache::InitTSD):
+ (WTF::TCMalloc_ThreadCache::CreateCacheIfNecessary):
+
+2007-10-30 Adam Roben <aroben@apple.com>
+
+ Switch to a Win32 critical section implementation of spinlocks
+
+ Speeds up SunSpider by 0.4%.
+
+ Reviewed by Steve.
+
+ * wtf/FastMalloc.cpp:
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::TCMalloc_SpinLock):
+ (TCMalloc_SpinLock::Init):
+ (TCMalloc_SpinLock::Finalize):
+ (TCMalloc_SpinLock::Lock):
+ (TCMalloc_SpinLock::Unlock):
+ * wtf/TCSystemAlloc.cpp:
+
+2007-10-30 Adam Roben <aroben@apple.com>
+
+ Fix Bug 15586: REGRESSION (r26759-r26785): Windows nightly builds crash with Safari 3 Public Beta
+
+ http://bugs.webkit.org/show_bug.cgi?id=15586
+
+ Also fixes: <rdar://5565303> Cannot use regsvr32.exe to register WebKit.dll
+
+ Use Win32 TLS functions instead of __declspec(thread), which breaks
+ delay-loading.
+
+ Reviewed by Steve.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::getThreadHeap):
+ (WTF::TCMalloc_ThreadCache::InitModule):
+
+2007-10-30 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - allocate numbers in half-size cells, for an 0.5% SunSpider speedup
+ http://bugs.webkit.org/show_bug.cgi?id=15772
+
+ We do this by using a single mark bit per two number cells, and
+ tweaking marking.
+
+ Besides being an 0.5% win overall, this is a 7.1% win on morph.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::heapAllocate):
+ (KJS::Collector::markStackObjectsConservatively):
+ (KJS::Collector::sweep):
+ * kjs/collector.h:
+ (KJS::SmallCollectorCell::):
+
+2007-10-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Adam Roben, Sam Weinig.
+
+ Made conflicts in grammar.y a persistent build failure.
+
+ * DerivedSources.make:
+
+2007-10-30 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam and Geoff.
+
+ - Added a new cast so all the casts are in the same place.
+
+ * API/APICast.h:
+ (toGlobalRef):
+
+2007-10-30 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed <rdar://problem/5567504> shift/reduce conflict introduced in r24457
+
+ JS tests, including
+
+ ecma_2/Statements/dowhile-001.js
+ ecma_2/Statements/dowhile-002.js
+ ecma_2/Statements/dowhile-003.js
+ ecma_2/Statements/dowhile-004.js
+ ecma_2/Statements/dowhile-005.js
+ ecma_2/Statements/dowhile-006.js
+ ecma_2/Statements/dowhile-007.js
+ js1_2/statements/do_while.js
+
+ and layout tests, including
+
+ do-while-expression-value.html
+ do-while-semicolon.html
+ do-while-without-semicolon.html
+
+ pass.
+
+ * kjs/grammar.y: Use the explicit "error" production, as we do with other
+ automatic semicolon insertions, to disambiguate "do { } while();" from
+ "do { } while()" followed by ";" (the empty statement).
+
+2007-10-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Debranching remaining assignment nodes, and miscellaneous cleanup
+
+ Split read-modify code paths out of AssignBracketNode and AssignDotNode
+ Removed now unnecessary check for write-only assignment in ReadModifyLocalVarNode
+ and ReadModifyResolveNode evaluate methods
+
+ Leads to a 1% gain in SunSpider.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::ReadModifyLocalVarNode::evaluate):
+ (KJS::ReadModifyResolveNode::evaluate):
+ (KJS::AssignDotNode::evaluate):
+ (KJS::ReadModifyDotNode::optimizeVariableAccess):
+ (KJS::ReadModifyDotNode::evaluate):
+ (KJS::AssignBracketNode::evaluate):
+ (KJS::ReadModifyBracketNode::optimizeVariableAccess):
+ (KJS::ReadModifyBracketNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::AssignBracketNode::):
+ (KJS::AssignBracketNode::precedence):
+ (KJS::AssignDotNode::):
+ (KJS::AssignDotNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::ReadModifyBracketNode::streamTo):
+ (KJS::AssignBracketNode::streamTo):
+ (KJS::ReadModifyDotNode::streamTo):
+ (KJS::AssignDotNode::streamTo):
+
+2007-10-29 Oliver Hunt <oliver@apple.com>
+
+ Debranching various Node::evaluate implementations
+
+ Reviewed by Maciej.
+
+ Split the read-modify-write assignment cases out of AssignResolveNode and into ReadModifyResolveNode
+ Split the increment and decrement cases for Prefix- and Postfix- ResolveNode, BracketNode, and DotNode
+
+ Gains 1.6% on SunSpider
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::PostIncResolveNode::optimizeVariableAccess):
+ (KJS::PostIncResolveNode::evaluate):
+ (KJS::PostIncLocalVarNode::evaluate):
+ (KJS::PostDecResolveNode::optimizeVariableAccess):
+ (KJS::PostDecResolveNode::evaluate):
+ (KJS::PostDecLocalVarNode::evaluate):
+ (KJS::PostIncBracketNode::evaluate):
+ (KJS::PostDecBracketNode::evaluate):
+ (KJS::PostIncDotNode::evaluate):
+ (KJS::PostDecDotNode::evaluate):
+ (KJS::PreIncResolveNode::optimizeVariableAccess):
+ (KJS::PreIncLocalVarNode::evaluate):
+ (KJS::PreIncResolveNode::evaluate):
+ (KJS::PreDecResolveNode::optimizeVariableAccess):
+ (KJS::PreDecLocalVarNode::evaluate):
+ (KJS::PreDecResolveNode::evaluate):
+ (KJS::PreIncBracketNode::evaluate):
+ (KJS::PreDecBracketNode::evaluate):
+ (KJS::PreIncDotNode::evaluate):
+ (KJS::PreDecDotNode::evaluate):
+ (KJS::ReadModifyResolveNode::optimizeVariableAccess):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::AssignLocalVarNode::evaluate):
+ (KJS::AssignResolveNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::PostDecResolveNode::):
+ (KJS::PostDecResolveNode::precedence):
+ (KJS::PostDecLocalVarNode::):
+ (KJS::PostfixBracketNode::):
+ (KJS::PostfixBracketNode::precedence):
+ (KJS::PostIncBracketNode::):
+ (KJS::PostIncBracketNode::isIncrement):
+ (KJS::PostDecBracketNode::):
+ (KJS::PostDecBracketNode::isIncrement):
+ (KJS::PostfixDotNode::):
+ (KJS::PostfixDotNode::precedence):
+ (KJS::PostIncDotNode::):
+ (KJS::PostIncDotNode::isIncrement):
+ (KJS::PostDecDotNode::):
+ (KJS::PreIncResolveNode::):
+ (KJS::PreDecResolveNode::):
+ (KJS::PreDecResolveNode::precedence):
+ (KJS::PreDecLocalVarNode::):
+ (KJS::PrefixBracketNode::):
+ (KJS::PrefixBracketNode::precedence):
+ (KJS::PreIncBracketNode::):
+ (KJS::PreIncBracketNode::isIncrement):
+ (KJS::PreDecBracketNode::):
+ (KJS::PreDecBracketNode::isIncrement):
+ (KJS::PrefixDotNode::):
+ (KJS::PrefixDotNode::precedence):
+ (KJS::PreIncDotNode::):
+ (KJS::PreIncDotNode::isIncrement):
+ (KJS::PreDecDotNode::):
+ (KJS::ReadModifyResolveNode::):
+ (KJS::ReadModifyLocalVarNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::AssignResolveNode::precedence):
+ * kjs/nodes2string.cpp:
+ (KJS::PostIncResolveNode::streamTo):
+ (KJS::PostDecResolveNode::streamTo):
+ (KJS::PostfixBracketNode::streamTo):
+ (KJS::PostfixDotNode::streamTo):
+ (KJS::PreIncResolveNode::streamTo):
+ (KJS::PreDecResolveNode::streamTo):
+ (KJS::ReadModifyResolveNode::streamTo):
+ (KJS::AssignResolveNode::streamTo):
+
+2007-10-29 Maciej Stachowiak <mjs@apple.com>
+
+ Not reviewed, build fix.
+
+ - Include Vector.h in a way that actually works.
+
+ * kjs/LocalStorage.h:
+
+2007-10-29 Maciej Stachowiak <mjs@apple.com>
+
+ Not reviewed, build fix.
+
+ - Install LocalStorage.h as a private header.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-10-29 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - Define good VectorTraits for LocalStorage entry for 0.5% speed improvement on SunSpider.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/LocalStorage.h: Added.
+ (KJS::LocalStorageEntry::LocalStorageEntry):
+ (WTF::):
+ * kjs/function.h:
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::processDeclarationsForFunctionCode):
+
+2007-10-29 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Some small tweaks that I notice while reviewing Oliver's last patch.
+
+ Includes removal of an unnecessary KJS_CHECKEXCEPTIONVALUE.
+
+ No change in SunSpider because SunSpider doesn't take the code path that
+ would execute the unnecessary KJS_CHECKEXCEPTIONVALUE much.
+
+ * kjs/nodes.cpp:
+ (KJS::LocalVarPostfixNode::evaluate):
+ (KJS::TypeOfResolveNode::optimizeVariableAccess):
+ (KJS::LocalVarTypeOfNode::evaluate):
+ (KJS::PrefixResolveNode::optimizeVariableAccess):
+ (KJS::LocalVarPrefixNode::evaluate):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::LocalVarAssignNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::LocalVarTypeOfNode::):
+ (KJS::PrefixResolveNode::):
+ (KJS::LocalVarPrefixNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::LocalVarAssignNode::):
+
+2007-10-29 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ SunSpider claims this was a 0.7% speedup.
+
+ * kjs/string_object.cpp:
+ (KJS::StringProtoFunc::callAsFunction): avoid mallocing a jsString in the common case
+
+2007-10-29 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Mark.
+
+ - re-enable asserts for access to empty or deleted keys
+
+ * wtf/HashTable.h:
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+ (WTF::::add):
+
+2007-10-29 Eric Seidel <eric@webkit.org>
+
+ Build fix only, no review.
+
+ * JavaScriptCore.exp: Export symbol for new StringInstance::getOwnPropertySlot
+
+2007-10-29 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix. Move struct declarations into nodes.h.
+
+ * kjs/grammar.y:
+ * kjs/nodes.h:
+
+2007-10-29 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Give StringInstance a getOwnPropertySlot(ExecState, unsigned, PropertySlot) fastpath, just like Arrays.
+ Make it a compile time error to use toString(ExecState) on a StringInstance
+
+ SunSpider claims this was a 6.6% speedup overall (22% on string-base64)
+
+ * kjs/internal.h:
+ (KJS::StringImp::getLength):
+ * kjs/string_object.cpp:
+ (KJS::StringInstance::lengthGetter):
+ (KJS::StringInstance::inlineGetOwnPropertySlot):
+ (KJS::StringInstance::getOwnPropertySlot):
+ * kjs/string_object.h:
+
+2007-10-28 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Add nodes to allow Assignment, TypeOf, and prefix operators to
+ make use of the new optimised local variable look up.
+
+ 5% gain on sunspider
+
+ * kjs/nodes.cpp:
+ (KJS::TypeOfResolveNode::optimizeVariableAccess):
+ (KJS::LocalTypeOfAccessNode::evaluate):
+ (KJS::PrefixResolveNode::optimizeVariableAccess):
+ (KJS::PrefixLocalAccessNode::evaluate):
+ (KJS::AssignResolveNode::optimizeVariableAccess):
+ (KJS::AssignLocalAccessNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::TypeOfResolveNode::):
+ (KJS::TypeOfResolveNode::precedence):
+ (KJS::LocalTypeOfAccessNode::):
+ (KJS::PrefixResolveNode::):
+ (KJS::PrefixResolveNode::precedence):
+ (KJS::PrefixLocalAccessNode::):
+ (KJS::AssignResolveNode::):
+ (KJS::AssignLocalAccessNode::):
+
+2007-10-28 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - avoid creating and then breaking circular lists in the parser, instead track head and tail pointers at parse time
+ http://bugs.webkit.org/show_bug.cgi?id=15748
+
+ Not a significant speedup or slowdown on SunSpider.
+
+ * kjs/Parser.cpp:
+ (KJS::clearNewNodes):
+ * kjs/Parser.h:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::BlockNode::BlockNode):
+ (KJS::CaseBlockNode::CaseBlockNode):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::SourceElementsNode::SourceElementsNode):
+ (KJS::ProgramNode::ProgramNode):
+ * kjs/nodes.h:
+ (KJS::ElementNode::):
+ (KJS::ArrayNode::):
+ (KJS::PropertyListNode::):
+ (KJS::ObjectLiteralNode::):
+ (KJS::ArgumentListNode::):
+ (KJS::ArgumentsNode::):
+ (KJS::VarDeclListNode::):
+ (KJS::VarStatementNode::):
+ (KJS::ForNode::):
+ (KJS::ParameterNode::):
+ (KJS::FuncExprNode::):
+ (KJS::FuncDeclNode::):
+ (KJS::SourceElementsNode::):
+ (KJS::CaseClauseNode::):
+ (KJS::ClauseListNode::):
+
+2007-10-28 Mark Rowe <mrowe@apple.com>
+
+ Disable assertions in a manner that doesn't break the Qt Windows build.
+
+ * wtf/HashTable.h:
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+
+2007-10-28 Geoffrey Garen <ggaren@apple.com>
+
+ Temporarily disabling some ASSERTs I introduced in my last check-in
+ because of http://bugs.webkit.org/show_bug.cgi?id=15747
+ Lots of layout tests fail the !HashTranslator::equal(KeyTraits::emptyValue() ASSERT
+
+ * wtf/HashTable.h:
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+ (WTF::::add):
+
+2007-10-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15746
+ #ifndef ASSERT_DISABLED is no good!
+
+ Replaced with #if !ASSERT_DISABLED.
+
+ * wtf/HashTable.h:
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+ (WTF::::add):
+
+2007-10-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Added FunctionCallResolveNode, PostfixResolveNode, and DeleteResolveNode
+ to the AST transfom that replaces slow resolve nodes with fast local
+ variable alternatives.
+
+ 2.5% speedup on SunSpider.
+
+ Also added some missing copyright notices.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionCallResolveNode::optimizeVariableAccess):
+ (KJS::FunctionCallResolveNode::evaluate):
+ (KJS::LocalVarFunctionCallNode::evaluate):
+ (KJS::PostfixResolveNode::optimizeVariableAccess):
+ (KJS::PostfixResolveNode::evaluate):
+ (KJS::LocalVarPostfixNode::evaluate):
+ (KJS::DeleteResolveNode::optimizeVariableAccess):
+ (KJS::DeleteResolveNode::evaluate):
+ (KJS::LocalVarDeleteNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::FunctionCallResolveNode::):
+ (KJS::LocalVarFunctionCallNode::LocalVarFunctionCallNode):
+ (KJS::PostfixResolveNode::):
+ (KJS::LocalVarPostfixNode::LocalVarPostfixNode):
+ (KJS::DeleteResolveNode::):
+ (KJS::LocalVarDeleteNode::LocalVarDeleteNode):
+
+2007-10-28 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Inline UString::Rep::deref() for a 0.8% improvement in SunSpider
+ Add virtual keyword to a few virtual functions previously unmarked.
+
+ * kjs/internal.h:
+ (KJS::StringImp::type):
+ (KJS::NumberImp::type):
+ * kjs/ustring.h:
+ (KJS::UString::Rep::deref):
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ - fix "broken everything" from the storage leak fix
+
+ * wtf/RefPtr.h: (WTF::RefPtr::RefPtr): Added a PlacementNewAdopt constructor.
+ * kjs/ustring.h: (KJS::UString::UString): Pass PlacementNewAdopt along to RefPtr.
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam.
+
+ - turn on unused parameter waring on Mac OS X because it's already on elsewhere
+
+ * Configurations/Base.xcconfig: Took out -wno-unused-parameter.
+
+ * API/JSNode.c:
+ * API/JSNodeList.c:
+ * API/minidom.c:
+ * API/testapi.c:
+ Fixed unused variables by using them or marked them with UNUSED_PARAM.
+
+ * kjs/CollectorHeapIntrospector.h: (KJS::CollectorHeapIntrospector::zoneCalloc):
+ Removed parameter names to indicate they are unused.
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix a storage leak where we ref the UString every time we replace
+ a ResolveNode with a LocalVarAccessNode
+
+ * kjs/identifier.h: (KJS::Identifier::Identifier): Added a constructor
+ that takes PlacementNewAdopt.
+
+ * kjs/nodes.h: (KJS::ResolveNode::ResolveNode): Initialize the ident
+ with PlacementNewAdopt instead of the old value of ident.
+
+ * kjs/ustring.h: (KJS::UString::UString): Added a constructor that
+ takes PlacementNewAdopt.
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ - Windows build fix; get rid of unused parameter
+
+ * kjs/nodes.cpp: (KJS::ResolveNode::optimizeVariableAccess): Don't pass it.
+ * kjs/nodes.h: (KJS::LocalVarAccessNode::LocalVarAccessNode): Remove it.
+ The assertions weren't all that helpful.
+
+2007-10-28 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix. Add include of MathExtras.h.
+
+ * kjs/string_object.cpp:
+
+2007-10-28 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej and Tim.
+
+ Replace uses of isNaN and isInf with isnan and isinf, and
+ remove isNaN and isInf.
+
+ * kjs/config.h: Remove unused HAVE_'s.
+ * kjs/date_object.cpp:
+ (KJS::DateInstance::getTime):
+ (KJS::DateInstance::getUTCTime):
+ (KJS::DateProtoFunc::callAsFunction):
+ (KJS::DateObjectImp::construct):
+ (KJS::DateObjectFuncImp::callAsFunction):
+ * kjs/function.cpp:
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/math_object.cpp:
+ (MathFuncImp::callAsFunction):
+ * kjs/nodes2string.cpp:
+ (KJS::isParserRoundTripNumber):
+ * kjs/number_object.cpp:
+ (NumberProtoFunc::callAsFunction):
+ * kjs/operations.cpp:
+ * kjs/operations.h:
+ * kjs/string_object.cpp:
+ (KJS::StringProtoFunc::callAsFunction):
+ * kjs/ustring.cpp:
+ (KJS::UString::from):
+ * kjs/value.cpp:
+ (KJS::JSValue::toInteger):
+ (KJS::JSValue::toInt32SlowCase):
+ (KJS::JSValue::toUInt32SlowCase):
+
+2007-10-28 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: use the new-fangled missingSymbolMarker().
+
+ * kjs/nodes.cpp:
+ (KJS::ResolveNode::optimizeVariableAccess):
+ * kjs/nodes.h:
+ (KJS::LocalVarAccessNode::LocalVarAccessNode):
+
+2007-10-28 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak, Darin Adler.
+
+ Much supporting work done by Maciej Stachowiak, Maks Orlovich, and
+ Cameron Zwarich.
+
+ AST transfom to replace slow resolve nodes with fast local variable
+ alternatives that do direct memory access. Currently, only ResolveNode
+ provides a fast local variable alternative. 6 others are soon to come.
+
+ 16.7% speedup on SunSpider.
+
+ Most of this patch is just scaffolding to support iterating all the
+ resolve nodes in the AST through optimizeResolveNodes(). In
+ optimizeResolveNodes(), most classes just push their child nodes onto
+ the processing stack, while ResolveNodes actually replace themselves in
+ the tree with more optimized alternatives, if possible.
+
+ Here are the interesting bits:
+
+ * kjs/nodes.h: Added PlacementNewAdoptTag, along with implementations
+ in Node and ResolveNode. This tag allows you to use placement new to
+ swap out a base class Node in favor of a subclass copy that holds the
+ same data. (Without this tag, default initialization would NULL out
+ RefPtrs, change line numbers, etc.)
+
+ * kjs/nodes.cpp:
+ (KJS::ResolveNode::evaluate): Since we're taking the slow path, ASSERT
+ that the fast path is impossible, to make sure we didn't leave anything
+ on the table.
+
+ (KJS::FunctionBodyNode::optimizeResolveNodes): Here's where the AST
+ transformation happens.
+
+ (KJS::ResolveNode::optimizeResolveNodes): Here's where the ResolveNode
+ optimization happens.
+
+ * kjs/function.h: Added symbolTable() accessor for, for the sake of
+ an ASSERT.
+
+2007-10-28 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Maciej.
+
+ Fix "AllInOneFile.o has a global initializer in it".
+
+ Some versions of gcc generate a global initializer for std::numeric_limits<size_t>::max().
+ We can avoid this by moving it inside an inline function.
+
+ * kjs/SymbolTable.h:
+ (KJS::missingSymbolMarker):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getOwnPropertySlot):
+ (KJS::ActivationImp::put):
+
+2007-10-28 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Mark.
+
+ - Added assertions to protect against adding empty or deleted keys to a HashTable
+
+ * wtf/HashTable.h:
+ (WTF::HashTable::lookup):
+ (WTF::HashTable::lookupForWriting):
+ (WTF::HashTable::fullLookupForWriting):
+ (WTF::HashTable::add):
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ - fix GTK build
+
+ * kjs/nodes2string.cpp: (KJS::isParserRoundTripNumber):
+ Use isNaN and isInf instead of isnan and isinf.
+
+2007-10-28 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15735
+ remove GroupNode to simplify AST and possibly get a modest speedup
+
+ This patch removes 4 node types: GroupNode, PropertyNameNode,
+ FunctionCallParenBracketNode, and FunctionCallParenDotNode.
+
+ To remove GroupNode, we add knowledge of precedence to the tree nodes,
+ and use that when serializing to determine where parentheses are needed.
+ This means we no longer have to represent parentheses in the tree.
+
+ The precedence values are named after productions in the grammar from the
+ JavaScript standard.
+
+ SunSpider says this is an 0.4% speedup.
+
+ * kjs/function.h:
+ * kjs/function.cpp: Removed escapeStringForPrettyPrinting -- it's part of
+ serialization, so I moved it to the file that takes care of that.
+
+ * kjs/grammar.y: Changed makeGetterOrSetterPropertyNode to use 0 to
+ indicate failure instead of a separate boolean. Got rid of PropertyNameNode
+ by merging the PropertyName rule into the Property rule (which was easier
+ than figuring out how to pass the Identifier from one node to another).
+ Got rid of GroupNode, nodeInsideAllParens(), FunctionCallParenBracketNode,
+ and FunctionCallParenDotNode.
+
+ * kjs/nodes.h: Removed unused forward declarations and Operator values.
+ Added Precedence enum, and precedence function to all nodes. Removed
+ nodeInsideAllParens. Added streamBinaryOperator function for serialization.
+ Removed GroupNode and PropertyNameNode. Made PropertyNode store an Identifier.
+ Removed FunctionCallParenBracketNode and FunctionCallParenDotNode.
+
+ * kjs/nodes.cpp: Removed Node::nodinsideAllParens, GroupNode, and PropertyNameNode.
+ (KJS::PropertyListNode::evaluate): Changed code to get name directly instead
+ of converting it from an Identifier to a jsString then back to a UString
+ then into an Identifier again!
+
+ * kjs/nodes2string.cpp: Changed special-token implementation to use a separate
+ function for each of Endl, Indent, Unindent, and DotExpr instead of using a
+ single function with a switch. Added a precedence that you can stream in, to
+ cause the next node serialized to add parentheses based on that precedence value.
+ (KJS::operatorString): Moved to the top of the file.
+ (KJS::escapeStringForPrettyPrinting): Moved here from function.cpp. Removed old
+ workaround for snprintf, since StringExtras.h takes care of that.
+ (KJS::operator<<): Made the char and char* versions faster by using UString's
+ character append functions instead of constructing a UString. Added the logic
+ to the Node* version to add parentheses if needed.
+ (KJS::Node::streamLeftAssociativeBinaryOperator): Added helper function.
+ (KJS::ElementNode::streamTo): Use PrecAssignment for the elements.
+ (KJS::BracketAccessorNode::streamTo): Use PrecCall for the expression before
+ the bracket.
+ (KJS::DotAccessorNode::streamTo): Use PrecCall for the expression before the dot.
+ (KJS::ArgumentListNode::streamTo): Use PrecAssignment for the arguments.
+ (KJS::NewExprNode::streamTo): Use PrecMember for the expression.
+ (KJS::FunctionCallValueNode::streamTo): Use PrecCall.
+ (KJS::FunctionCallBracketNode::streamTo): Ditto.
+ (KJS::FunctionCallDotNode::streamTo): Ditto.
+ (KJS::PostfixBracketNode::streamTo): Ditto.
+ (KJS::PostfixDotNode::streamTo): Ditto.
+ (KJS::PostfixErrorNode::streamTo): Use PrecLeftHandSide.
+ (KJS::DeleteBracketNode::streamTo): Use PrecCall.
+ (KJS::DeleteDotNode::streamTo): Ditto.
+ (KJS::DeleteValueNode::streamTo): Use PrecUnary.
+ (KJS::VoidNode::streamTo): Ditto.
+ (KJS::TypeOfValueNode::streamTo): Ditto.
+ (KJS::PrefixBracketNode::streamTo): Use PrecCall.
+ (KJS::PrefixDotNode::streamTo): Ditto.
+ (KJS::PrefixErrorNode::streamTo): Use PrecUnary.
+ (KJS::UnaryPlusNode::streamTo): Ditto.
+ (KJS::NegateNode::streamTo): Ditto.
+ (KJS::BitwiseNotNode::streamTo): Ditto.
+ (KJS::LogicalNotNode::streamTo): Ditto.
+ (KJS::MultNode::streamTo): Use streamLeftAssociativeBinaryOperator.
+ (KJS::DivNode::streamTo): Ditto.
+ (KJS::ModNode::streamTo): Ditto.
+ (KJS::AddNode::streamTo): Ditto.
+ (KJS::SubNode::streamTo): Ditto.
+ (KJS::LeftShiftNode::streamTo): Ditto.
+ (KJS::RightShiftNode::streamTo): Ditto.
+ (KJS::UnsignedRightShiftNode::streamTo): Ditto.
+ (KJS::LessNode::streamTo): Ditto.
+ (KJS::GreaterNode::streamTo): Ditto.
+ (KJS::LessEqNode::streamTo): Ditto.
+ (KJS::GreaterEqNode::streamTo): Ditto.
+ (KJS::InstanceOfNode::streamTo): Ditto.
+ (KJS::InNode::streamTo): Ditto.
+ (KJS::EqualNode::streamTo): Ditto.
+ (KJS::NotEqualNode::streamTo): Ditto.
+ (KJS::StrictEqualNode::streamTo): Ditto.
+ (KJS::NotStrictEqualNode::streamTo): Ditto.
+ (KJS::BitAndNode::streamTo): Ditto.
+ (KJS::BitXOrNode::streamTo): Ditto.
+ (KJS::BitOrNode::streamTo): Ditto.
+ (KJS::LogicalAndNode::streamTo): Ditto.
+ (KJS::LogicalOrNode::streamTo): Ditto.
+ (KJS::ConditionalNode::streamTo): Ditto.
+ (KJS::AssignResolveNode::streamTo): Use PrecAssignment for the right side.
+ (KJS::AssignBracketNode::streamTo): Use PrecCall for the expression before
+ the bracket and PrecAssignment for the right side.
+ (KJS::AssignDotNode::streamTo): Ditto.
+ (KJS::AssignErrorNode::streamTo): Use PrecLeftHandSide for the left side
+ and PrecAssignment for the right side.
+ (KJS::CommaNode::streamTo): Use PrecAssignment for both expressions.
+ (KJS::AssignExprNode::streamTo): Use PrecAssignment.
+
+2007-10-28 Kevin Ollivier <kevino@theolliviers.com>
+
+ Define wx port and set wx port USE options.
+
+ Reviewed by Adam Roben.
+
+ * wtf/Platform.h:
+
+2007-10-28 Mark Rowe <mrowe@apple.com>
+
+ We don't include "config.h" in headers.
+
+ * bindings/jni/jni_instance.h:
+ * kjs/regexp.h:
+ * wtf/TCPageMap.h:
+ * wtf/TCSpinLock.h:
+
+2007-10-28 Maciej Stachowiak <mjs@apple.com>
+
+ Rubber stamped by Mark.
+
+ - avoid using non-portable SIZE_T_MAX in favor of std::numeric_limits
+
+ * kjs/SymbolTable.h:
+ (KJS::SymbolTableIndexHashTraits::emptyValue):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getOwnPropertySlot):
+ (KJS::ActivationImp::put):
+
+2007-10-28 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Eric.
+
+ - switch SymbolTable to be a HashMap instead of a PropertyMap for 3% SunSpider speedup
+
+ * kjs/SymbolTable.h:
+ (KJS::IdentifierRepHash::hash): Special hash function for identifier reps.
+ (KJS::IdentifierRepHash::equal): ditto
+ (KJS::SymbolTableIndexHashTraits::emptyValue): Special HashTraits for the index value.
+ (KJS::SymbolTable): change to a typedef for a HashMap.
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getOwnPropertySlot): Adjusted for new SymbolTable API.
+ (KJS::ActivationImp::deleteProperty): ditto
+ (KJS::ActivationImp::put): ditto
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::initializesymbolTable): Adjusted, since
+ you now have to store a UString::rep, not an identifier.
+
+2007-10-27 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - numerous HashTable performance improvements
+
+ This does not quite add up to a measurable win on SunSpider, but it allows a
+ follow-on > 3% improvement and probably helps WebCore too.
+
+ I made the following improvements, among others:
+
+ - Made HashFunctions note whether it is ok to compare a real value with the equal() function
+ to the empty or deleted value, and used this to optimize the comparisons done in hash lookup.
+
+ - Specialized lookup so it doesn't have to do so many extra branches and build so many extra
+ std::pairs for cases that don't need them. There are now four versions, one for read-only access,
+ two for writing, and one folded directly into add() (these all were improvments).
+
+ - Made HashMap::get() use lookup() directly instead of find() to avoid having to build iterators.
+
+ - Made a special constructor for iterators that knows it points to
+ a valid filled cell and so skips updating itself.
+
+ - Reordered memory accesses in the various lookup functions for better code generation
+
+ - Made simple translators avoid passing a hash code around
+
+ - Other minor tweaks
+
+ * wtf/HashTable.h:
+ (WTF::):
+ (WTF::HashTableConstIterator::HashTableConstIterator):
+ (WTF::HashTableIterator::HashTableIterator):
+ (WTF::IdentityHashTranslator::translate):
+ (WTF::HashTable::end):
+ (WTF::HashTable::lookup):
+ (WTF::HashTable::lookupForWriting):
+ (WTF::HashTable::makeKnownGoodIterator):
+ (WTF::HashTable::makeKnownGoodConstIterator):
+ (WTF::::lookup):
+ (WTF::::lookupForWriting):
+ (WTF::::fullLookupForWriting):
+ (WTF::::add):
+ (WTF::::addPassingHashCode):
+ (WTF::::reinsert):
+ (WTF::::find):
+ (WTF::::contains):
+ * kjs/identifier.cpp:
+ (WTF::):
+ * wtf/HashFunctions.h:
+ (WTF::):
+ * wtf/HashMap.h:
+ (WTF::):
+ (WTF::::get):
+ * wtf/HashSet.h:
+ (WTF::):
+ (WTF::::add):
+ * wtf/ListHashSet.h:
+ (WTF::ListHashSetTranslator::translate):
+
+2007-10-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - fix ASCIICType.h for some Windows compiles
+
+ * wtf/ASCIICType.h: Check the compiler, not the OS, since it's the
+ compiler/library that has the wchar_t that is just a typedef.
+
+2007-10-27 Kevin McCullough <kmccullough@apple.com>
+
+ - BuildFix
+ - Forgot to change the build step when I changed the filename.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-10-27 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Fixed the rest of "ASSERTION FAILED: _hash in KJS::UString::Rep::
+ computedHash()"
+ http://bugs.webkit.org/show_bug.cgi?id=15718
+
+ * kjs/identifier.cpp: Fixed more cases where an Identifier didn't get a
+ hash value. Also changed O(n) strlen to O(1) check for empty string.
+ (KJS::Identifier::add):
+
+ * kjs/ustring.cpp: Changed O(n) strlens to O(1) checks for empty string.
+ (KJS::UString::UString):
+ (KJS::UString::operator=):
+
+2007-10-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - fix pow on Windows
+
+ * wtf/MathExtras.h: (wtf_pow): Add a special case for MSVC, which has
+ a "pow" function that does not properly handle the case where arg1 is
+ NaN and arg2 is 0.
+
+ * kjs/math_object.cpp: (MathFuncImp::callAsFunction): Don't explicity
+ specify "::pow" -- just "pow" is fine.
+
+2007-10-27 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15711
+ force JSImmediate to be inlined for roughly 1.2% SunSpider speedup
+
+ * kjs/JSImmediate.h: Put ALWAYS_INLINE on everything.
+
+ * kjs/object.h: Removed redundant includes.
+ * kjs/value.h: Ditto.
+
+2007-10-27 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Mark.
+
+ - fixed "ASSERTION FAILED: _hash in KJS::UString::Rep::computedHash()"
+ http://bugs.webkit.org/show_bug.cgi?id=15718
+
+ * kjs/identifier.cpp:
+ (KJS::Identifier::addSlowCase): Ensure that empty Identifiers have a hash computed,
+ now that we count on all Identifiers already having one.
+
+2007-10-27 Mark Rowe <mrowe@apple.com>
+
+ Silence a warning.
+
+ * kjs/SymbolTable.h:
+
+2007-10-27 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/function.h:
+
+2007-10-26 Kevin McCullough <kmccullough@apple.com>
+
+ Rubber stamp by Adam.
+
+ - Renamed JSStringRefCOM to JSStringRefBSTR since it he only thing the
+ files contain are functions that operate on BSTRs.
+
+ * API/JSStringRefBSTR.cpp: Copied from API/JSStringRefCOM.cpp.
+ * API/JSStringRefBSTR.h: Copied from API/JSStringRefCOM.h.
+ * API/JSStringRefCOM.cpp: Removed.
+ * API/JSStringRefCOM.h: Removed.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-10-26 Kevin McCullough <kmccullough@apple.com>
+
+ Reviewed by Adam.
+
+ - Made JSStringCreateWithBSTR capable of handling null BSTRs.
+
+ * API/JSStringRefCOM.cpp:
+ (JSStringCreateWithBSTR):
+
+2007-10-26 Sam Weinig <sam@webkit.org>
+
+ Windows build fix.
+
+ * kjs/SymbolTable.h: Add header gaurd.
+ * kjs/nodes.h: #include "SymbolTable.h"
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Suggested by Anders Carlsson.
+
+ Fixed tyop.
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getOwnPropertySlot):
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Suggested by Darin Adler.
+
+ Use computedHash(), which is safer than just directly accessing _hash.
+
+ * kjs/lookup.cpp:
+ (KJS::Lookup::findEntry):
+ (KJS::Lookup::find):
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: svn add SymbolTable.h
+
+ * kjs/SymbolTable.h: Added.
+ (KJS::SymbolTable::set):
+ (KJS::SymbolTable::get):
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix: export SymbolTable.h to WebCore.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Comment tweak suggested by Maciej.
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::getOwnPropertySlot):
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Tweaked property maps to remove 2 branches. 2.5% speedup on SunSpider.
+
+ * kjs/property_map.cpp: Use a special no branch accessor to the UString's
+ hash value. Also, return immediately instead of branching to the end
+ of the loop if the value is not found.
+ (KJS::PropertyMap::get):
+ (KJS::PropertyMap::getLocation):
+ (KJS::PropertyMap::put):
+ (KJS::PropertyMap::insert):
+ (KJS::PropertyMap::remove):
+ (KJS::PropertyMap::checkConsistency):
+
+ * kjs/ustring.h:
+ (KJS::UString::Rep::computedHash): Special no branch accessor to the
+ UString's hash value. Used when the caller knows that the hash value
+ has already been computed. (For example, if the caller got the UString
+ from an Identifier.)
+
+2007-10-26 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Switched ActivationImp to using a symbol table. For now, though, all
+ clients take the slow path.
+
+ Net .6% speedup on SunSpider.
+
+ Slowdowns:
+ - ActivationImp now mallocs in its constructor
+ - Local variable hits use an extra level of indirection to retrieve
+ data
+ - Local variable misses do two lookups
+
+ Speedups:
+ - Fast initialization of local variables upon function entry
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: Added SymbolTable.h
+
+ * kjs/function.cpp:
+ (KJS::ActivationImp::ActivationImp): Malloc a private structure to hold
+ data that won't fit in a JSCell.
+ (KJS::ActivationImp::argumentsGetter): Use slow symbol table path for
+ lookup.
+ (KJS::ActivationImp::getOwnPropertySlot): ditto
+ (KJS::ActivationImp::deleteProperty): ditto
+ (KJS::ActivationImp::put): ditto
+ (KJS::ActivationImp::createArgumentsObject): ditto
+
+ (KJS::ActivationImp::mark): Call JSObject::mark first so that one of
+ our properties doesn't try to recursively mark us. (This caused a crash
+ in earlier testing. Not sure why we haven't run into it before.)
+
+ * kjs/nodes.cpp: Functions now build a symbol table the first time
+ they're called.
+ (KJS::VarDeclNode::evaluate):
+ (KJS::FunctionBodyNode::FunctionBodyNode):
+ (KJS::FunctionBodyNode::initializeSymbolTable):
+ (KJS::FunctionBodyNode::processDeclarations):
+ (KJS::FunctionBodyNode::processDeclarationsForFunctionCode):
+ (KJS::FunctionBodyNode::processDeclarationsForProgramCode):
+
+ * kjs/nodes.h:
+ (KJS::FunctionBodyNode::symbolTable):
+
+ * wtf/Forward.h: Added Vector.
+
+2007-10-26 Kevin McCullough <kmccullough@apple.com>
+
+ - Corrected function name mistake in this changelog.
+
+2007-10-26 Kevin McCullough <kmccullough@apple.com>
+ Reviewed by Sam and Steve.
+
+ - Added convenience methods for converting between BSTR and JSStringRefs
+
+ * API/JSStringRefCOM.cpp: Added.
+ (JSStringCreateWithBSTR):
+ (JSStringCopyBSTR):
+ * API/JSStringRefCOM.h: Added.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-10-26 Mark Rowe <mrowe@apple.com>
+
+ Windows build fix.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+
+2007-10-26 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Make the JSC GC use a separate heap for JSNumbers to get a 0.7-1.4% progression in SunSpider.
+
+ * kjs/CollectorHeapIntrospector.cpp:
+ (KJS::CollectorHeapIntrospector::init):
+ (KJS::CollectorHeapIntrospector::enumerate):
+ * kjs/CollectorHeapIntrospector.h:
+ * kjs/collector.cpp:
+ (KJS::Collector::recordExtraCost):
+ (KJS::Collector::heapAllocate):
+ (KJS::Collector::allocate):
+ (KJS::Collector::allocateNumber):
+ (KJS::Collector::registerThread):
+ (KJS::Collector::markStackObjectsConservatively):
+ (KJS::Collector::markMainThreadOnlyObjects):
+ (KJS::Collector::sweep):
+ (KJS::Collector::collect):
+ * kjs/collector.h:
+ * kjs/internal.h:
+ (KJS::NumberImp::operator new):
+ Force numbers to be allocated in the secondary heap.
+
+2007-10-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - encourage GCC a little harder to inline a few hot functions for 1.5% improvement on SunSpider.
+
+ * kjs/value.h:
+ (KJS::JSValue::getUInt32):
+ (KJS::JSValue::getTruncatedInt32):
+ (KJS::JSValue::toNumber):
+ * wtf/PassRefPtr.h:
+ (WTF::PassRefPtr::~PassRefPtr):
+ * wtf/RefPtr.h:
+ (WTF::RefPtr::operator->):
+
+2007-10-26 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/ExecState.h:
+
+2007-10-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Mark.
+
+ - Merge Context class fully into ExecState, since they are always created and used together.
+
+ No measurable performance impact but this is a useful cleanup.
+
+ * JavaScriptCore.pri:
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::ExecState):
+ (KJS::ExecState::~ExecState):
+ (KJS::ExecState::mark):
+ (KJS::ExecState::lexicalInterpreter):
+ * kjs/ExecState.h:
+ (KJS::ExecState::dynamicInterpreter):
+ (KJS::ExecState::setException):
+ (KJS::ExecState::clearException):
+ (KJS::ExecState::exception):
+ (KJS::ExecState::exceptionSlot):
+ (KJS::ExecState::hadException):
+ (KJS::ExecState::scopeChain):
+ (KJS::ExecState::callingExecState):
+ (KJS::ExecState::propertyNames):
+ * kjs/collector.cpp:
+ (KJS::Collector::reportOutOfMemoryToAllInterpreters):
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::FunctionImp::argumentsGetter):
+ (KJS::FunctionImp::callerGetter):
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::Interpreter):
+ (KJS::Interpreter::init):
+ (KJS::Interpreter::evaluate):
+ (KJS::Interpreter::mark):
+ * kjs/interpreter.h:
+ (KJS::Interpreter::setCurrentExec):
+ (KJS::Interpreter::currentExec):
+ * kjs/nodes.cpp:
+ (KJS::currentSourceId):
+ (KJS::currentSourceURL):
+ (KJS::ThisNode::evaluate):
+ (KJS::ResolveNode::evaluate):
+ (KJS::FunctionCallResolveNode::evaluate):
+ (KJS::PostfixResolveNode::evaluate):
+ (KJS::DeleteResolveNode::evaluate):
+ (KJS::TypeOfResolveNode::evaluate):
+ (KJS::PrefixResolveNode::evaluate):
+ (KJS::AssignResolveNode::evaluate):
+ (KJS::VarDeclNode::evaluate):
+ (KJS::DoWhileNode::execute):
+ (KJS::WhileNode::execute):
+ (KJS::ForNode::execute):
+ (KJS::ForInNode::execute):
+ (KJS::ContinueNode::execute):
+ (KJS::BreakNode::execute):
+ (KJS::ReturnNode::execute):
+ (KJS::WithNode::execute):
+ (KJS::SwitchNode::execute):
+ (KJS::LabelNode::execute):
+ (KJS::TryNode::execute):
+ (KJS::FunctionBodyNode::processDeclarationsFunctionCode):
+ (KJS::FunctionBodyNode::processDeclarationsProgramCode):
+ (KJS::FunctionBodyNode::processDeclarations):
+ (KJS::FuncDeclNode::makeFunction):
+ (KJS::FuncExprNode::evaluate):
+
+2007-10-26 Mark Rowe <mrowe@apple.com>
+
+ Windows build fix.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-10-26 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * JavaScriptCore.pri:
+ * kjs/ExecState.cpp:
+
+2007-10-26 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - moved Context class into ExecState.{h,cpp} in preparation for merging
+ ExecState and Context classes.
+
+ * kjs/ExecState.h: Moved CodeType enum and Context class here in
+ preparation for merging ExecState and Context.
+ * kjs/ExecState.cpp: Moved Context class here from Context.cpp.
+ (KJS::Context::Context):
+ (KJS::Context::~Context):
+ (KJS::Context::mark):
+ * kjs/context.h: Removed.
+ * kjs/Context.cpp: Removed.
+ * kjs/function.h: Removed CodeType enum.
+ * kjs/LabelStack.h: Added. Pulled LabelStack class out of internal.h.
+ * kjs/internal.h: Removed LabelStack.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Added new file, removed ones that are gone.
+ * kjs/collector.cpp: Fixed includes.
+ * kjs/function.cpp: ditto
+ * kjs/internal.cpp: ditto
+ * kjs/interpreter.cpp: ditto
+ * kjs/lookup.h: ditto
+ * kjs/nodes.cpp: ditto
+
+2007-10-26 Mark Rowe <mrowe@apple.com>
+
+ Windows build fix.
+
+ * kjs/string_object.cpp:
+ (KJS::StringObjectFuncImp::callAsFunction):
+
+2007-10-25 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15703
+ fix numeric functions -- improve correctness and speed
+
+ Gives about 1% gain on SunSpider.
+
+ * kjs/value.h: Added toIntegerPreserveNan, removed toUInt16.
+ (KJS::JSValue::toInt32): Changed to call getTruncatedInt32 in a way that works
+ with both immediate and number values.
+ (KJS::JSValue::toUInt32): Ditto.
+ * kjs/value.cpp:
+ (KJS::JSValue::toInteger): Moved the logic from roundValue here, with a couple
+ differences. One is that it now correctly returns 0 for NaN, and another is that
+ there's no special case for 0 or infinity, since the general case already handles
+ those correctly.
+ (KJS::JSValue::toIntegerPreserveNaN): Added. Like toInteger, but without the
+ check for NaN.
+ (KJS::JSValue::toInt32SlowCase): Call toNumber instead of roundValue. The
+ truncation done by the typecast already does the necessary truncation that
+ roundValue was doing.
+ (KJS::JSValue::toUInt32SlowCase): Ditto.
+ (KJS::JSValue::toUInt16): Removed.
+
+ * kjs/internal.h: Removed roundValue.
+ * kjs/internal.cpp: Ditto.
+
+ * kjs/array_object.cpp: (KJS::ArrayProtoFunc::callAsFunction): Remove unneeded
+ code to handle NaN in Array.slice; toInteger now never returns NaN as specified.
+
+ * kjs/date_object.cpp:
+ (KJS::fillStructuresUsingTimeArgs): Replaced call to roundValue with a call to
+ toNumber as specified.
+ (KJS::DateProtoFunc::callAsFunction): In SetTime case, replaced call to roundValue
+ with a call to toNumber and timeClip as specified.
+ (KJS::DateObjectImp::construct): Removed unnecessary checks of numArgs in cases
+ where the default behavior of toInt32 (returning 0) was already correct. Replaced
+ call to roundValue with a call to toNumber as specified.
+ (KJS::DateObjectFuncImp::callAsFunction): Ditto.
+
+ * kjs/math_object.cpp: (MathFuncImp::callAsFunction): Removed unnecessary special
+ cases for the pow function that the library already handles correctly.
+
+ * kjs/number_object.cpp: (NumberProtoFunc::callAsFunction): Changed ToString to
+ call toIntegerPreserveNaN, so we can continue to handle the NaN case differently.
+ The real toInteger now returns 0 for NaN. Took out unneeded special case in
+ ToFixed for undefined; was only needed because our toInteger was wrong. Same
+ thing in ToExponential. Changed ToPrecision to call toIntegerPreserveNaN.
+
+ * kjs/string_object.cpp:
+ (KJS::StringProtoFunc::callAsFunction): Took out CharAt and CharCodeAt special
+ cases for undefined that were only needed because toInteger was wrong. Same in
+ IndexOf, and was able to remove some special cases. In LastIndexOf, used
+ toIntegerPreserveNaN, but was able to remove some special cases there too.
+ Changed Substr implementation to preserve correct behavior with the change
+ to toInteger and match the specification. Also made sure we weren't converting
+ an out of range double to an int.
+ (KJS::StringObjectFuncImp::callAsFunction): Changed constructor to just use
+ toUInt32, because truncating toUInt32 to 16 bits is the same thing and there's
+ no reason to have toUInt16 as a second, less-optimized function that's only
+ called at this one call site.
+
+ * wtf/MathExtras.h: Added trunc function for Windows.
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Tweaked the inner hashtable lookup loop to remove a branch in the "not
+ found" case. .5% speedup on SunSpider.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * wtf/HashTable.h:
+ (WTF::::lookup):
+
+2007-10-25 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - fold together toPrimitive() and toNumber() conversions for 0.5% gain on SunSpider
+
+ * kjs/nodes.cpp:
+ (KJS::SubNode::evaluate): Subtract directly, since toPrimitive() is not
+ adding any value over toNumber() here.
+ (KJS::valueForReadModifyAssignment): Ditto.
+ (KJS::lessThan): Use new getPrimitiveNumber() method to avoid some virtual calls
+ and branches.
+ (KJS::lessThanEq): Ditto.
+ * JavaScriptCore.exp: Export new functions as needed.
+ * kjs/value.h:
+ (KJS::JSValue::toPrimitive): Fixed formatting.
+ (KJS::JSValue::getPrimitiveNumber): New method - this simultaneously converts
+ to number and tells you whether a toPrimitive() conversion with a Number hint
+ would have given a string.
+ * kjs/internal.cpp:
+ (KJS::StringImp::getPrimitiveNumber): Implemented.
+ (KJS::NumberImp::getPrimitiveNumber): ditto
+ (KJS::GetterSetterImp::getPrimitiveNumber): ditto
+ (KJS::StringImp::toPrimitive): Fixed formatting.
+ (KJS::NumberImp::toPrimitive): ditto
+ (KJS::GetterSetterImp::toPrimitive): ditto
+ * kjs/internal.h:
+ * kjs/object.cpp:
+ (KJS::JSObject::getPrimitiveNumber): Implemented.
+ * kjs/object.h:
+
+2007-10-25 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ Remove JSStringRefCFHack from windows as it is no longer needed.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Rolled out my last patch. It turns out that I needed 2 words, not 1,
+ so it didn't help.
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15694
+ Shrink the size of an activation object by 1 word
+
+ This is in preparation for adding a symbol table to the activation
+ object.
+
+ The basic strategy here is to rely on the mutual exclusion between
+ the arguments object pointer and the function pointer (you only need
+ the latter in order to create the former), and store them in the same
+ place. The LazyArgumentsObject class encapsulates this strategy.
+
+ Also inlined the ArgumentsImp constructor, for good measure.
+
+ SunSpider reports no regression. Regression tests pass.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/Context.cpp:
+ (KJS::Context::~Context):
+ * kjs/function.cpp:
+ (KJS::ActivationImp::LazyArgumentsObject::createArgumentsObject):
+ (KJS::ActivationImp::LazyArgumentsObject::mark):
+ (KJS::ActivationImp::argumentsGetter):
+ (KJS::ActivationImp::mark):
+ * kjs/function.h:
+ (KJS::ActivationImp::LazyArgumentsObject::LazyArgumentsObject):
+ (KJS::ActivationImp::LazyArgumentsObject::getOrCreate):
+ (KJS::ActivationImp::LazyArgumentsObject::resetArguments):
+ (KJS::ActivationImp::LazyArgumentsObject::setArgumentsObject):
+ (KJS::ActivationImp::LazyArgumentsObject::argumentsObject):
+ (KJS::ActivationImp::LazyArgumentsObject::setFunction):
+ (KJS::ActivationImp::LazyArgumentsObject::function):
+ (KJS::ActivationImp::LazyArgumentsObject::createdArgumentsObject):
+ (KJS::ActivationImp::LazyArgumentsObject::):
+ (KJS::ActivationImp::ActivationImp::ActivationImp):
+ (KJS::ActivationImp::resetArguments):
+
+2007-10-25 Adam Roben <aroben@apple.com>
+
+ Change JavaScriptCore.vcproj to use DerivedSources.make
+
+ We were trying to emulate the logic of make in
+ build-generated-files.sh, but we got it wrong. We now use a
+ build-generated-files very much like the one that WebCore uses to
+ invoke make.
+
+ We also now only have a Debug configuration of dftables which we build
+ even when doing a Release build of JavaScriptCore. dftables also no
+ longer has the "_debug" name suffix.
+
+ Changes mostly made by Darin, reviewed by me.
+
+ * DerivedSources.make: Add a variable to set the extension used for
+ the dftables executable.
+ * JavaScriptCore.vcproj/JavaScriptCore.sln: Updated to use Debug
+ dftables in Release configurations.
+ * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: Ditto.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ - Updated include path to point to the new location of the derived
+ sources.
+ - Modified pre-build event to pass the right arguments to
+ build-generated-files.sh and not call dftables directly.
+ - Added the derived source files to the project.
+ - Removed grammarWrapper.cpp, which isn't needed now that we're
+ compiling grammar.cpp directly.
+ * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh:
+ Slightly modified from the WebCore version.
+ * JavaScriptCore.vcproj/JavaScriptCore/grammarWrapper.cpp: Removed.
+ * JavaScriptCore.vcproj/dftables/dftables.vcproj:
+ - Changed the output location to match Mac.
+ - Removed the Release configuration.
+ - Removed the _debug suffix.
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Slightly elaborated the differences between declaration procesing in
+ Function Code and Program Code.
+
+ .3% speedup on SunSpider.
+
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::processDeclarationsFunctionCode):
+ (KJS::FunctionBodyNode::processDeclarationsProgramCode): Store a
+ minimum set of attributes instead of recomputing all the time. Also,
+ ignore m_parameters, since programs don't have arguments.
+
+2007-10-25 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ More preparation work before adding long-running mode to testkjs.
+
+ * kjs/testkjs.cpp:
+ (TestFunctionImp::callAsFunction):
+ (prettyPrintScript):
+ (runWithScripts):
+ (parseArguments):
+ (kjsmain):
+ (fillBufferWithContentsOfFile):
+
+2007-10-25 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Bring testkjs code out of the dark ages in preparation for more
+ radical improvements (like long-running testing support!)
+
+ * kjs/testkjs.cpp:
+ (TestFunctionImp::callAsFunction):
+ (setupInterpreter):
+ (doIt):
+ (fillBufferWithContentsOfFile):
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Make a fast path for declaration processing inside Function Code.
+
+ Lifted declaration processing code up from individual declaration nodes
+ and into processDeclarations.
+
+ Broke out processDeclarations into two cases, depending on the type of
+ code. This eliminates 2 branches, and facilitates more radical
+ divergeance in the future.
+
+ 2.5% SunSpider speedup.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/nodes.cpp:
+ (KJS::FunctionBodyNode::initializeDeclarationStacks):
+ (KJS::FunctionBodyNode::processDeclarationsFunctionCode):
+ (KJS::FunctionBodyNode::processDeclarationsProgramCode):
+ (KJS::FunctionBodyNode::execute):
+ (KJS::FuncDeclNode::makeFunction):
+ * kjs/nodes.h:
+
+2007-10-25 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Adam.
+
+ - add header includes needed on platforms that don't use AllInOneFile.cpp
+
+ * API/JSCallbackObject.cpp:
+ * kjs/Context.cpp:
+ * kjs/ExecState.cpp:
+ * kjs/array_instance.cpp:
+ * kjs/function_object.cpp:
+ * kjs/interpreter.cpp:
+ * kjs/nodes.cpp:
+
+2007-10-25 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Geoff.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj: re-mark JSGlobalObject.h as private
+
+2007-10-25 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15683
+ Re-order declaration initialization to avoid calling hasProperty inside
+ VarDeclNode::processDeclaration
+
+ .7% speedup on SunSpider.
+
+ * kjs/function.h:
+ * kjs/function.cpp: Merged parameter processing into FunctionBodyNode's
+ other processing of declared symbols, so the order of execution could
+ change.
+
+ * kjs/nodes.cpp:
+ (KJS::VarDeclNode::getDeclarations): Added special case for the
+ "arguments" property name, explained in the comment.
+
+ (KJS::VarDeclNode::processDeclaration): Removed call to hasProperty
+ in the case of function code, since we know the declared symbol
+ management will resolve conflicts between symbols. Yay!
+
+ (KJS::VarDeclListNode::getDeclarations): Now that VarDeclNode's
+ implementation of getDeclarations is non-trivial, we can't take a
+ short-cut here any longer -- we need to put the VarDecl node on the
+ stack so it gets processed normally.
+
+ (KJS::FunctionBodyNode::processDeclarations): Changed the order of
+ processing to enforce mutual exclusion rules.
+
+ * kjs/nodes.h:
+ (KJS::DeclarationStacks::DeclarationStacks): Structure includes an
+ ExecState now, for fast access to the "arguments" property name.
+
+2007-10-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Add a JSGlobalObject class and remove the InterpreterMap
+ http://bugs.webkit.org/show_bug.cgi?id=15681
+
+ This required making JSCallbackObject a template class to allow for
+ JSGlobalObjects with JSCallbackObject functionality.
+
+ SunSpider claims this was a 0.5% speedup.
+
+ * API/JSCallbackObject.cpp:
+ * API/JSCallbackObject.h:
+ * API/JSCallbackObjectFunctions.h: Copied from API/JSCallbackObject.cpp.
+ (KJS::::JSCallbackObject):
+ (KJS::::init):
+ (KJS::::~JSCallbackObject):
+ (KJS::::initializeIfNeeded):
+ (KJS::::className):
+ (KJS::::getOwnPropertySlot):
+ (KJS::::put):
+ (KJS::::deleteProperty):
+ (KJS::::implementsConstruct):
+ (KJS::::construct):
+ (KJS::::implementsHasInstance):
+ (KJS::::hasInstance):
+ (KJS::::implementsCall):
+ (KJS::::callAsFunction):
+ (KJS::::getPropertyNames):
+ (KJS::::toNumber):
+ (KJS::::toString):
+ (KJS::::setPrivate):
+ (KJS::::getPrivate):
+ (KJS::::inherits):
+ (KJS::::cachedValueGetter):
+ (KJS::::staticValueGetter):
+ (KJS::::staticFunctionGetter):
+ (KJS::::callbackGetter):
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+ * API/JSContextRef.cpp:
+ (JSGlobalContextCreate):
+ * API/JSObjectRef.cpp:
+ (JSObjectMake):
+ (JSObjectGetPrivate):
+ (JSObjectSetPrivate):
+ * API/JSValueRef.cpp:
+ (JSValueIsObjectOfClass):
+ * JavaScriptCore.exp:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bindings/c/c_utility.cpp:
+ (KJS::Bindings::convertValueToNPVariant):
+ * bindings/jni/jni_jsobject.cpp:
+ * bindings/objc/objc_utility.mm:
+ (KJS::Bindings::convertValueToObjcValue):
+ * kjs/Context.cpp:
+ (KJS::Context::Context):
+ * kjs/ExecState.cpp:
+ (KJS::ExecState::lexicalInterpreter):
+ * kjs/JSGlobalObject.h: Added.
+ (KJS::JSGlobalObject::JSGlobalObject):
+ (KJS::JSGlobalObject::isGlobalObject):
+ (KJS::JSGlobalObject::interpreter):
+ (KJS::JSGlobalObject::setInterpreter):
+ * kjs/array_instance.cpp:
+ * kjs/context.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::Interpreter):
+ (KJS::Interpreter::init):
+ (KJS::Interpreter::~Interpreter):
+ (KJS::Interpreter::globalObject):
+ (KJS::Interpreter::initGlobalObject):
+ (KJS::Interpreter::evaluate):
+ * kjs/interpreter.h:
+ * kjs/lookup.h:
+ (KJS::cacheGlobalObject):
+ * kjs/object.h:
+ (KJS::JSObject::isGlobalObject):
+ * kjs/testkjs.cpp:
+
+2007-10-24 Eric Seidel <eric@webkit.org>
+
+ Build fix for Gtk, no review.
+
+ * kjs/collector.cpp: #include "context.h"
+
+2007-10-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Maciej.
+
+ Stop checking isOutOfMemory after every allocation, instead let the collector
+ notify all ExecStates if we ever hit this rare condition.
+
+ SunSpider claims this was a 2.2% speedup.
+
+ * kjs/collector.cpp:
+ (KJS::Collector::collect):
+ (KJS::Collector::reportOutOfMemoryToAllInterpreters):
+ * kjs/collector.h:
+ * kjs/nodes.cpp:
+ (KJS::TryNode::execute):
+
+2007-10-24 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/identifier.h: Remove extra qualification.
+
+2007-10-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Disable ALWAYS_INLINE in debug builds, since it drives the debugger
+ crazy.
+
+ * wtf/AlwaysInline.h:
+
+2007-10-24 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Inlined the fast path for creating an Identifier from an Identifier.
+
+ This is a .4% speedup on SunSpider overall, but as big as a 2.5%
+ speedup on certain individual tests. 65% of the Identifiers creating
+ by SunSpider are already Identifiers.
+
+ (The main reason I'm making this change is that it resolves a large
+ regression in a patch I haven't checked in yet.)
+
+ * JavaScriptCore.exp:
+ * kjs/identifier.cpp:
+ (KJS::Identifier::addSlowCase):
+ * kjs/identifier.h:
+ (KJS::Identifier::Identifier::add):
+
+2007-10-24 Lars Knoll <lars@trolltech.com>
+
+ Reviewed by Simon.
+
+ some changes to the way JS values are converted to Qt values in the script bindings. Added support for converting JS arrays into QStringList's.
+
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtInstance::invokeMethod):
+ * bindings/qt/qt_runtime.cpp:
+ (KJS::Bindings::convertValueToQVariant):
+ (KJS::Bindings::QtField::setValueToInstance):
+
+2007-10-24 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin.
+
+ Remove old relation method, replace with specialised LessThan and lessThenEq functions for a 0.5-0.6% improvement in SunSpider
+
+ * kjs/nodes.cpp:
+ (KJS::lessThan):
+ (KJS::lessThanEq):
+ (KJS::LessNode::evaluate):
+ (KJS::GreaterNode::evaluate):
+ (KJS::LessEqNode::evaluate):
+ (KJS::GreaterEqNode::evaluate):
+ * kjs/operations.cpp:
+ * kjs/operations.h:
+
+2007-10-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ * kjs/nodes.h:
+ (KJS::ImmediateNumberNode::): Fix ASSERT correctness (and debug build!)
+
+2007-10-24 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ * kjs/object.cpp: (KJS::JSObject::defaultValue): Get rid of a little
+ Identifier ref/deref for what SunSpider claims is a 0.4% speedup.
+
+2007-10-24 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - separate out the code to create a hash table the first time from the code
+ to rehash
+
+ SunSpider claims this was a 0.7% speedup.
+
+ * kjs/property_map.cpp:
+ (KJS::PropertyMap::expand): Changed to call either createTable or rehash.
+ (KJS::PropertyMap::createTable): Added. For the case where we had no table.
+ (KJS::PropertyMap::rehash): Removed code needed only in the case where we
+ had no table.
+ * kjs/property_map.h: Added createTable.
+
+2007-10-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Add ImmediateNumberNode to hold a JSValue* instead of a double for numbers
+ which can be represented by JSImmediate.
+
+ SunSpider claims this was a 0.6% speedup.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::NumberNode::evaluate):
+ (KJS::ImmediateNumberNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::Node::):
+ (KJS::ImmediateNumberNode::):
+ * kjs/nodes2string.cpp:
+ (ImmediateNumberNode::streamTo):
+
+2007-10-24 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15657
+ change static hash tables to use powers of two for speed
+
+ Seems to give 0.7% SunSpider speedup.
+
+ * kjs/create_hash_table: Updated to generate new format.
+ * kjs/lookup.cpp:
+ (KJS::keysMatch): Took out unneeded typecast.
+ (KJS::findEntry): Updated to expect table type 3 -- changed the printf to a plain old assert.
+ Replaced the modulus with a bit mask.
+ (KJS::Lookup::findEntry): Get the hash directly, since we know identifiers already have computed
+ their hash -- saves a branch.
+ (KJS::Lookup::find): Ditto.
+ * kjs/lookup.h: Changed attr from 2-byte value to one-byte value. Replaced hashSize with hashSizeMask.
+
+2007-10-24 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - remove KJS_CHECKEXCEPTIONs in places where exceptions can't happen for 0.6% SunSpider speedup
+
+ * kjs/nodes.cpp:
+ (KJS::DoWhileNode::execute):
+ (KJS::WhileNode::execute):
+ (KJS::ForNode::execute):
+ (KJS::ForInNode::execute):
+ (KJS::SourceElementsNode::execute):
+
+2007-10-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ * kjs/JSImmediate.h: (KJS::JSImmediate::getUInt32):
+ Changed an && to an & for a 1% gain in SunSpider.
+
+2007-10-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Reduce branching in implementations of some operator implementations, yielding 1.3% boost to SunSpider.
+
+ * kjs/nodes.cpp:
+ (KJS::MultNode::evaluate):
+ (KJS::DivNode::evaluate):
+ (KJS::ModNode::evaluate):
+ (KJS::add):
+ (KJS::sub):
+ (KJS::AddNode::evaluate):
+ (KJS::SubNode::evaluate):
+ (KJS::valueForReadModifyAssignment):
+ * kjs/operations.cpp:
+ * kjs/operations.h:
+
+2007-10-23 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej.
+
+ Separating all of the simple (eg. non-read-modify-write) binary operators
+ into separate classes in preparation for further JS optimisations.
+
+ Happily this produces a 0.8% to 1.0% performance increase in SunSpider with
+ no further work.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::MultNode::evaluate):
+ (KJS::DivNode::evaluate):
+ (KJS::ModNode::evaluate):
+ (KJS::AddNode::evaluate):
+ (KJS::SubNode::evaluate):
+ (KJS::LeftShiftNode::evaluate):
+ (KJS::RightShiftNode::evaluate):
+ (KJS::UnsignedRightShiftNode::evaluate):
+ (KJS::LessNode::evaluate):
+ (KJS::GreaterNode::evaluate):
+ (KJS::LessEqNode::evaluate):
+ (KJS::GreaterEqNode::evaluate):
+ (KJS::InstanceOfNode::evaluate):
+ (KJS::InNode::evaluate):
+ (KJS::EqualNode::evaluate):
+ (KJS::NotEqualNode::evaluate):
+ (KJS::StrictEqualNode::evaluate):
+ (KJS::NotStrictEqualNode::evaluate):
+ (KJS::BitAndNode::evaluate):
+ (KJS::BitXOrNode::evaluate):
+ (KJS::BitOrNode::evaluate):
+ (KJS::LogicalAndNode::evaluate):
+ (KJS::LogicalOrNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::MultNode::):
+ (KJS::DivNode::):
+ (KJS::ModNode::):
+ (KJS::AddNode::):
+ (KJS::SubNode::):
+ (KJS::LeftShiftNode::):
+ (KJS::RightShiftNode::):
+ (KJS::UnsignedRightShiftNode::):
+ (KJS::LessNode::):
+ (KJS::GreaterNode::):
+ (KJS::LessEqNode::):
+ (KJS::GreaterEqNode::):
+ (KJS::InstanceOfNode::):
+ (KJS::InNode::):
+ (KJS::EqualNode::):
+ (KJS::NotEqualNode::):
+ (KJS::StrictEqualNode::):
+ (KJS::NotStrictEqualNode::):
+ (KJS::BitAndNode::):
+ (KJS::BitOrNode::):
+ (KJS::BitXOrNode::):
+ (KJS::LogicalAndNode::):
+ (KJS::LogicalOrNode::):
+ * kjs/nodes2string.cpp:
+ (MultNode::streamTo):
+ (DivNode::streamTo):
+ (ModNode::streamTo):
+ (AddNode::streamTo):
+ (SubNode::streamTo):
+ (LeftShiftNode::streamTo):
+ (RightShiftNode::streamTo):
+ (UnsignedRightShiftNode::streamTo):
+ (LessNode::streamTo):
+ (GreaterNode::streamTo):
+ (LessEqNode::streamTo):
+ (GreaterEqNode::streamTo):
+ (InstanceOfNode::streamTo):
+ (InNode::streamTo):
+ (EqualNode::streamTo):
+ (NotEqualNode::streamTo):
+ (StrictEqualNode::streamTo):
+ (NotStrictEqualNode::streamTo):
+ (BitAndNode::streamTo):
+ (BitXOrNode::streamTo):
+ (BitOrNode::streamTo):
+ (LogicalAndNode::streamTo):
+
+2007-10-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15639
+ fix Math.abs(0), Math.ceil(-0), and Math.floor(-0)
+
+ Test: fast/js/math.html
+
+ * kjs/math_object.cpp: (MathFuncImp::callAsFunction):
+ Fix abs to look at the sign bit. Add a special case for values in the range
+ between -0 and -1 and a special case for ceil and for -0 for floor.
+
+2007-10-23 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric.
+
+ - streamline exception handling code for a >1% speed-up of SunSpider
+
+ * kjs/nodes.cpp: Changed macros to use functions for everything that's not
+ part of normal execution. We'll take function call overhead when propagating
+ an exception or out of memory.
+ (KJS::createOutOfMemoryCompletion): Added.
+ (KJS::substitute): Use append instead of the relatively inefficient + operator.
+ (KJS::Node::rethrowException): Added.
+ * kjs/nodes.h: Added rethrowException.
+
+2007-10-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15636
+ some JavaScriptCore regression tests are failing due to numeric conversion
+
+ This should restore correctness and make speed better too, restoring some
+ of the optimization we lost in my last check-in.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::getTruncatedInt32): Added. Uses the range checking idiom
+ I used in my patch yesterday.
+ (KJS::JSImmediate::getTruncatedUInt32): Ditto.
+
+ * kjs/internal.h: Removed getInt32 and added getTruncatedInt/UInt32.
+ * kjs/internal.cpp:
+ (KJS::NumberImp::getUInt32): Changed to always use double, since I can't find
+ a way to write this more efficiently for float.
+ (KJS::NumberImp::getTruncatedInt32): Added.
+ (KJS::NumberImp::getTruncatedUInt32): Added.
+
+ * kjs/value.h: Removed getInt32 and added getTruncatedInt/UInt32.
+ (KJS::JSValue::getUInt32):
+ (KJS::JSValue::getTruncatedInt32): Added.
+ (KJS::JSValue::getTruncatedUInt32): Added.
+ (KJS::JSValue::toInt32): Changed getInt32 call to getTruncatedInt32.
+ (KJS::JSValue::toUInt32): Changed getUInt32 call to getTruncatedUInt32.
+ * kjs/value.cpp:
+ (KJS::JSCell::getTruncatedInt32): Added.
+ (KJS::JSCell::getTruncatedUInt32): Added.
+ (KJS::JSValue::toInteger): Changed getUInt32 call to getTruncatedInt32.
+ (KJS::JSValue::toInt32SlowCase): Removed extra getInt32 call I accidentally
+ had left in here.
+ (KJS::JSValue::toUInt32SlowCase): Ditto.
+ (KJS::JSValue::toUInt16): Changed getUInt32 call to getTruncatedUInt32.
+
+ * JavaScriptCore.exp: Updated.
+
+2007-10-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15632
+ js1_5/Array/array-001.js test failing
+
+ One of the JavaScriptCore tests was failing; it failed because of
+ my change to NumberImp::getUInt32. The incorrect code I copied was
+ from JSImmediate::getUInt32, and was a pre-existing bug.
+
+ This patch fixes correctness, but will surely slow down SunSpider.
+ We may be able to code this tighter and get the speed back.
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::getInt32): Renamed from toInt32 to more accurately
+ reflect the fact that this function only returns true if the value is
+ accurate (no fractional part, etc.). Changed code so that it returns
+ false when the value has a fraction.
+ (KJS::JSImmediate::getUInt32): Ditto.
+
+ * kjs/internal.cpp:
+ (KJS::NumberImp::getInt32): Changed code so that it returns false when
+ the value has a fraction. Restores the old behavior.
+ (KJS::NumberImp::getUInt32): Ditto.
+
+ * kjs/value.h:
+ (KJS::JSValue::getInt32): Updated for name change.
+ (KJS::JSValue::getUInt32): Ditto.
+ (KJS::JSValue::toInt32): Ditto.
+ (KJS::JSValue::toUInt32): Ditto.
+
+2007-10-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Brady.
+
+ - fix crash seen when running JavaScriptCore tests
+
+ * kjs/array_instance.cpp: (KJS::ArrayInstance::mark):
+ Copy and paste error: I accidentally had code here that was
+ making a copy of the HashMap -- that's illegal inside a mark
+ function and was unnecessary. The other callsite was modifying
+ the map as it iterated it, but this function is not.
+
+2007-10-22 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Oliver.
+
+ - Avoid moving floats into integer registers in jsNumber() for 3% speedup on SunSpider
+ http://bugs.webkit.org/show_bug.cgi?id=15627
+
+ * kjs/JSImmediate.h:
+ (KJS::JSImmediate::fromDouble): Avoid moving floats to integer
+ registers since this is very slow.
+
+2007-10-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15617
+ improve speed of integer conversions
+
+ Makes SunSpider 6% faster.
+
+ * kjs/JSImmediate.h: Added toInt32 and toUInt32, with separate versions for
+ 32-bit and 64-bit.
+ * kjs/value.h:
+ (KJS::JSValue::getUInt32): Call JSImmediate::toUInt32.
+
+ * kjs/internal.h: Added getInt32.
+ * kjs/internal.cpp:
+ (KJS::NumberImp::getInt32): Added.
+ (KJS::NumberImp::getUInt32): Replaced with more-optimal implementation
+ stolen from JSValue.
+
+ * kjs/value.h:
+ (KJS::jsNumber): Marked ALWAYS_INLINE, because this wasn't getting
+ inlined.
+ (KJS::JSValue::getInt32): Added.
+ (KJS::JSValue::getUInt32): Changed to call the new JSImmediate::toUInt32
+ to avoid converting from float to double.
+ (KJS::JSValue::toInt32): Made inline, separated out the slow case.
+ (KJS::JSValue::toUInt32): Ditto.
+ * kjs/value.cpp:
+ (KJS::JSCell::getInt32): Added.
+ (KJS::JSValue::toInt32SlowCase): Renamed from toInt32. Changed to use the
+ new getInt32. Added a faster case for in-range numbers.
+ (KJS::JSValue::toUInt32SlowCase): Ditto.
+ (KJS::JSValue::toUInt16): Added a faster case for in-range numbers.
+
+ * JavaScriptCore.exp: Updated for changes.
+
+2007-10-22 Adam Roben <aroben@apple.com>
+
+ Windows build fix
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Turn off
+ warning about implicit conversion to bool.
+
+2007-10-22 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * kjs/array_instance.cpp:
+
+2007-10-22 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15606
+ make cut-off for sparse vs. dense arrays smarter for speed with large arrays
+
+ Makes the morph test in SunSpider 26% faster, and the overall
+ benchmark 3% faster.
+
+ This also fixes some small problems we had with the distinction
+ between nonexistent and undefined values in arrays.
+
+ * kjs/array_instance.h: Tweaked formatting and naming.
+ * kjs/array_instance.cpp: Copied from kjs/array_object.cpp.
+ (KJS::storageSize): Added. Computes the size of the storage given a vector length.
+ (KJS::increasedVectorLength): Added. Implements the rule for resizing the vector.
+ (KJS::isDenseEnoughForVector): Added.
+ (KJS::ArrayInstance::ArrayInstance): Initialize the new fields.
+ (KJS::ArrayInstance::~ArrayInstance): Since m_storage is now never 0, delete it.
+ (KJS::ArrayInstance::getItem): Updated for name changes.
+ (KJS::ArrayInstance::lengthGetter): Ditto.
+ (KJS::ArrayInstance::inlineGetOwnPropertySlot): Added. Allows both versions of
+ getOwnPropertySlot to share more code.
+ (KJS::ArrayInstance::getOwnPropertySlot): Just refactored, no code change.
+ (KJS::ArrayInstance::put): Added logic for extending the vector as long as the
+ array is dense enough. Also keep m_numValuesInVector up to date.
+ (KJS::ArrayInstance::deleteProperty): Added code to keep m_numValuesInVector
+ up to date.
+ (KJS::ArrayInstance::getPropertyNames): Fixed bug where this would omit names
+ for array indices with undefined values.
+ (KJS::ArrayInstance::increaseVectorLength): Renamed from resizeStorage. Also
+ simplified to only handle getting larger.
+ (KJS::ArrayInstance::setLength): Added code to update m_numValuesInVector, to
+ zero out the unused part of the vector and to delete the map if it's no longer
+ needed.
+ (KJS::ArrayInstance::mark): Tweaked formatting.
+ (KJS::compareByStringForQSort): Ditto.
+ (KJS::ArrayInstance::sort): Ditto.
+ (KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
+ Ditto.
+ (KJS::compareWithCompareFunctionForQSort): Ditto.
+ (KJS::ArrayInstance::compactForSorting): Fixed bug where this would turn
+ undefined values into nonexistent values in some cases.
+
+ * kjs/array_object.h: Removed MAX_ARRAY_INDEX.
+ * kjs/array_object.cpp: Removed ArrayInstance. Moved to a separate file.
+
+ * JavaScriptCore.pri: Added array_instance.cpp.
+ * JavaScriptCore.xcodeproj/project.pbxproj: Ditto.
+ * kjs/AllInOneFile.cpp: Ditto.
+
+2007-10-22 Andrew Wellington <proton@wiretapped.net>
+
+ Reviewed by Mark Rowe.
+
+ Fix for local database support after r26879
+ Ensure that ENABLE_DATABASE and ENABLE_ICONDATABASE are correctly set
+
+ * Configurations/JavaScriptCore.xcconfig:
+
+2007-10-22 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by Alp.
+
+ Build fix for the non-qmake builds.
+
+ * wtf/Platform.h: Default to enabling the database features unless
+ otherwise specified. (similar to ENABLE_ICONDATABASE)
+
+2007-10-22 Holger Freyther <zecke@selfish.org>
+
+ Reviewed by Simon Hausmann <hausmann@kde.org>.
+
+ * Do not build testkjs as an application bundle. This is
+ needed for run-javascriptcore-tests on OSX.
+ * Also, based on r26633, allow to test the WebKit/Qt port on OSX.
+ * Set DYLD_LIBRARY_PATH if it was set in the environment. It must be set
+ as we do not have -rpath on OSX.
+
+ * kjs/testkjs.pro:
+
+2007-10-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Alp.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15575
+ Bug 15575: [GTK] Implement threading using GThread
+
+ * wtf/Platform.h: Do not enable pthreads for Gtk.
+
+2007-10-21 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Mitz.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=15603
+ Bug 15603: Regression(r26847): Crash when sorting an empty array from JavaScript
+
+ * kjs/array_object.cpp:
+ (KJS::freeStorage): Reinstate null-check that was removed in r26847.
+
+2007-10-21 Darin Adler <darin@apple.com>
+
+ - fix Windows build
+
+ * kjs/array_instance.h: Removed unused ExecState parameter.
+ * kjs/array_object.cpp:
+ (KJS::ArrayInstance::put): Ditto.
+ (KJS::ArrayInstance::setLength): Ditto.
+
+2007-10-21 Darin Adler <darin@apple.com>
+
+ * kjs/array_object.cpp: (KJS::ArrayInstance::put):
+ Add missing assignment that was causing regression test crash.
+
+2007-10-21 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15585
+ speed up sparse arrays by using a custom map
+
+ Speeds up SunSpider by 10%.
+
+ * kjs/array_object.cpp:
+ (allocateStorage): Leave room for an additional pointer.
+ (reallocateStorage): Ditto.
+ (freeStorage): Ditto.
+ (ArrayInstance::~ArrayInstance): Delete the overflow map if present.
+ (ArrayInstance::getItem): Read values from the overflow map if present.
+ Removed the check of length, since it slows down the common case.
+ (ArrayInstance::getOwnPropertySlot): Ditto. Also removed the fallback
+ to the property map.
+ (ArrayInstance::put): Write values into the overflow map as needed.
+ Also create overflow map when needed.
+ (ArrayInstance::deleteProperty): Remove values from the overflow map
+ as appropriate.
+ (ArrayInstance::getPropertyNames): Add a name for each identifier in
+ the property map. This is extremely inefficient.
+ (ArrayInstance::setLength): Remove any values in the overflow map
+ that are past the new length, as we formerly did with the property map.
+ (ArrayInstance::mark): Mark any values in the overflow map.
+ (compareByStringForQSort): Removed unneeded undefined case, since
+ compactForSorting guarantees we will have no undefined values.
+ (compareWithCompareFunctionForQSort): Ditto.
+ (ArrayInstance::compactForSorting): Copy all the values out of the
+ overflow map and destroy it.
+
+ * kjs/property_map.h: Removed now-unused getSparseArrayPropertyNames.
+ * kjs/property_map.cpp: Ditto.
+
+2007-10-20 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej.
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15579
+ stop churning identifier reference counts copying Completion objects
+
+ * kjs/completion.h: Replace the Identifier with an Identifier*.
+ * kjs/nodes.cpp:
+ (ForInNode::execute): Update for change to Completion constructor.
+ (ContinueNode::execute): Ditto.
+ (BreakNode::execute): Ditto.
+
+2007-10-20 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Alp.
+
+ Gtk changes needed to enable HTML 5 client-side database storage.
+
+ * wtf/Platform.h: Have Gtk use pthreads for now.
+
+2007-10-20 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15570
+ Store gathered declaration nodes in the function body node.
+
+ This means that you only have to gather the declaration nodes the first
+ time the function executes. Performance gain of 2.10% on SunSpider,
+ 0.90% on command-line JS iBench.
+
+ * kjs/nodes.cpp: Split declaration stack initialization code off into
+ initializeDeclarationStacks().
+ (FunctionBodyNode::FunctionBodyNode):
+ (FunctionBodyNode::initializeDeclarationStacks):
+ (FunctionBodyNode::processDeclarations):
+
+ * kjs/nodes.h: Changed DeclarationStacks structure to hold references,
+ since the actual Vectors are now stored either on the stack or in the
+ function body node.
+
+2007-10-19 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ http://bugs.webkit.org/show_bug.cgi?id=15559
+ Moved processDeclarations call into FunctionBodyNode::execute
+
+ To improve encapsulation, moved processDeclarations call into
+ FunctionBodyNode::execute. Also marked processDeclarations
+ ALWAYS_INLINE, since it has only 1 caller now. This is a .71% speedup
+ on command-line JS iBench.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::GlobalFuncImp::callAsFunction):
+ * kjs/function.h:
+ * kjs/interpreter.cpp:
+ (KJS::Interpreter::evaluate):
+ * kjs/nodes.cpp:
+ (FunctionBodyNode::execute):
+ * kjs/nodes.h:
+
+2007-10-19 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Sam
+
+ Queue -> Deque! and small style tweaks
+
+ * JavaScriptCore.vcproj/WTF/WTF.vcproj:
+ * JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+ * wtf/Deque.h: Added.
+ (WTF::DequeNode::DequeNode):
+ (WTF::Deque::Deque):
+ (WTF::Deque::~Deque):
+ (WTF::Deque::size):
+ (WTF::Deque::isEmpty):
+ (WTF::Deque::append):
+ (WTF::Deque::prepend):
+ (WTF::Deque::first):
+ (WTF::Deque::last):
+ (WTF::Deque::removeFirst):
+ (WTF::Deque::clear):
+ * wtf/Queue.h: Removed.
+
+
+2007-10-19 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Oliver
+
+ Added a simple LinkedList based Queue to wtf
+ We can make a better, more sophisticated an efficient one later, but have
+ needed one for some time, now!
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * wtf/Queue.h: Added.
+ (WTF::QueueNode::QueueNode):
+ (WTF::Queue::Queue):
+ (WTF::Queue::~Queue):
+ (WTF::Queue::size):
+ (WTF::Queue::isEmpty):
+ (WTF::Queue::append):
+ (WTF::Queue::prepend):
+ (WTF::Queue::first):
+ (WTF::Queue::last):
+ (WTF::Queue::removeFirst):
+ (WTF::Queue::clear):
+
+2007-10-19 Nikolas Zimmermann <zimmermann@kde.org>
+
+ Reviewed by Anders.
+
+ Try to fix Qt/Win build slave, by including windows.h also on Qt/Win.
+
+ * kjs/testkjs.cpp: Change PLATFORM(WIN) to PLATFORM(WIN_OS)
+
+2007-10-19 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by Lars.
+
+ Fix compilation on Windows when wchar_t is a typedef instead of a native type (triggered by -Zc:wchar_t-).
+ Don't provide the wchar_t overloads then as they conflict with the unsigned short ones.
+
+ * wtf/ASCIICType.h:
+ (WTF::isASCIIAlpha):
+ (WTF::isASCIIAlphanumeric):
+ (WTF::isASCIIDigit):
+ (WTF::isASCIIHexDigit):
+ (WTF::isASCIILower):
+ (WTF::isASCIISpace):
+ (WTF::toASCIILower):
+ (WTF::toASCIIUpper):
+
+2007-10-19 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by Lars.
+
+ Another build fix for the windows/qt build: Apply the same fix as in revision 26686 also to kjs/config.h to disable the disallowctype feature.
+
+ * kjs/config.h:
+
+2007-10-18 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Adam.
+
+ - use __declspec(thread) for fast thread-local storage on Windows
+
+ - 2.2% speedup on sunspider (on Windows)
+ - 7% speedup on the string section
+ - 6% speedup on JS iBench
+
+ - fixed <rdar://problem/5473084> PLT on Windows got 2.5% slower between r25406 and r25422
+ - fixed at least some of <rdar://5527965? i-Bench JS was 14% slower in 310A11 than 310A10
+
+
+ * wtf/FastMalloc.cpp:
+ (WTF::getThreadHeap):
+ (WTF::setThreadHeap):
+ (WTF::TCMalloc_ThreadCache::GetCache):
+ (WTF::TCMalloc_ThreadCache::GetCacheIfPresent):
+ (WTF::TCMalloc_ThreadCache::CreateCacheIfNecessary):
+
+2007-10-17 Darin Adler <darin@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ - fix http://bugs.webkit.org/show_bug.cgi?id=15543
+ <rdar://problem/5545639> REGRESSION (r26697):
+ GoogleDocs: Can't create new documents or open existing ones
+
+ Test: fast/js/regexp-non-character.html
+
+ * pcre/pcre_compile.c: (check_escape): Take out the checks for valid characters
+ in the \u sequences -- not needed and actively harmful.
+
+2007-10-17 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Oliver.
+
+ * wtf/Platform.h:
+ #define USE_PTHREADS on Mac.
+
+2007-10-17 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Merged DeclaredFunctionImp into FunctionImp (the base class) because
+ the distinction between the two was unused.
+
+ Removed codeType() from FunctionImp because FunctionImp and its
+ subclasses all returned FunctionCode, so it was unused, practically
+ speaking.
+
+ Removed a different codeType() from GlobalFuncImp because it was unused.
+ (Perhaps it was vestigial from a time when GlobalFuncImp used to
+ inherit from FunctionImp.)
+
+ * bindings/runtime_method.cpp:
+ * bindings/runtime_method.h:
+ * kjs/function.cpp:
+ (KJS::FunctionImp::FunctionImp):
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::FunctionImp::construct):
+ (KJS::FunctionImp::execute):
+ (KJS::FunctionImp::processVarDecls):
+ * kjs/function.h:
+ (KJS::FunctionImp::implementsConstruct):
+ (KJS::FunctionImp::scope):
+ * kjs/function_object.cpp:
+ (FunctionProtoFunc::callAsFunction):
+ (FunctionObjectImp::construct):
+ * kjs/nodes.cpp:
+ (FuncDeclNode::processFuncDecl):
+ (FuncExprNode::evaluate):
+
+2007-10-17 Adam Roben <aroben@apple.com>
+
+ Windows build fix part 2.
+
+ Fix was by Darin, reviewed by Anders and Adam.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add
+ FastMallocPCRE.cpp to the project, and let Visual Studio have its way
+ with the post-build step.
+ * pcre/pcre.h: Don't DLL export the entry points just because this
+ is Win32 -- this is an internal copy of PCRE and should be private.
+ * pcre/pcre_compile.c: Fix an uninitialized variable warning --
+ there's no real problem but it's better to quiet the compiler by
+ tweaking the code slightly than turn off the warning entirely.
+
+2007-10-17 Adam Roben <aroben@apple.com>
+
+ Windows build fix.
+
+ Reviewed by Anders.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Disable
+ some mismatched signed/unsigned comparison warnings.
+ * pcre/pcre_exec.c:
+ (match): #if-out some labels that don't seem to exist.
+
+2007-10-17 Mark Rowe <mrowe@apple.com>
+
+ Gtk build fix.
+
+ * JavaScriptCore.pri: Add FastMallocPCRE.cpp.
+ * pcre/pcre_get. #if out two functions that depend on pcre_get_stringnumber, which
+ is currently unavailable for UTF-16.
+
+2007-10-16 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - merged PCRE changes between 6.4 and 6.5
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ Removed pcre_config.c, pcre_globals.c, pcre_info.c, pcre_maketables.c,
+ pcre_printint.src, pcre_refcount.c, pcre_study.c, pcre_try_flipped.c,
+ pcre_ucp_findchar.c, pcre_version.c, and ucptable.c. Added pcre_ucp_searchfuncs.c.
+
+ * pcre/AUTHORS:
+ * pcre/LICENCE:
+ * pcre/MERGING:
+ * pcre/dftables.c:
+ * pcre/pcre-config.h:
+ * pcre/pcre.h:
+ * pcre/pcre.pri:
+ * pcre/pcre_compile.c:
+ * pcre/pcre_exec.c:
+ * pcre/pcre_fullinfo.c:
+ * pcre/pcre_get.c:
+ * pcre/pcre_internal.h:
+ * pcre/pcre_maketables.c:
+ * pcre/pcre_ord2utf8.c:
+ * pcre/pcre_tables.c:
+ * pcre/pcre_ucp_searchfuncs.c: Copied from pcre/pcre_ucp_findchar.c.
+ * pcre/pcre_xclass.c:
+ * pcre/ucp.h:
+ * pcre/ucpinternal.h:
+ * pcre/ucptable.c:
+ Updated with new versions from the PCRE 6.5 release, merged with changes.
+
+ * pcre/pcre_config.c: Removed.
+ * pcre/pcre_globals.c: Removed.
+ * pcre/pcre_info.c: Removed.
+ * pcre/pcre_printint.src: Removed.
+ * pcre/pcre_refcount.c: Removed.
+ * pcre/pcre_study.c: Removed.
+ * pcre/pcre_try_flipped.c: Removed.
+ * pcre/pcre_ucp_findchar.c: Removed.
+ * pcre/pcre_version.c: Removed.
+
+2007-10-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Removed KJS_VERBOSE because it was getting in the way of readability,
+ and the messages didn't seem very helpful.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::callAsFunction):
+ (KJS::FunctionImp::passInParameters):
+ * kjs/lookup.h:
+ (KJS::lookupPut):
+ * kjs/object.cpp:
+ (KJS::JSObject::put):
+ * kjs/value.h:
+
+2007-10-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Removed the Parameter class because it was a redundant wrapper around
+ Identifier.
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::passInParameters):
+ (KJS::FunctionImp::getParameterName):
+ * kjs/nodes.cpp:
+ (FunctionBodyNode::addParam):
+ * kjs/nodes.h:
+ (KJS::FunctionBodyNode::):
+
+2007-10-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Global replace of assert with ASSERT.
+
+2007-10-16 Adam Roben <aroben@apple.com>
+
+ Make testkjs not delay-load WebKit
+
+ Soon, delay-loading WebKit will be impossible (because we will be
+ using __declspec(thread) for thread-local storage). This change
+ prepares testkjs for the future.
+
+ Reviewed by Sam.
+
+ * JavaScriptCore.vcproj/JavaScriptCore.sln: Removed WebKitInitializer,
+ added FindSafari.
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj: Don't link against
+ WebKitInitializer, don't delay-load WebKit.
+ * kjs/testkjs.cpp: Don't use WebKitInitializer.
+
+2007-10-16 Adam Roben <aroben@apple.com>
+
+ Updated testkjs for the rename of WebKit_debug.dll to WebKit.dll for the Debug configuration
+
+ Reviewed by Kevin McCullough.
+
+ * JavaScriptCore.vcproj/debug.vsprops: Added WebKitDLLConfigSuffix.
+ * JavaScriptCore.vcproj/debug_internal.vsprops: Ditto.
+ * JavaScriptCore.vcproj/release.vsprops: Ditto.
+ * JavaScriptCore.vcproj/testkjs/testkjs.vcproj: Use
+ WebKitDLLConfigSuffix when referring to WebKit.dll, and fixed a typo
+ in the name of icuuc36[_debug].dll.
+
+2007-10-16 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Re-structured variable and function declaration code.
+
+ Command-line JS iBench shows no regression.
+
+ Here are the changes:
+
+ 1. Function declarations are now processed at the same time as var
+ declarations -- namely, immediately upon entry to an execution context.
+ This does not match Firefox, which waits to process a function
+ declaration until the declaration's containing block executes, but it
+ does match IE and the ECMA spec. (10.1.3 states that var and function
+ declarations should be processed at the same time -- namely, "On
+ entering an execution context." 12.2 states that "A Block does not
+ define a new execution scope.")
+
+ 2. Declaration processing proceeds iteratively now, rather than
+ recursively, storing the nodes is finds in stacks. This will later
+ facilitate an optimization to hold on to the gathered declaration nodes,
+ rather than re-fetching them in every function call.
+ [ http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ Modified these tests because they expected the incorrect Mozilla
+ behavior described above:
+
+ * tests/mozilla/ecma_3/Function/scope-001.js:
+ * tests/mozilla/js1_5/Scope/regress-184107.js:
+
+2007-10-16 Darin Adler <darin@apple.com>
+
+ - try to fix the GTK build
+
+ * kjs/ustring.cpp: Include ASCIICType.h, not ASCIICtype.h.
+
+2007-10-16 Darin Adler <darin@apple.com>
+
+ - try to fix the Windows build
+
+ * kjs/date_object.cpp: (KJS::parseDate): A couple instances of isspace were
+ in here. Not sure why it wasn't failing elsewhere. Changed to isASCIISpace.
+
+2007-10-16 Darin Adler <darin@apple.com>
+
+ - try to fix the GTK build
+
+ * kjs/ustring.cpp: Include ASCIICType.h.
+
+2007-10-16 Darin Adler <darin@apple.com>
+
+ Reviewed by Maciej and Geoff (and looked over by Eric).
+
+ - http://bugs.webkit.org/show_bug.cgi?id=15519
+ eliminate use of <ctype.h> for processing ASCII
+
+ * wtf/ASCIICType.h: Added.
+ * wtf/DisallowCType.h: Added.
+
+ * kjs/config.h: Include DisallowCType.h.
+
+ * kjs/date_object.cpp:
+ (KJS::skipSpacesAndComments):
+ (KJS::findMonth):
+ (KJS::parseDate):
+ * kjs/function.cpp:
+ (KJS::decode):
+ * kjs/ustring.cpp:
+ (KJS::UString::toDouble):
+ Use ASCIICType.h functions instead of ctype.h ones.
+
+2007-10-14 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Darin.
+
+ - fixes for "New JavaScript benchmark"
+ http://bugs.webkit.org/show_bug.cgi?id=15515
+
+ * kjs/testkjs.cpp:
+ (TestFunctionImp::callAsFunction): Implement "load" for compatibility
+ with SpiderMonkey.
+ (TestFunctionImp::): ditto
+ (doIt): ditto
+ (kjsmain): Drop useless --> from output.
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Removed unnecessary #include.
+
+ * API/JSObjectRef.cpp:
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Double-reverse build fix. My tree was out of date.
+
+ * kjs/nodes.cpp:
+ (NumberNode::evaluate):
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Build fix.
+
+ * kjs/nodes.cpp:
+ (NumberNode::evaluate):
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Removed surprising self-named "hack" that made nested functions
+ available as named properties of their containing functions, and placed
+ containing function objects in the scope chains of nested functions.
+
+ There were a few reasons to remove this "hack:"
+
+ 1. It contradicted FF, IE, and the ECMA spec.
+
+ 2. It incurred a performance penalty, since merely parsing a function
+ required parsing its body for nested functions (and so on).
+
+ 3. SVN history contains no explanation for why it was added. It was just
+ legacy code in a large merge a long, long time ago.
+
+ [ Patch broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ * kjs/nodes.cpp:
+ (FuncDeclNode::processFuncDecl):
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Removed the concept of AnonymousCode. It was unused, and it doesn't
+ exist in the ECMA spec.
+
+ [ Patch broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ * kjs/Context.cpp:
+ (KJS::Context::Context):
+ * kjs/function.h:
+ * kjs/nodes.cpp:
+ (ReturnNode::execute):
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Made function parameters DontDelete. This matches FF and the vague
+ description in ECMA 10.1.3. It's also required in order to make
+ symbol table based lookup of function parameters valid. (If the
+ parameters aren't DontDelete, you can't guarantee that you'll find
+ them later in the symbol table.)
+
+ [ Patch broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ * kjs/function.cpp:
+ (KJS::FunctionImp::passInParameters):
+
+2007-10-15 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Some Vector optimizations. These are especially important when using
+ Vector as a stack for implementing recursive algorithms iteratively.
+
+ [ Broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ 1. Added shrink(), which is a version of resize() that you can call
+ to save a branch / improve code generation and inlining when you know
+ that the vector is not getting bigger.
+
+ 2. Changed subclassing relationship in VectorBuffer to remove a call to
+ fastFree() in the destructor for the inlineCapacity != 0 template
+ specialization. This brings inline Vectors one step closer to true
+ stack-allocated arrays.
+
+ Also changed abort() to CRASH(), since the latter works better.
+
+ * wtf/Vector.h:
+ (WTF::VectorBufferBase::allocateBuffer):
+ (WTF::VectorBufferBase::deallocateBuffer):
+ (WTF::VectorBufferBase::VectorBufferBase):
+ (WTF::VectorBufferBase::~VectorBufferBase):
+ (WTF::):
+ (WTF::VectorBuffer::VectorBuffer):
+ (WTF::VectorBuffer::~VectorBuffer):
+ (WTF::VectorBuffer::deallocateBuffer):
+ (WTF::VectorBuffer::releaseBuffer):
+ (WTF::Vector::clear):
+ (WTF::Vector::removeLast):
+ (WTF::::operator):
+ (WTF::::fill):
+ (WTF::::shrink):
+
+2007-10-12 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15490
+ Iteration statements sometimes incorrectly evaluate to the empty value
+ (KDE r670547).
+
+ [ Broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]
+
+ This patch is a merge of KDE r670547, with substantial modification
+ for performance.
+
+ It fixes do-while statements to evaluate to a value. (They used
+ to evaluate to the empty value in all cases.)
+
+ It also fixes SourceElementsNode to maintain the value of abnormal
+ completions like "break" and "continue."
+
+ It also re-works the main execution loop in SourceElementsNode so that
+ it (1) makes a little more sense and (2) avoids unnecessary work. This
+ is a .28% speedup on command-line JS iBench.
+
+ * kjs/nodes.cpp:
+ (DoWhileNode::execute):
+ (SourceElementsNode::execute):
+
+2007-10-15 Simon Hausmann <hausmann@kde.org>
+
+ Reviewed by Lars.
+
+ Fix compilation with gcc 4.3 by including 'limits' due to the use of std::numeric_limits.
+
+ * wtf/HashTraits.h:
+
+2007-10-5 Kevin Ollivier <kevino@theolliviers.com>
+
+ Reviewed by Adam.
+
+ Add support for MSVC7, and fix cases where PLATFORM(WIN) should
+ be PLATFORM(WIN_OS) for other ports building on Windows.
+
+ * kjs/DateMath.cpp:
+ (KJS::getDSTOffsetSimple):
+ * kjs/JSImmediate.h:
+ * wtf/Assertions.cpp:
+ * wtf/Assertions.h:
+ * wtf/Platform.h:
+ * wtf/StringExtras.h:
+ (snprintf):
+ (vsnprintf):
+
+2007-10-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Darin.
+
+ Adds NegateNode optimization from KJS. The relevant revision in KDE
+ is 666736.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (NumberNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::Node::):
+ (KJS::NumberNode::):
+ * kjs/nodes2string.cpp:
+ (NumberNode::streamTo):
+
+2007-10-14 Jason Foreman <jason@threeve.org>
+
+ Reviewed by Maciej.
+
+ Fix http://bugs.webkit.org/show_bug.cgi?id=15145
+
+ Ensure that if adjusting n to minimize the difference of n*intPow10(e-p+1) to x,
+ that the property n < intPow10(p) is maintained.
+
+ * kjs/number_object.cpp:
+ (NumberProtoFunc::callAsFunction):
+
+== Rolled over to ChangeLog-2007-10-14 ==
-# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+# Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
VPATH = \
- $(JavaScriptCore)/kjs \
+ $(JavaScriptCore) \
+ $(JavaScriptCore)/parser \
$(JavaScriptCore)/pcre \
+ $(JavaScriptCore)/docs \
+ $(JavaScriptCore)/runtime \
+ $(JavaScriptCore)/interpreter \
+ $(JavaScriptCore)/jit \
#
.PHONY : all
all : \
- array_object.lut.h \
+ ArrayPrototype.lut.h \
chartables.c \
- date_object.lut.h \
- grammar.cpp \
- lexer.lut.h \
- math_object.lut.h \
- number_object.lut.h \
- regexp_object.lut.h \
- string_object.lut.h \
+ DatePrototype.lut.h \
+ Grammar.cpp \
+ Lexer.lut.h \
+ MathObject.lut.h \
+ NumberConstructor.lut.h \
+ RegExpConstructor.lut.h \
+ RegExpObject.lut.h \
+ StringPrototype.lut.h \
+ docs/bytecode.html \
#
# lookup tables for classes
%.lut.h: create_hash_table %.cpp
$^ -i > $@
-lexer.lut.h: create_hash_table keywords.table
+Lexer.lut.h: create_hash_table Keywords.table
$^ > $@
# JavaScript language grammar
-grammar.cpp: grammar.y
- bison -d -p kjsyy $< -o $@ > bison_out.txt 2>&1
- perl -p -e 'END { if ($$conflict) { unlink "grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
- touch grammar.cpp.h
- touch grammar.hpp
- cat grammar.cpp.h grammar.hpp > grammar.h
- rm -f grammar.cpp.h grammar.hpp bison_out.txt
+Grammar.cpp: Grammar.y
+ bison -d -p jscyy $< -o $@ > bison_out.txt 2>&1
+ perl -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
+ touch Grammar.cpp.h
+ touch Grammar.hpp
+ cat Grammar.cpp.h Grammar.hpp > Grammar.h
+ rm -f Grammar.cpp.h Grammar.hpp bison_out.txt
# character tables for PCRE
chartables.c : dftables
$^ $@
+
+docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp
+ perl $^ $@
+++ /dev/null
-#include <kjs/JSLock.h>
--- /dev/null
+#include <JavaScriptCore/API/OpaqueJSString.h>
--- /dev/null
+#include <JavaScriptCore/API/WebKitAvailability.h>
-# tell automake to create gensources/ for us
-nodist_EXTRA_libJavaScriptCore_la_SOURCES = \
- DerivedSources/dummy.cxx
-
javascriptcore_cppflags += \
+ -I$(srcdir)/JavaScriptCore/API \
-I$(srcdir)/JavaScriptCore/ForwardingHeaders \
- -I$(srcdir)/JavaScriptCore/bindings \
- -I$(srcdir)/JavaScriptCore/bindings/c \
+ -I$(srcdir)/JavaScriptCore/interpreter \
+ -I$(srcdir)/JavaScriptCore/bytecode \
+ -I$(srcdir)/JavaScriptCore/bytecompiler \
+ -I$(srcdir)/JavaScriptCore/debugger \
+ -I$(srcdir)/JavaScriptCore/jit \
+ -I$(srcdir)/JavaScriptCore/pcre \
+ -I$(srcdir)/JavaScriptCore/profiler \
+ -I$(srcdir)/JavaScriptCore/runtime \
+ -I$(srcdir)/JavaScriptCore/wrec \
+ -I$(srcdir)/JavaScriptCore/jit \
+ -I$(srcdir)/JavaScriptCore/assembler \
+ -I$(srcdir)/JavaScriptCore/wtf/unicode \
-I$(top_builddir)/JavaScriptCore/pcre \
- -I$(top_builddir)/JavaScriptCore/kjs
+ -I$(top_builddir)/JavaScriptCore/parser \
+ -I$(top_builddir)/JavaScriptCore/runtime
javascriptcore_h_api += \
- JavaScriptCore/API/JavaScript.h \
- JavaScriptCore/API/JavaScriptCore.h \
JavaScriptCore/API/JSBase.h \
JavaScriptCore/API/JSContextRef.h \
JavaScriptCore/API/JSObjectRef.h \
+ JavaScriptCore/API/JSStringRef.h \
JavaScriptCore/API/JSStringRefBSTR.h \
JavaScriptCore/API/JSStringRefCF.h \
- JavaScriptCore/API/JSStringRef.h \
- JavaScriptCore/API/JSValueRef.h
+ JavaScriptCore/API/JSValueRef.h \
+ JavaScriptCore/API/JavaScript.h \
+ JavaScriptCore/API/JavaScriptCore.h \
+ JavaScriptCore/API/WebKitAvailability.h
javascriptcore_built_nosources += \
- JavaScriptCore/kjs/array_object.lut.h \
- JavaScriptCore/kjs/date_object.lut.h \
- JavaScriptCore/kjs/math_object.lut.h \
- JavaScriptCore/kjs/number_object.lut.h \
- JavaScriptCore/kjs/regexp_object.lut.h \
- JavaScriptCore/kjs/string_object.lut.h \
- JavaScriptCore/pcre/chartables.c \
- DerivedSources/lexer.lut.h
+ DerivedSources/Lexer.lut.h \
+ JavaScriptCore/runtime/ArrayPrototype.lut.h \
+ JavaScriptCore/runtime/DatePrototype.lut.h \
+ JavaScriptCore/runtime/MathObject.lut.h \
+ JavaScriptCore/runtime/NumberConstructor.lut.h \
+ JavaScriptCore/runtime/RegExpConstructor.lut.h \
+ JavaScriptCore/runtime/RegExpObject.lut.h \
+ JavaScriptCore/runtime/StringPrototype.lut.h \
+ JavaScriptCore/pcre/chartables.c
javascriptcore_sources += \
+ JavaScriptCore/API/APICast.h \
JavaScriptCore/API/JSBase.cpp \
+ JavaScriptCore/API/JSBasePrivate.h \
JavaScriptCore/API/JSCallbackConstructor.cpp \
+ JavaScriptCore/API/JSCallbackConstructor.h \
JavaScriptCore/API/JSCallbackFunction.cpp \
+ JavaScriptCore/API/JSCallbackFunction.h \
JavaScriptCore/API/JSCallbackObject.cpp \
+ JavaScriptCore/API/JSCallbackObject.h \
+ JavaScriptCore/API/JSCallbackObjectFunctions.h \
JavaScriptCore/API/JSClassRef.cpp \
+ JavaScriptCore/API/JSClassRef.h \
JavaScriptCore/API/JSContextRef.cpp \
JavaScriptCore/API/JSObjectRef.cpp \
+ JavaScriptCore/API/JSRetainPtr.h \
JavaScriptCore/API/JSStringRef.cpp \
JavaScriptCore/API/JSValueRef.cpp \
- JavaScriptCore/bindings/NP_jsobject.cpp \
- JavaScriptCore/bindings/c/c_class.cpp \
- JavaScriptCore/bindings/c/c_instance.cpp \
- JavaScriptCore/bindings/c/c_runtime.cpp \
- JavaScriptCore/bindings/c/c_utility.cpp \
- JavaScriptCore/bindings/npruntime.cpp \
- JavaScriptCore/bindings/runtime.cpp \
- JavaScriptCore/bindings/runtime_array.cpp \
- JavaScriptCore/bindings/runtime_method.cpp \
- JavaScriptCore/bindings/runtime_object.cpp \
- JavaScriptCore/bindings/runtime_root.cpp \
- JavaScriptCore/kjs/JSGlobalObject.cpp \
- JavaScriptCore/kjs/JSVariableObject.cpp \
+ JavaScriptCore/API/OpaqueJSString.cpp \
+ JavaScriptCore/API/OpaqueJSString.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSBase.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSContextRef.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRef.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSRetainPtr.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRef.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRefCF.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSValueRef.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScript.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScriptCore.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/OpaqueJSString.h \
+ JavaScriptCore/ForwardingHeaders/JavaScriptCore/WebKitAvailability.h \
+ JavaScriptCore/JavaScriptCorePrefix.h \
+ JavaScriptCore/jit/ExecutableAllocator.h \
+ JavaScriptCore/jit/JIT.cpp \
+ JavaScriptCore/jit/JITCall.cpp \
+ JavaScriptCore/jit/JITPropertyAccess.cpp \
+ JavaScriptCore/jit/JITArithmetic.cpp \
+ JavaScriptCore/jit/ExecutableAllocator.cpp \
+ JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \
+ JavaScriptCore/jit/JIT.h \
+ JavaScriptCore/jit/JITInlineMethods.h \
+ JavaScriptCore/bytecode/StructureStubInfo.cpp \
+ JavaScriptCore/bytecode/StructureStubInfo.h \
+ JavaScriptCore/bytecode/CodeBlock.cpp \
+ JavaScriptCore/bytecode/CodeBlock.h \
+ JavaScriptCore/bytecode/JumpTable.cpp \
+ JavaScriptCore/bytecode/JumpTable.h \
+ JavaScriptCore/bytecode/EvalCodeCache.h \
+ JavaScriptCore/runtime/ExceptionHelpers.cpp \
+ JavaScriptCore/runtime/ExceptionHelpers.h \
+ JavaScriptCore/bytecode/Instruction.h \
+ JavaScriptCore/bytecompiler/Label.h \
+ JavaScriptCore/interpreter/Interpreter.cpp \
+ JavaScriptCore/interpreter/Interpreter.h \
+ JavaScriptCore/bytecode/Opcode.cpp \
+ JavaScriptCore/bytecode/Opcode.h \
+ JavaScriptCore/interpreter/Register.h \
+ JavaScriptCore/bytecompiler/RegisterID.h \
+ JavaScriptCore/bytecode/SamplingTool.cpp \
+ JavaScriptCore/bytecode/SamplingTool.h \
+ JavaScriptCore/bytecompiler/SegmentedVector.h \
+ JavaScriptCore/config.h \
+ JavaScriptCore/debugger/DebuggerActivation.cpp \
+ JavaScriptCore/debugger/DebuggerActivation.h \
+ JavaScriptCore/debugger/DebuggerCallFrame.cpp \
+ JavaScriptCore/debugger/DebuggerCallFrame.h \
+ JavaScriptCore/icu/unicode/parseerr.h \
+ JavaScriptCore/icu/unicode/platform.h \
+ JavaScriptCore/icu/unicode/putil.h \
+ JavaScriptCore/icu/unicode/uchar.h \
+ JavaScriptCore/icu/unicode/ucnv.h \
+ JavaScriptCore/icu/unicode/ucnv_err.h \
+ JavaScriptCore/icu/unicode/ucol.h \
+ JavaScriptCore/icu/unicode/uconfig.h \
+ JavaScriptCore/icu/unicode/uenum.h \
+ JavaScriptCore/icu/unicode/uiter.h \
+ JavaScriptCore/icu/unicode/uloc.h \
+ JavaScriptCore/icu/unicode/umachine.h \
+ JavaScriptCore/icu/unicode/unorm.h \
+ JavaScriptCore/icu/unicode/urename.h \
+ JavaScriptCore/icu/unicode/uset.h \
+ JavaScriptCore/icu/unicode/ustring.h \
+ JavaScriptCore/icu/unicode/utf.h \
+ JavaScriptCore/icu/unicode/utf16.h \
+ JavaScriptCore/icu/unicode/utf8.h \
+ JavaScriptCore/icu/unicode/utf_old.h \
+ JavaScriptCore/icu/unicode/utypes.h \
+ JavaScriptCore/icu/unicode/uversion.h \
+ JavaScriptCore/assembler/X86Assembler.h \
+ JavaScriptCore/assembler/AssemblerBuffer.h \
+ JavaScriptCore/assembler/MacroAssembler.h \
+ JavaScriptCore/os-win32/stdbool.h \
+ JavaScriptCore/os-win32/stdint.h \
+ JavaScriptCore/pcre/pcre.h \
JavaScriptCore/pcre/pcre_compile.cpp \
JavaScriptCore/pcre/pcre_exec.cpp \
+ JavaScriptCore/pcre/pcre_internal.h \
JavaScriptCore/pcre/pcre_tables.cpp \
JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp \
JavaScriptCore/pcre/pcre_xclass.cpp \
+ JavaScriptCore/pcre/ucpinternal.h \
+ JavaScriptCore/profiler/CallIdentifier.h \
+ JavaScriptCore/profiler/HeavyProfile.cpp \
+ JavaScriptCore/profiler/HeavyProfile.h \
+ JavaScriptCore/profiler/Profile.cpp \
+ JavaScriptCore/profiler/Profile.h \
+ JavaScriptCore/profiler/ProfileGenerator.cpp \
+ JavaScriptCore/profiler/ProfileGenerator.h \
+ JavaScriptCore/profiler/ProfileNode.cpp \
+ JavaScriptCore/profiler/ProfileNode.h \
+ JavaScriptCore/profiler/Profiler.cpp \
+ JavaScriptCore/profiler/Profiler.h \
+ JavaScriptCore/profiler/TreeProfile.cpp \
+ JavaScriptCore/profiler/TreeProfile.h \
+ JavaScriptCore/interpreter/CallFrame.cpp \
+ JavaScriptCore/interpreter/CallFrame.h \
+ JavaScriptCore/runtime/InitializeThreading.cpp \
+ JavaScriptCore/runtime/InitializeThreading.h \
+ JavaScriptCore/runtime/JSActivation.cpp \
+ JavaScriptCore/runtime/JSActivation.h \
+ JavaScriptCore/runtime/JSByteArray.cpp \
+ JavaScriptCore/runtime/JSByteArray.h \
+ JavaScriptCore/runtime/JSGlobalData.cpp \
+ JavaScriptCore/runtime/JSGlobalData.h \
+ JavaScriptCore/runtime/JSNotAnObject.cpp \
+ JavaScriptCore/runtime/JSNotAnObject.h \
+ JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
+ JavaScriptCore/runtime/JSPropertyNameIterator.h \
+ JavaScriptCore/runtime/SmallStrings.cpp \
+ JavaScriptCore/runtime/SmallStrings.h \
+ JavaScriptCore/runtime/Structure.cpp \
+ JavaScriptCore/runtime/Structure.h \
+ JavaScriptCore/runtime/StructureChain.cpp \
+ JavaScriptCore/runtime/StructureChain.h \
+ JavaScriptCore/runtime/StructureTransitionTable.h \
+ JavaScriptCore/runtime/TypeInfo.h \
+ JavaScriptCore/wrec/CharacterClass.cpp \
+ JavaScriptCore/wrec/CharacterClass.h \
+ JavaScriptCore/wrec/CharacterClassConstructor.cpp \
+ JavaScriptCore/wrec/CharacterClassConstructor.h \
+ JavaScriptCore/wrec/Escapes.h \
+ JavaScriptCore/wrec/Quantifier.h \
+ JavaScriptCore/wrec/WREC.cpp \
+ JavaScriptCore/wrec/WREC.h \
+ JavaScriptCore/wrec/WRECFunctors.cpp \
+ JavaScriptCore/wrec/WRECFunctors.h \
+ JavaScriptCore/wrec/WRECGenerator.cpp \
+ JavaScriptCore/wrec/WRECGenerator.h \
+ JavaScriptCore/wrec/WRECParser.cpp \
+ JavaScriptCore/wrec/WRECParser.h \
+ JavaScriptCore/wtf/ASCIICType.h \
+ JavaScriptCore/wtf/AVLTree.h \
+ JavaScriptCore/wtf/AlwaysInline.h \
JavaScriptCore/wtf/Assertions.cpp \
+ JavaScriptCore/wtf/Assertions.h \
+ JavaScriptCore/wtf/ByteArray.cpp \
+ JavaScriptCore/wtf/ByteArray.h \
+ JavaScriptCore/wtf/CurrentTime.cpp \
+ JavaScriptCore/wtf/CurrentTime.h \
+ JavaScriptCore/wtf/Deque.h \
+ JavaScriptCore/wtf/DisallowCType.h \
+ JavaScriptCore/wtf/Forward.h \
+ JavaScriptCore/wtf/GOwnPtr.cpp \
+ JavaScriptCore/wtf/GOwnPtr.h \
+ JavaScriptCore/wtf/GetPtr.h \
+ JavaScriptCore/wtf/HashCountedSet.h \
+ JavaScriptCore/wtf/HashFunctions.h \
+ JavaScriptCore/wtf/HashIterators.h \
+ JavaScriptCore/wtf/HashMap.h \
+ JavaScriptCore/wtf/HashSet.h \
JavaScriptCore/wtf/HashTable.cpp \
- JavaScriptCore/wtf/unicode/UTF8.cpp
+ JavaScriptCore/wtf/HashTable.h \
+ JavaScriptCore/wtf/HashTraits.h \
+ JavaScriptCore/wtf/ListHashSet.h \
+ JavaScriptCore/wtf/ListRefPtr.h \
+ JavaScriptCore/wtf/Locker.h \
+ JavaScriptCore/wtf/MainThread.cpp \
+ JavaScriptCore/wtf/MainThread.h \
+ JavaScriptCore/wtf/MathExtras.h \
+ JavaScriptCore/wtf/MessageQueue.h \
+ JavaScriptCore/wtf/Noncopyable.h \
+ JavaScriptCore/wtf/NotFound.h \
+ JavaScriptCore/wtf/OwnArrayPtr.h \
+ JavaScriptCore/wtf/OwnPtr.h \
+ JavaScriptCore/wtf/PassRefPtr.h \
+ JavaScriptCore/wtf/Platform.h \
+ JavaScriptCore/wtf/PtrAndFlags.h \
+ JavaScriptCore/wtf/RandomNumber.cpp \
+ JavaScriptCore/wtf/RandomNumber.h \
+ JavaScriptCore/wtf/RandomNumberSeed.h \
+ JavaScriptCore/wtf/RefCounted.h \
+ JavaScriptCore/wtf/RefCountedLeakCounter.cpp \
+ JavaScriptCore/wtf/RefCountedLeakCounter.h \
+ JavaScriptCore/wtf/RefPtr.h \
+ JavaScriptCore/wtf/RefPtrHashMap.h \
+ JavaScriptCore/wtf/RetainPtr.h \
+ JavaScriptCore/wtf/StdLibExtras.h \
+ JavaScriptCore/wtf/StringExtras.h \
+ JavaScriptCore/wtf/TCPackedCache.h \
+ JavaScriptCore/wtf/TCPageMap.h \
+ JavaScriptCore/wtf/TCSpinLock.h \
+ JavaScriptCore/wtf/ThreadSpecific.h \
+ JavaScriptCore/wtf/Threading.h \
+ JavaScriptCore/wtf/Threading.cpp \
+ JavaScriptCore/wtf/ThreadingGtk.cpp \
+ JavaScriptCore/wtf/ThreadingPthreads.cpp \
+ JavaScriptCore/wtf/UnusedParam.h \
+ JavaScriptCore/wtf/Vector.h \
+ JavaScriptCore/wtf/VectorTraits.h \
+ JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
+ JavaScriptCore/wtf/unicode/Collator.h \
+ JavaScriptCore/wtf/unicode/CollatorDefault.cpp \
+ JavaScriptCore/wtf/unicode/UTF8.cpp \
+ JavaScriptCore/wtf/unicode/UTF8.h \
+ JavaScriptCore/wtf/unicode/Unicode.h \
+ JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \
+ JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
# Debug build
if ENABLE_DEBUG
javascriptcore_built_sources += \
- DerivedSources/grammar.h \
- DerivedSources/grammar.cpp
+ DerivedSources/Grammar.cpp \
+ DerivedSources/Grammar.h
javascriptcore_sources += \
- JavaScriptCore/kjs/CommonIdentifiers.cpp \
- JavaScriptCore/kjs/DateMath.cpp \
- JavaScriptCore/kjs/ExecState.cpp \
- JavaScriptCore/kjs/JSImmediate.cpp \
- JavaScriptCore/kjs/JSLock.cpp \
- JavaScriptCore/kjs/JSWrapperObject.cpp \
- JavaScriptCore/kjs/Parser.cpp \
- JavaScriptCore/kjs/PropertyNameArray.cpp \
- JavaScriptCore/kjs/array_instance.cpp \
- JavaScriptCore/kjs/array_object.cpp \
- JavaScriptCore/kjs/bool_object.cpp \
- JavaScriptCore/kjs/collector.cpp \
- JavaScriptCore/kjs/date_object.cpp \
- JavaScriptCore/kjs/debugger.cpp \
- JavaScriptCore/kjs/dtoa.cpp \
- JavaScriptCore/kjs/error_object.cpp \
- JavaScriptCore/kjs/function.cpp \
- JavaScriptCore/kjs/function_object.cpp \
- JavaScriptCore/kjs/identifier.cpp \
- JavaScriptCore/kjs/internal.cpp \
- JavaScriptCore/kjs/interpreter.cpp \
- JavaScriptCore/kjs/lexer.cpp \
- JavaScriptCore/kjs/list.cpp \
- JavaScriptCore/kjs/lookup.cpp \
- JavaScriptCore/kjs/math_object.cpp \
- JavaScriptCore/kjs/nodes.cpp \
- JavaScriptCore/kjs/nodes2string.cpp \
- JavaScriptCore/kjs/number_object.cpp \
- JavaScriptCore/kjs/object.cpp \
- JavaScriptCore/kjs/object_object.cpp \
- JavaScriptCore/kjs/operations.cpp \
- JavaScriptCore/kjs/property_map.cpp \
- JavaScriptCore/kjs/property_slot.cpp \
- JavaScriptCore/kjs/regexp.cpp \
- JavaScriptCore/kjs/regexp_object.cpp \
- JavaScriptCore/kjs/scope_chain.cpp \
- JavaScriptCore/kjs/string_object.cpp \
- JavaScriptCore/kjs/ustring.cpp \
- JavaScriptCore/kjs/value.cpp \
+ JavaScriptCore/interpreter/RegisterFile.cpp \
+ JavaScriptCore/interpreter/RegisterFile.h \
+ JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
+ JavaScriptCore/bytecompiler/BytecodeGenerator.h \
+ JavaScriptCore/bytecompiler/LabelScope.h \
+ JavaScriptCore/debugger/Debugger.cpp \
+ JavaScriptCore/debugger/Debugger.h \
+ JavaScriptCore/parser/Lexer.cpp \
+ JavaScriptCore/parser/Lexer.h \
+ JavaScriptCore/parser/NodeInfo.h \
+ JavaScriptCore/parser/Nodes.cpp \
+ JavaScriptCore/parser/Nodes.h \
+ JavaScriptCore/parser/Parser.cpp \
+ JavaScriptCore/parser/Parser.h \
+ JavaScriptCore/parser/ResultType.h \
+ JavaScriptCore/parser/SourceCode.h \
+ JavaScriptCore/parser/SourceProvider.h \
+ JavaScriptCore/runtime/ArgList.cpp \
+ JavaScriptCore/runtime/ArgList.h \
+ JavaScriptCore/runtime/Arguments.cpp \
+ JavaScriptCore/runtime/Arguments.h \
+ JavaScriptCore/runtime/ArrayConstructor.cpp \
+ JavaScriptCore/runtime/ArrayConstructor.h \
+ JavaScriptCore/runtime/ArrayPrototype.cpp \
+ JavaScriptCore/runtime/ArrayPrototype.h \
+ JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
+ JavaScriptCore/runtime/BooleanConstructor.cpp \
+ JavaScriptCore/runtime/BooleanConstructor.h \
+ JavaScriptCore/runtime/BooleanObject.cpp \
+ JavaScriptCore/runtime/BooleanObject.h \
+ JavaScriptCore/runtime/BooleanPrototype.cpp \
+ JavaScriptCore/runtime/BooleanPrototype.h \
+ JavaScriptCore/runtime/CallData.cpp \
+ JavaScriptCore/runtime/CallData.h \
+ JavaScriptCore/runtime/ClassInfo.h \
+ JavaScriptCore/runtime/Collector.cpp \
+ JavaScriptCore/runtime/Collector.h \
+ JavaScriptCore/runtime/CollectorHeapIterator.h \
+ JavaScriptCore/runtime/CommonIdentifiers.cpp \
+ JavaScriptCore/runtime/CommonIdentifiers.h \
+ JavaScriptCore/runtime/Completion.h \
+ JavaScriptCore/runtime/ConstructData.cpp \
+ JavaScriptCore/runtime/ConstructData.h \
+ JavaScriptCore/runtime/DateConstructor.cpp \
+ JavaScriptCore/runtime/DateConstructor.h \
+ JavaScriptCore/runtime/DateInstance.cpp \
+ JavaScriptCore/runtime/DateInstance.h \
+ JavaScriptCore/runtime/DateMath.cpp \
+ JavaScriptCore/runtime/DateMath.h \
+ JavaScriptCore/runtime/DatePrototype.cpp \
+ JavaScriptCore/runtime/DatePrototype.h \
+ JavaScriptCore/runtime/Error.cpp \
+ JavaScriptCore/runtime/Error.h \
+ JavaScriptCore/runtime/ErrorConstructor.cpp \
+ JavaScriptCore/runtime/ErrorConstructor.h \
+ JavaScriptCore/runtime/ErrorInstance.cpp \
+ JavaScriptCore/runtime/ErrorInstance.h \
+ JavaScriptCore/runtime/ErrorPrototype.cpp \
+ JavaScriptCore/runtime/ErrorPrototype.h \
+ JavaScriptCore/runtime/FunctionConstructor.cpp \
+ JavaScriptCore/runtime/FunctionConstructor.h \
+ JavaScriptCore/runtime/FunctionPrototype.cpp \
+ JavaScriptCore/runtime/FunctionPrototype.h \
+ JavaScriptCore/runtime/GetterSetter.cpp \
+ JavaScriptCore/runtime/GetterSetter.h \
+ JavaScriptCore/runtime/GlobalEvalFunction.cpp \
+ JavaScriptCore/runtime/GlobalEvalFunction.h \
+ JavaScriptCore/runtime/Identifier.cpp \
+ JavaScriptCore/runtime/Identifier.h \
+ JavaScriptCore/runtime/InternalFunction.cpp \
+ JavaScriptCore/runtime/InternalFunction.h \
+ JavaScriptCore/runtime/Completion.cpp \
+ JavaScriptCore/runtime/JSArray.cpp \
+ JavaScriptCore/runtime/JSArray.h \
+ JavaScriptCore/runtime/JSCell.cpp \
+ JavaScriptCore/runtime/JSCell.h \
+ JavaScriptCore/runtime/JSFunction.cpp \
+ JavaScriptCore/runtime/JSFunction.h \
+ JavaScriptCore/runtime/JSGlobalObject.cpp \
+ JavaScriptCore/runtime/JSGlobalObject.h \
+ JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp \
+ JavaScriptCore/runtime/JSGlobalObjectFunctions.h \
+ JavaScriptCore/runtime/JSImmediate.cpp \
+ JavaScriptCore/runtime/JSImmediate.h \
+ JavaScriptCore/runtime/JSLock.cpp \
+ JavaScriptCore/runtime/JSLock.h \
+ JavaScriptCore/runtime/JSNumberCell.cpp \
+ JavaScriptCore/runtime/JSNumberCell.h \
+ JavaScriptCore/runtime/JSObject.cpp \
+ JavaScriptCore/runtime/JSObject.h \
+ JavaScriptCore/runtime/JSStaticScopeObject.cpp \
+ JavaScriptCore/runtime/JSStaticScopeObject.h \
+ JavaScriptCore/runtime/JSString.cpp \
+ JavaScriptCore/runtime/JSString.h \
+ JavaScriptCore/runtime/JSType.h \
+ JavaScriptCore/runtime/JSValue.cpp \
+ JavaScriptCore/runtime/JSValue.h \
+ JavaScriptCore/runtime/JSVariableObject.cpp \
+ JavaScriptCore/runtime/JSVariableObject.h \
+ JavaScriptCore/runtime/JSWrapperObject.cpp \
+ JavaScriptCore/runtime/JSWrapperObject.h \
+ JavaScriptCore/runtime/Lookup.cpp \
+ JavaScriptCore/runtime/Lookup.h \
+ JavaScriptCore/runtime/MathObject.cpp \
+ JavaScriptCore/runtime/MathObject.h \
+ JavaScriptCore/runtime/NativeErrorConstructor.cpp \
+ JavaScriptCore/runtime/NativeErrorConstructor.h \
+ JavaScriptCore/runtime/NativeErrorPrototype.cpp \
+ JavaScriptCore/runtime/NativeErrorPrototype.h \
+ JavaScriptCore/runtime/NumberConstructor.cpp \
+ JavaScriptCore/runtime/NumberConstructor.h \
+ JavaScriptCore/runtime/NumberObject.cpp \
+ JavaScriptCore/runtime/NumberObject.h \
+ JavaScriptCore/runtime/NumberPrototype.cpp \
+ JavaScriptCore/runtime/NumberPrototype.h \
+ JavaScriptCore/runtime/ObjectConstructor.cpp \
+ JavaScriptCore/runtime/ObjectConstructor.h \
+ JavaScriptCore/runtime/ObjectPrototype.cpp \
+ JavaScriptCore/runtime/ObjectPrototype.h \
+ JavaScriptCore/runtime/Operations.cpp \
+ JavaScriptCore/runtime/Operations.h \
+ JavaScriptCore/runtime/PropertyMapHashTable.h \
+ JavaScriptCore/runtime/PropertyNameArray.cpp \
+ JavaScriptCore/runtime/PropertyNameArray.h \
+ JavaScriptCore/runtime/PropertySlot.cpp \
+ JavaScriptCore/runtime/PropertySlot.h \
+ JavaScriptCore/runtime/Protect.h \
+ JavaScriptCore/runtime/PrototypeFunction.cpp \
+ JavaScriptCore/runtime/PrototypeFunction.h \
+ JavaScriptCore/runtime/PutPropertySlot.h \
+ JavaScriptCore/runtime/RegExp.cpp \
+ JavaScriptCore/runtime/RegExp.h \
+ JavaScriptCore/runtime/RegExpConstructor.cpp \
+ JavaScriptCore/runtime/RegExpConstructor.h \
+ JavaScriptCore/runtime/RegExpMatchesArray.h \
+ JavaScriptCore/runtime/RegExpObject.cpp \
+ JavaScriptCore/runtime/RegExpObject.h \
+ JavaScriptCore/runtime/RegExpPrototype.cpp \
+ JavaScriptCore/runtime/RegExpPrototype.h \
+ JavaScriptCore/runtime/ScopeChain.cpp \
+ JavaScriptCore/runtime/ScopeChain.h \
+ JavaScriptCore/runtime/ScopeChainMark.h \
+ JavaScriptCore/runtime/StringConstructor.cpp \
+ JavaScriptCore/runtime/StringConstructor.h \
+ JavaScriptCore/runtime/StringObject.cpp \
+ JavaScriptCore/runtime/StringObject.h \
+ JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h \
+ JavaScriptCore/runtime/StringPrototype.cpp \
+ JavaScriptCore/runtime/StringPrototype.h \
+ JavaScriptCore/runtime/SymbolTable.h \
+ JavaScriptCore/runtime/Tracing.h \
+ JavaScriptCore/runtime/UString.cpp \
+ JavaScriptCore/runtime/UString.h \
JavaScriptCore/wtf/FastMalloc.cpp \
- JavaScriptCore/wtf/TCSystemAlloc.cpp
+ JavaScriptCore/wtf/FastMalloc.h \
+ JavaScriptCore/wtf/MallocZoneSupport.h \
+ JavaScriptCore/wtf/TCSystemAlloc.cpp \
+ JavaScriptCore/wtf/TCSystemAlloc.h \
+ JavaScriptCore/wtf/dtoa.cpp \
+ JavaScriptCore/wtf/dtoa.h
else
javascriptcore_built_nosources += \
- DerivedSources/grammar.h \
- DerivedSources/grammar.cpp
+ DerivedSources/Grammar.cpp \
+ DerivedSources/Grammar.h
javascriptcore_sources += \
- JavaScriptCore/kjs/AllInOneFile.cpp
+ JavaScriptCore/AllInOneFile.cpp
endif # END ENABLE_DEBUG
-DerivedSources/grammar.h: DerivedSources/grammar.cpp;
+DerivedSources/Grammar.h: DerivedSources/Grammar.cpp;
-DerivedSources/grammar.cpp: $(srcdir)/JavaScriptCore/kjs/grammar.y
- $(BISON) -d -p kjsyy $(srcdir)/JavaScriptCore/kjs/grammar.y -o $@ > bison_out.txt 2>&1
- $(PERL) -p -e 'END { if ($$conflict) { unlink "grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
- cat $(GENSOURCES)/grammar.hpp > $(GENSOURCES)/grammar.h
- rm -f $(GENSOURCES)/grammar.hpp bison_out.txt
+DerivedSources/Grammar.cpp: $(srcdir)/JavaScriptCore/parser/Grammar.y
+ $(BISON) -d -p jscyy $(srcdir)/JavaScriptCore/parser/Grammar.y -o $@ > bison_out.txt 2>&1
+ $(PERL) -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
+ cat $(GENSOURCES)/Grammar.hpp > $(GENSOURCES)/Grammar.h
+ rm -f $(GENSOURCES)/Grammar.hpp bison_out.txt
-DerivedSources/lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/kjs/keywords.table
+DerivedSources/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser/Keywords.table
$(PERL) $^ > $@
-%_object.lut.h: $(CREATE_HASH_TABLE) %_object.cpp
- $^ -i > $@
+JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp
+ $(PERL) $^ -i > $@
JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables
- $^ $@
+ $(PERL) $^ $@
+
+bin_PROGRAMS += \
+ Programs/jsc
noinst_PROGRAMS += \
- Programs/minidom \
- Programs/testkjs
+ Programs/minidom
# minidom
Programs_minidom_SOURCES = \
- JavaScriptCore/API/JSNode.c \
- JavaScriptCore/API/JSNodeList.c \
- JavaScriptCore/API/Node.c \
- JavaScriptCore/API/NodeList.c \
- JavaScriptCore/API/minidom.c
-Programs_minidom_CPPFLAGS = $(global_cppflags)
-Programs_minidom_CXXFLAGS = $(global_cxxflags) $(global_cflags)
-Programs_minidom_LDADD = libJavaScriptCore.la
-Programs_minidom_LDFLAGS = -rpath $(CURDIR)/.libs
-
-# testkjs
-Programs_testkjs_SOURCES = JavaScriptCore/kjs/testkjs.cpp
-Programs_testkjs_CPPFLAGS = $(global_cppflags)
-Programs_testkjs_CXXFLAGS = $(global_cxxflags) $(global_cflags)
-Programs_testkjs_LDADD = libJavaScriptCore.la
-Programs_testkjs_LDFLAGS = -rpath $(CURDIR)/.libs
+ JavaScriptCore/API/tests/JSNode.c \
+ JavaScriptCore/API/tests/JSNode.h \
+ JavaScriptCore/API/tests/JSNodeList.c \
+ JavaScriptCore/API/tests/JSNodeList.h \
+ JavaScriptCore/API/tests/Node.c \
+ JavaScriptCore/API/tests/Node.h \
+ JavaScriptCore/API/tests/NodeList.c \
+ JavaScriptCore/API/tests/NodeList.h \
+ JavaScriptCore/API/tests/minidom.c
+
+Programs_minidom_CPPFLAGS = \
+ $(global_cppflags) \
+ $(javascriptcore_cppflags)
+
+Programs_minidom_CFLAGS = \
+ -ansi \
+ -fno-strict-aliasing \
+ -O2 \
+ $(global_cflags) \
+ $(GLOBALDEPS_CFLAGS)
+
+Programs_minidom_LDADD = \
+ libJavaScriptCore.la \
+ -lm \
+ -lstdc++
+
+# jsc
+Programs_jsc_SOURCES = \
+ JavaScriptCore/jsc.cpp
+
+Programs_jsc_CPPFLAGS = \
+ $(global_cppflags) \
+ $(javascriptcore_cppflags)
+
+Programs_jsc_CXXFLAGS = \
+ -fno-strict-aliasing \
+ -O2 \
+ $(global_cxxflags) \
+ $(global_cflags) \
+ $(GLOBALDEPS_CFLAGS) \
+ $(UNICODE_CFLAGS)
+
+Programs_jsc_LDADD = \
+ libJavaScriptCore.la
+
+javascriptcore_dist += \
+ $(CREATE_HASH_TABLE) \
+ JavaScriptCore/AUTHORS \
+ JavaScriptCore/COPYING.LIB \
+ JavaScriptCore/ChangeLog \
+ JavaScriptCore/THANKS \
+ JavaScriptCore/icu/LICENSE \
+ JavaScriptCore/icu/README \
+ JavaScriptCore/pcre/COPYING \
+ JavaScriptCore/pcre/AUTHORS \
+ JavaScriptCore/pcre/dftables \
+ JavaScriptCore/pcre/ucptable.cpp \
+ JavaScriptCore/parser/Grammar.y \
+ JavaScriptCore/parser/Keywords.table
# Clean rules for JavaScriptCore
CLEANFILES += \
- JavaScriptCore/kjs/array_object.lut.h \
- JavaScriptCore/kjs/date_object.lut.h \
- JavaScriptCore/kjs/math_object.lut.h \
- JavaScriptCore/kjs/number_object.lut.h \
- JavaScriptCore/kjs/regexp_object.lut.h \
- JavaScriptCore/kjs/string_object.lut.h \
- JavaScriptCore/pcre/chartables.c
+ JavaScriptCore/runtime/ArrayPrototype.lut.h \
+ JavaScriptCore/runtime/DatePrototype.lut.h \
+ JavaScriptCore/runtime/MathObject.lut.h \
+ JavaScriptCore/runtime/NumberConstructor.lut.h \
+ JavaScriptCore/runtime/RegExpConstructor.lut.h \
+ JavaScriptCore/runtime/RegExpObject.lut.h \
+ JavaScriptCore/runtime/StringPrototype.lut.h \
+ JavaScriptCore/pcre/chartables.c \
+ Programs/jsc \
+ Programs/minidom
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleGetInfoString</key>
- <string>${BUNDLE_VERSION}, Copyright 2003-2007 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
+ <string>${BUNDLE_VERSION}, Copyright 2003-2009 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
<key>CFBundleIdentifier</key>
<string>com.apple.${PRODUCT_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>${BUNDLE_VERSION}</string>
+ <string>${SHORT_VERSION_STRING}</string>
<key>CFBundleVersion</key>
<string>${BUNDLE_VERSION}</string>
</dict>
_JSClassRelease
_JSClassRetain
_JSContextGetGlobalObject
+_JSContextGetGroup
+_JSContextGroupCreate
+_JSContextGroupRelease
+_JSContextGroupRetain
+_JSEndProfiling
_JSEvaluateScript
_JSGarbageCollect
_JSGlobalContextCreate
+_JSGlobalContextCreateInGroup
_JSGlobalContextRelease
_JSGlobalContextRetain
_JSObjectCallAsConstructor
_JSObjectIsConstructor
_JSObjectIsFunction
_JSObjectMake
+_JSObjectMakeArray
_JSObjectMakeConstructor
+_JSObjectMakeDate
+_JSObjectMakeError
_JSObjectMakeFunction
_JSObjectMakeFunctionWithCallback
+_JSObjectMakeRegExp
_JSObjectSetPrivate
_JSObjectSetProperty
_JSObjectSetPropertyAtIndex
_JSPropertyNameArrayGetNameAtIndex
_JSPropertyNameArrayRelease
_JSPropertyNameArrayRetain
+_JSReportExtraMemoryCost
+_JSStartProfiling
_JSStringCopyCFString
_JSStringCreateWithCFString
_JSStringCreateWithCharacters
_WTFReportAssertionFailureWithMessage
_WTFReportError
_WTFReportFatalError
-#__NPN_CreateObject
-#__NPN_DeallocateObject
-#__NPN_Enumerate
-#__NPN_Evaluate
-#__NPN_GetIntIdentifier
-#__NPN_GetProperty
-#__NPN_GetStringIdentifier
-#__NPN_GetStringIdentifiers
-#__NPN_IdentifierIsString
-#__NPN_Invoke
-#__NPN_InvokeDefault
-#__NPN_ReleaseObject
-#__NPN_ReleaseVariantValue
-#__NPN_RemoveProperty
-#__NPN_RetainObject
-#__NPN_SetException
-#__NPN_SetProperty
-#__NPN_UTF8FromIdentifier
__Z12jsRegExpFreeP8JSRegExp
__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
-#__Z23_NPN_CreateScriptObjectP4_NPPPN3KJS8JSObjectEN3WTF10PassRefPtrINS1_8Bindings10RootObjectEEE
-#__Z25_NPN_CreateNoScriptObjectv
-__ZN3KJS10Identifier11addSlowCaseEPNS_7UString3RepE
-__ZN3KJS10Identifier3addEPKNS_5UCharEi
-__ZN3KJS10Identifier3addEPKc
-__ZN3KJS10Identifier5equalEPKNS_7UString3RepEPKc
-__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
-__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3KJS11Interpreter11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
-__ZN3KJS11Interpreter21shouldPrintExceptionsEv
-__ZN3KJS11Interpreter24setShouldPrintExceptionsEb
-__ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE
-__ZN3KJS11JSImmediate4typeEPKNS_7JSValueE
-__ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE
-__ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE
-__ZN3KJS11ProgramNode6createERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS7_IPNS_12FuncDeclNodeELm16EEE
-__ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE
-__ZN3KJS11PropertyMap5clearEv
-__ZN3KJS11PropertyMap7restoreERKNS_15SavedPropertiesE
-__ZN3KJS11PropertyMapD1Ev
-__ZN3KJS12DateInstance4infoE
-__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_
-__ZN3KJS12jsNumberCellEd
-__ZN3KJS13ArrayInstance4infoE
-__ZN3KJS13StatementNode6setLocEii
-__ZN3KJS13jsOwnedStringERKNS_7UStringE
-__ZN3KJS14JSGlobalObject10globalExecEv
-__ZN3KJS14JSGlobalObject15restoreBuiltinsERKNS_13SavedBuiltinsE
-__ZN3KJS14JSGlobalObject16stopTimeoutCheckEv
-__ZN3KJS14JSGlobalObject17startTimeoutCheckEv
-__ZN3KJS14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS14JSGlobalObject4initEv
-__ZN3KJS14JSGlobalObject4markEv
-__ZN3KJS14JSGlobalObject5resetEPNS_7JSValueE
-__ZN3KJS14JSGlobalObject6s_headE
-__ZN3KJS14JSGlobalObjectD2Ev
-__ZN3KJS14StringInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS14StringInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS14StringInstance4infoE
-__ZN3KJS14StringInstanceC1EPNS_8JSObjectERKNS_7UStringE
-__ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE
-__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectE
-__ZN3KJS15JSWrapperObject4markEv
-__ZN3KJS15SavedPropertiesC1Ev
-__ZN3KJS15SavedPropertiesD1Ev
-__ZN3KJS16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS16JSVariableObject19restoreLocalStorageERKNS_15SavedPropertiesE
-__ZN3KJS16ParserRefCounted3refEv
-__ZN3KJS16ParserRefCounted5derefEv
-__ZN3KJS16RuntimeObjectImp4infoE
-__ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE
-__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE
-__ZN3KJS19InternalFunctionImp4infoE
-__ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE
-__ZN3KJS23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS4List15expandAndAppendEPNS_7JSValueE
-__ZN3KJS4List7markSetEv
-__ZN3KJS6JSCell9getObjectEv
-__ZN3KJS6JSCellnwEm
-__ZN3KJS6JSLock12DropAllLocksC1Ev
-__ZN3KJS6JSLock12DropAllLocksD1Ev
-__ZN3KJS6JSLock14registerThreadEv
-__ZN3KJS6JSLock4lockEv
-__ZN3KJS6JSLock6unlockEv
-__ZN3KJS6JSLock9lockCountEv
-__ZN3KJS6Lookup9findEntryEPKNS_9HashTableERKNS_10IdentifierE
-__ZN3KJS6Parser5parseEPiPNS_7UStringE
-__ZN3KJS6parserEv
-__ZN3KJS7CStringD1Ev
-__ZN3KJS7UString3Rep4nullE
-__ZN3KJS7UString3Rep7destroyEv
-__ZN3KJS7UString4fromEj
-__ZN3KJS7UString6appendERKS0_
-__ZN3KJS7UStringC1EPKNS_5UCharEi
-__ZN3KJS7UStringC1EPKc
-__ZN3KJS7UStringC1ERKS0_S2_
-__ZN3KJS7UStringaSEPKc
-__ZN3KJS8Bindings10RootObject10invalidateEv
-__ZN3KJS8Bindings10RootObject11gcUnprotectEPNS_8JSObjectE
-__ZN3KJS8Bindings10RootObject17_createRootObjectE
-__ZN3KJS8Bindings10RootObject19setCreateRootObjectEPFN3WTF10PassRefPtrIS1_EEPvE
-__ZN3KJS8Bindings10RootObject6createEPKvPNS_14JSGlobalObjectE
-__ZN3KJS8Bindings10RootObject9gcProtectEPNS_8JSObjectE
-__ZN3KJS8Bindings10RootObjectD1Ev
-__ZN3KJS8Bindings10throwErrorEPNS_9ExecStateENS_9ErrorTypeEP8NSString
-__ZN3KJS8Bindings23convertObjcValueToValueEPNS_9ExecStateEPvNS0_13ObjcValueTypeEPNS0_10RootObjectE
-__ZN3KJS8Bindings23convertValueToObjcValueEPNS_9ExecStateEPNS_7JSValueENS0_13ObjcValueTypeE
-__ZN3KJS8Bindings24findProtectingRootObjectEPNS_8JSObjectE
-__ZN3KJS8Bindings8Instance18didExecuteFunctionEv
-__ZN3KJS8Bindings8Instance19createRuntimeObjectEPS1_
-__ZN3KJS8Bindings8Instance21setDidExecuteFunctionEPFvPNS_9ExecStateEPNS_8JSObjectEE
-__ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Debugger6attachEPNS_14JSGlobalObjectE
-__ZN3KJS8Debugger12sourceUnusedEPNS_9ExecStateEl
-__ZN3KJS8DebuggerC2Ev
-__ZN3KJS8DebuggerD2Ev
-__ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
-__ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE
-__ZN3KJS8JSObject14callAsFunctionEPNS_9ExecStateEPS0_RKNS_4ListE
-__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZN3KJS8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
-__ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE
-__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS8JSObject3putEPNS_9ExecStateEjPNS_7JSValueEi
-__ZN3KJS8JSObject4callEPNS_9ExecStateEPS0_RKNS_4ListE
-__ZN3KJS8JSObject4markEv
-__ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEii
-__ZN3KJS8jsStringEPKc
-__ZN3KJS8jsStringERKNS_7UStringE
-__ZN3KJS9Collector15recordExtraCostEm
-__ZN3KJS9Collector17globalObjectCountEv
-__ZN3KJS9Collector20protectedObjectCountEv
-__ZN3KJS9Collector23collectOnMainThreadOnlyEPNS_7JSValueE
-__ZN3KJS9Collector25protectedObjectTypeCountsEv
-__ZN3KJS9Collector26protectedGlobalObjectCountEv
-__ZN3KJS9Collector4sizeEv
-__ZN3KJS9Collector7collectEv
-__ZN3KJS9Collector7protectEPNS_7JSValueE
-__ZN3KJS9Collector9unprotectEPNS_7JSValueE
-__ZN3KJS9ExecState16activeExecStatesEv
-__ZN3KJSeqERKNS_7UStringEPKc
+__ZN14OpaqueJSString6createERKN3JSC7UStringE
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
+__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_7UString3RepE
+__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_7UString3RepE
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
+__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
+__ZN3JSC10JSFunction4infoE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
+__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC11JSImmediate12nonInlineNaNEv
+__ZN3JSC11JSImmediate8toObjectENS_10JSValuePtrEPNS_9ExecStateE
+__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE
+__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE
+__ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E
+__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
+__ZN3JSC12DateInstance4infoE
+__ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3JSC12JSGlobalData12createLeakedEv
+__ZN3JSC12JSGlobalData14sharedInstanceEv
+__ZN3JSC12JSGlobalData6createEv
+__ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12SamplingTool13notifyOfScopeEPNS_9ScopeNodeE
+__ZN3JSC12SamplingTool4dumpEPNS_9ExecStateE
+__ZN3JSC12SamplingTool4stopEv
+__ZN3JSC12SamplingTool5startEj
+__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
+__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC12StringObject4infoE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE
+__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSC13StatementNode6setLocEii
+__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC14JSGlobalObject10globalExecEv
+__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject14setTimeoutTimeEj
+__ZN3JSC14JSGlobalObject16stopTimeoutCheckEv
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj
+__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject4markEv
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
+__ZN3JSC16FunctionBodyNode14copyParametersEv
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC16InternalFunction4infoE
+__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC16ParserRefCounted3refEv
+__ZN3JSC16ParserRefCounted5derefEv
+__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
+__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectES6_RKNS_7ArgListEE
+__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
+__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZN3JSC19initializeThreadingEv
+__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_10JSValuePtrEPNS_14JSGlobalObjectE
+__ZN3JSC4Heap11objectCountEv
+__ZN3JSC4Heap14allocateNumberEm
+__ZN3JSC4Heap14primaryHeapEndEv
+__ZN3JSC4Heap15recordExtraCostEm
+__ZN3JSC4Heap16primaryHeapBeginEv
+__ZN3JSC4Heap17globalObjectCountEv
+__ZN3JSC4Heap20protectedObjectCountEv
+__ZN3JSC4Heap24setGCProtectNeedsLockingEv
+__ZN3JSC4Heap25protectedObjectTypeCountsEv
+__ZN3JSC4Heap26protectedGlobalObjectCountEv
+__ZN3JSC4Heap4heapENS_10JSValuePtrE
+__ZN3JSC4Heap6isBusyEv
+__ZN3JSC4Heap7collectEv
+__ZN3JSC4Heap7destroyEv
+__ZN3JSC4Heap7protectENS_10JSValuePtrE
+__ZN3JSC4Heap8allocateEm
+__ZN3JSC4Heap9unprotectENS_10JSValuePtrE
+__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3JSC6JSCell11getJSNumberEv
+__ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
+__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC6JSCell9getObjectEv
+__ZN3JSC6JSCellnwEmPNS_9ExecStateE
+__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
+__ZN3JSC6JSLock12DropAllLocksC1Eb
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSC6JSLock4lockEb
+__ZN3JSC6JSLock6unlockEb
+__ZN3JSC6JSLock9lockCountEv
+__ZN3JSC6JSLockC1EPNS_9ExecStateE
+__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
+__ZN3JSC7ArgList10slowAppendENS_10JSValuePtrE
+__ZN3JSC7CStringD1Ev
+__ZN3JSC7CStringaSERKS0_
+__ZN3JSC7JSArray4infoE
+__ZN3JSC7Profile10restoreAllEv
+__ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
+__ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
+__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
+__ZN3JSC7UString3Rep11computeHashEPKti
+__ZN3JSC7UString3Rep14nullBaseStringE
+__ZN3JSC7UString3Rep7destroyEv
+__ZN3JSC7UString4fromEi
+__ZN3JSC7UString4fromEj
+__ZN3JSC7UString6appendEPKc
+__ZN3JSC7UString6appendERKS0_
+__ZN3JSC7UStringC1EPKc
+__ZN3JSC7UStringC1EPKti
+__ZN3JSC7UStringaSEPKc
+__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
+__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
+__ZN3JSC8DebuggerC2Ev
+__ZN3JSC8DebuggerD2Ev
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_10JSValuePtrES3_
+__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC8JSObject15unwrappedObjectEv
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC8JSObject17createInheritorIDEv
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_10JSValuePtrEj
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_10JSValuePtrE
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC8JSObject4markEv
+__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC8Profiler8profilerEv
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC9CodeBlockD1Ev
+__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC9Structure17stopIgnoringLeaksEv
+__ZN3JSC9Structure18startIgnoringLeaksEv
+__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure22materializePropertyMapEv
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE
+__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj
+__ZN3JSC9Structure3getERKNS_10IdentifierERj
+__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE
+__ZN3JSC9StructureD1Ev
+__ZN3JSC9constructEPNS_9ExecStateENS_10JSValuePtrENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+__ZN3JSCeqERKNS_7UStringEPKc
+__ZN3JSCeqERKNS_7UStringES2_
+__ZN3JSCgtERKNS_7UStringES2_
+__ZN3JSCltERKNS_7UStringES2_
__ZN3WTF10fastCallocEmm
__ZN3WTF10fastMallocEm
+__ZN3WTF11currentTimeEv
__ZN3WTF11fastReallocEPvm
+__ZN3WTF12createThreadEPFPvS0_ES0_
+__ZN3WTF12createThreadEPFPvS0_ES0_PKc
+__ZN3WTF12detachThreadEj
+__ZN3WTF12isMainThreadEv
+__ZN3WTF12randomNumberEv
+__ZN3WTF13currentThreadEv
+__ZN3WTF13tryFastCallocEmm
+__ZN3WTF15ThreadCondition4waitERNS_5MutexE
+__ZN3WTF15ThreadCondition6signalEv
+__ZN3WTF15ThreadCondition9broadcastEv
+__ZN3WTF15ThreadConditionC1Ev
+__ZN3WTF15ThreadConditionD1Ev
+__ZN3WTF16callOnMainThreadEPFvPvES0_
__ZN3WTF16fastZeroedMallocEm
+__ZN3WTF19initializeThreadingEv
+__ZN3WTF20fastMallocStatisticsEv
+__ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
+__ZN3WTF21RefCountedLeakCounter24cancelMessageSuppressionEPKc
+__ZN3WTF21RefCountedLeakCounter9decrementEv
+__ZN3WTF21RefCountedLeakCounter9incrementEv
+__ZN3WTF21RefCountedLeakCounterC1EPKc
+__ZN3WTF21RefCountedLeakCounterD1Ev
+__ZN3WTF23waitForThreadCompletionEjPPv
__ZN3WTF27releaseFastMallocFreeMemoryEv
+__ZN3WTF28setMainThreadCallbacksPausedEb
+__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3WTF5Mutex4lockEv
+__ZN3WTF5Mutex6unlockEv
+__ZN3WTF5Mutex7tryLockEv
+__ZN3WTF5MutexC1Ev
+__ZN3WTF5MutexD1Ev
+__ZN3WTF6strtodEPKcPPc
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3WTF8Collator18setOrderLowerFirstEb
+__ZN3WTF8CollatorC1EPKc
+__ZN3WTF8CollatorD1Ev
__ZN3WTF8fastFreeEPv
-__ZNK3KJS11PropertyMap3getERKNS_10IdentifierE
-__ZNK3KJS11PropertyMap4saveERNS_15SavedPropertiesE
-__ZNK3KJS12DateInstance7getTimeERdRi
-__ZNK3KJS13ArrayInstance7getItemEj
-__ZNK3KJS14JSGlobalObject12saveBuiltinsERNS_13SavedBuiltinsE
-__ZNK3KJS16JSVariableObject16saveLocalStorageERNS_15SavedPropertiesE
-__ZNK3KJS19InternalFunctionImp14implementsCallEv
-__ZNK3KJS19InternalFunctionImp21implementsHasInstanceEv
-__ZNK3KJS4List8getSliceEiRS0_
-__ZN3KJS4Node8toStringEv
-__ZNK3KJS6JSCell17getTruncatedInt32ERi
-__ZNK3KJS6JSCell18getTruncatedUInt32ERj
-__ZNK3KJS6JSCell9getNumberERd
-__ZNK3KJS6JSCell9getNumberEv
-__ZNK3KJS6JSCell9getStringERNS_7UStringE
-__ZNK3KJS6JSCell9getStringEv
-__ZNK3KJS6JSCell9getUInt32ERj
-__ZNK3KJS7JSValue15toInt32SlowCaseEPNS_9ExecStateERb
-__ZNK3KJS7JSValue16toUInt32SlowCaseEPNS_9ExecStateERb
-__ZNK3KJS7JSValue7toFloatEPNS_9ExecStateE
-__ZNK3KJS7JSValue9toIntegerEPNS_9ExecStateE
-__ZNK3KJS7UString10UTF8StringEb
-__ZNK3KJS7UString14toStrictUInt32EPb
-__ZNK3KJS7UString5asciiEv
-__ZNK3KJS7UString6is8BitEv
-__ZNK3KJS7UString6substrEii
-__ZNK3KJS7UString8toUInt32EPb
-__ZNK3KJS7UString8toUInt32EPbb
-__ZNK3KJS8Bindings10RootObject12globalObjectEv
-__ZNK3KJS8Bindings8Instance10rootObjectEv
-__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
-__ZNK3KJS8JSObject14implementsCallEv
-__ZNK3KJS8JSObject19implementsConstructEv
-__ZNK3KJS8JSObject21implementsHasInstanceEv
-__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3KJS8JSObject3getEPNS_9ExecStateEj
-__ZNK3KJS8JSObject4typeEv
-__ZNK3KJS8JSObject6canPutEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE
-__ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE
-__ZNK3KJS8JSObject8toStringEPNS_9ExecStateE
-__ZNK3KJS8JSObject9classInfoEv
-__ZNK3KJS8JSObject9classNameEv
-__ZNK3KJS8JSObject9toBooleanEPNS_9ExecStateE
-__ZNK3KJS9ExecState19lexicalGlobalObjectEv
-__ZTVN3KJS14JSGlobalObjectE
-__ZTVN3KJS14StringInstanceE
-__ZTVN3KJS15JSWrapperObjectE
-__ZTVN3KJS16JSVariableObjectE
-__ZTVN3KJS19InternalFunctionImpE
-__ZTVN3KJS8JSObjectE
-_jscore_collector_introspection
+__ZN3WTF9ByteArray6createEm
+__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE
+__ZNK3JSC12DateInstance7getTimeERdRi
+__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
+__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
+__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZNK3JSC16InternalFunction9classInfoEv
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZNK3JSC17DebuggerCallFrame10thisObjectEv
+__ZNK3JSC17DebuggerCallFrame12functionNameEv
+__ZNK3JSC17DebuggerCallFrame4typeEv
+__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_10JSValuePtrE
+__ZNK3JSC4Heap10statisticsEv
+__ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
+__ZNK3JSC6JSCell14isGetterSetterEv
+__ZNK3JSC6JSCell17getTruncatedInt32ERi
+__ZNK3JSC6JSCell18getTruncatedUInt32ERj
+__ZNK3JSC6JSCell9classInfoEv
+__ZNK3JSC6JSCell9getStringERNS_7UStringE
+__ZNK3JSC6JSCell9getStringEv
+__ZNK3JSC6JSCell9getUInt32ERj
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZNK3JSC7UString10UTF8StringEb
+__ZNK3JSC7UString14toStrictUInt32EPb
+__ZNK3JSC7UString5asciiEv
+__ZNK3JSC7UString6is8BitEv
+__ZNK3JSC7UString6substrEii
+__ZNK3JSC7UString8toUInt32EPb
+__ZNK3JSC7UString8toUInt32EPbb
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject9classNameEv
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
+__ZNK3JSC9HashTable11deleteTableEv
+__ZNK3WTF8Collator7collateEPKtmS2_m
+__ZTVN3JSC12StringObjectE
+__ZTVN3JSC14JSGlobalObjectE
+__ZTVN3JSC15JSWrapperObjectE
+__ZTVN3JSC16InternalFunctionE
+__ZTVN3JSC16JSVariableObjectE
+__ZTVN3JSC8JSObjectE
+__ZTVN3JSC8JSStringE
_jscore_fastmalloc_introspection
_kJSClassDefinitionEmpty
-_kjs_strtod
-_JSLockDropAllLocks
-_JSLockRecoverAllLocks
-_JSSetJavaScriptCollectionThread
--- /dev/null
+__ZN3JSC19initializeThreadingEv
+dyld_stub_binding_helper
+__ZN3JSCL23initializeThreadingOnceEv
+__ZN3WTF19initializeThreadingEv
+__ZN3WTF10fastMallocEm
+__ZN3WTF10fastMallocILb1EEEPvm
+__ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
+__ZN3WTFL15InitSizeClassesEv
+__Z20TCMalloc_SystemAllocmPmm
+__ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
+__ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi
+__ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
+__ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
+__ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
+__ZN3WTFL13MetaDataAllocEm
+__Z22TCMalloc_SystemReleasePvm
+__ZN3WTFL25identifierByPthreadHandleERKP17_opaque_pthread_t
+__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
+__ZN3WTF16fastZeroedMallocEm
+__ZN3WTF8fastFreeEPv
+__ZN3WTF22initializeMainNSThreadEv
+__ZN3WTF20initializeMainThreadEv
+__ZN3WTF5MutexC1Ev
+__ZN3JSC17initializeUStringEv
+__ZN3JSC12initDateMathEv
+__ZN3WTF11currentTimeEv
+__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
+__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3JSC8DebuggerC2Ev
+__ZN3WTF5Mutex4lockEv
+__ZN3WTF5Mutex6unlockEv
+__ZN3WTF6strtodEPKcPPc
+__ZN3JSC6JSLock12DropAllLocksC1Eb
+__ZN3JSCL17createJSLockCountEv
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3WTF15ThreadConditionC1Ev
+__ZN3WTF12createThreadEPFPvS0_ES0_PKc
+__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
+__ZN3WTF15ThreadCondition4waitERNS_5MutexE
+__ZN3WTFL16threadEntryPointEPv
+__ZN3WTF5MutexD1Ev
+__ZN3WTF13currentThreadEv
+__ZN3WTF15ThreadCondition9broadcastEv
+__ZN3WTF15ThreadCondition6signalEv
+__ZN3WTF16callOnMainThreadEPFvPvES0_
+__ZN3WTF6VectorINS_19FunctionWithContextELm0EE14expandCapacityEm
+__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
+__ZN3WTF12mainNSThreadEv
+-[WTFMainThreadCaller call]
+__ZN3WTF31dispatchFunctionsFromMainThreadEv
+__ZN3WTF11fastReallocEPvm
+__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
+__ZN3JSC7UStringC1EPKti
+__ZN3JSC7UStringC2EPKti
+__ZN3JSC12JSGlobalData12createLeakedEv
+__ZN3JSC12JSGlobalDataC2Eb
+__ZN3JSC11InterpreterC1Ev
+__ZN3JSC11InterpreterC2Ev
+__ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_10JSValuePtrE
+__ZN3WTF7HashMapIPvN3JSC8OpcodeIDENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS6_IS3_EEE3addERKS1_RKS3_
+__ZN3WTF9HashTableIPvSt4pairIS1_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS5_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTraitsIS1_EENSB_IS4_EEEESC_E6expandEv
+__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE
+__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayD1Ev
+__ZN3JSC7JSArrayD2Ev
+__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
+__ZN3JSC9StructureD1Ev
+__ZN3JSC9StructureD2Ev
+__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC11JSByteArrayD1Ev
+__ZN3JSC8JSStringD1Ev
+__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev
+__ZN3JSC10JSFunctionD1Ev
+__ZN3JSC8JSObjectD2Ev
+__ZN3JSC21createIdentifierTableEv
+__ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
+__ZN3JSC17CommonIdentifiersC2EPNS_12JSGlobalDataE
+__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
+__ZN3WTF7HashMapIPKcNS_6RefPtrIN3JSC7UString3RepEEENS_7PtrHashIS2_EENS_10HashTraitsIS2_EENSA_IS7_EEE3addERKS2_RKS7_
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E6rehashEi
+__ZN3JSC12SmallStringsC1Ev
+__ZN3JSC5LexerC1EPNS_12JSGlobalDataE
+__ZN3JSC5LexerC2EPNS_12JSGlobalDataE
+__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
+__ZN3JSC27startProfilerServerIfNeededEv
++[ProfilerServer sharedProfileServer]
+-[ProfilerServer init]
+__ZN3JSC11Interpreter10initializeEPNS_12JSGlobalDataE
+__ZN3JSC4Heap8allocateEm
+__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv
+__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject5resetENS_10JSValuePtrE
+__ZN3JSC4Heap12heapAllocateILNS_8HeapTypeE0EEEPvm
+__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
+__ZN3JSC7UStringC1EPKc
+__ZN3JSCL9createRepEPKc
+__ZN3JSC8JSObject9putDirectERKNS_10IdentifierENS_10JSValuePtrEjbRNS_15PutPropertySlotE
+__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure3getERKNS_10IdentifierERj
+__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure3putERKNS_10IdentifierEj
+__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj
+__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC9Structure26rehashPropertyMapHashTableEj
+__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSCL13allocateBlockILNS_8HeapTypeE1EEEPNS_14CollectorBlockEv
+__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringES9_
+__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeE
+__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
+__ZNK3JSC16InternalFunction9classInfoEv
+__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeE
+__ZNK3JSC14ArrayPrototype9classInfoEv
+__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
+__ZNK3JSC15StringPrototype9classInfoEv
+__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
+__ZNK3JSC13BooleanObject9classInfoEv
+__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
+__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
+__ZNK3JSC13DatePrototype9classInfoEv
+__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
+__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
+__ZNK3JSC13ErrorInstance9classInfoEv
+__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
+__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC12SmallStrings24singleCharacterStringRepEh
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEE3addEPS4_RKS6_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E6expandEv
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE
+__ZN3JSC9Structure17copyPropertyTableEv
+__ZN3JSC14JSGlobalObject14setTimeoutTimeEj
+__ZN3JSC14JSGlobalObject10globalExecEv
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
+__ZN3JSC4Heap4heapENS_10JSValuePtrE
+__ZN3JSC4Heap7protectENS_10JSValuePtrE
+__ZN3WTF7HashMapIPN3JSC6JSCellEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC6JSCellnwEmPNS_9ExecStateE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
+__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
+__ZN3JSC11Interpreter17resetTimeoutCheckEv
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC6JSLock4lockEb
+__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
+__ZN3JSC7UStringaSEPKc
+__Z10jscyyparsePv
+__ZN3JSC5Lexer3lexEPvS1_
+__ZN3WTF6VectorItLm0EE6appendItEEvRKT_
+__ZN3WTF6VectorItLm0EE15reserveCapacityEm
+__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
+__ZN3WTF7HashSetIPN3JSC16ParserRefCountedENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC16ParserRefCountedES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC16ParserRefCountedC2EPNS_12JSGlobalDataE
+__ZN3JSC16ParserRefCounted3refEv
+__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3JSC14SourceElements6appendEN3WTF10PassRefPtrINS_13StatementNodeEEE
+__ZNK3JSC13StatementNode16isEmptyStatementEv
+__Z21mergeDeclarationListsIPN3JSC20ParserRefCountedDataIN3WTF6VectorINS2_6RefPtrINS0_12FuncDeclNodeEEELm0EEEEEET_SA_SA_
+__ZL20makeFunctionCallNodePvN3JSC8NodeInfoIPNS0_14ExpressionNodeEEENS1_IPNS0_13ArgumentsNodeEEEiii
+__ZNK3JSC15DotAccessorNode10isLocationEv
+__ZNK3JSC14ExpressionNode13isResolveNodeEv
+__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
+__ZN3WTF7HashMapIPN3JSC16ParserRefCountedEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC16ParserRefCountedESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEEEPNS3_INS5_INS4_6RefPtrINS_12FuncDeclNodeEEELm0EEEEEjii
+__ZN3JSC5Lexer5clearEv
+__ZN3JSC16ParserRefCounted16deleteNewObjectsEPNS_12JSGlobalDataE
+__ZN3JSC11ResolveNodeD0Ev
+__ZN3JSC15DotAccessorNodeD0Ev
+__ZN3JSC12NodeReleaser15releaseAllNodesEPNS_16ParserRefCountedE
+__ZN3JSC15DotAccessorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12NodeReleaser7releaseINS_14ExpressionNodeEEEvRN3WTF6RefPtrIT_EE
+__ZN3JSC12NodeReleaser5adoptEN3WTF10PassRefPtrINS_16ParserRefCountedEEE
+__ZN3JSC16ParserRefCounted9hasOneRefEv
+__ZN3JSC16ParserRefCounted5derefEv
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS9_INS8_6RefPtrINS_12FuncDeclNodeEEELm0EEEji
+__ZN3WTF6VectorINS_6RefPtrIN3JSC13StatementNodeEEELm0EE14shrinkCapacityEm
+__ZN3JSC14SourceElementsD0Ev
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_10JSValuePtrE
+__ZN3JSC11ProgramNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC9CodeBlockC2EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
+__ZN3WTF7HashSetIPN3JSC16ProgramCodeBlockENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE15reserveCapacityEm
+__ZN3JSC9Structure22toDictionaryTransitionEPS0_
+__ZN3JSC17BytecodeGenerator11newRegisterEv
+__ZN3JSC9Structure24fromDictionaryTransitionEPS0_
+__ZN3JSC17BytecodeGenerator8generateEv
+__ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
+__ZN3JSC17BytecodeGenerator11addConstantENS_10JSValuePtrE
+__ZN3WTF7HashMapIPN3JSC23JSValueEncodedAsPointerEjNS_7PtrHashIS3_EENS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC23JSValueEncodedAsPointerESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEEESC_E6rehashEi
+__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
+__ZNK3JSC13StatementNode6isLoopEv
+__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
+__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE
+__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEiNS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEE3addEPS4_RKi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESD_E6rehashEi
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator12newTemporaryEv
+__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF6VectorIjLm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF7HashMapIPN3JSC7UString3RepEPNS1_8JSStringENS1_17IdentifierRepHashENS_10HashTraitsIS4_EENS8_IS6_EEE3addERKS4_RKS6_
+__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS7_EEEESE_E6rehashEi
+__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE6appendIiEEvRKT_
+__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
+__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
+__ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
+__ZNK3JSC21UStringSourceProvider6lengthEv
+__ZNK3JSC21UStringSourceProvider4dataEv
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
+__ZN3JSC19extractFunctionBodyEPNS_11ProgramNodeE
+__ZNK3JSC17ExprStatementNode15isExprStatementEv
+__ZNK3JSC12FuncExprNode14isFuncExprNodeEv
+__ZN3JSC16FunctionBodyNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser14reparseInPlaceEPNS_12JSGlobalDataEPNS_16FunctionBodyNodeE
+__ZL11makeSubNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC14ExpressionNode14stripUnaryPlusEv
+__ZNK3JSC14ExpressionNode8isNumberEv
+__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
+__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
+__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC7SubNode8opcodeIDEv
+__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
+__ZNK3JSC9BlockNode7isBlockEv
+__ZNK3JSC10ReturnNode12isReturnNodeEv
+__ZN3JSC9CodeBlock11shrinkToFitEv
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIjLm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
+__ZN3JSC9BlockNodeD0Ev
+__ZN3JSC9BlockNode12releaseNodesERNS_12NodeReleaserE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC16ParserRefCountedEEELm0EE15reserveCapacityEm
+__ZN3JSC10ReturnNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12BinaryOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16ParserRefCounted12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10ReturnNodeD0Ev
+__ZN3JSC7SubNodeD0Ev
+__ZN3JSC12BinaryOpNodeD2Ev
+__ZN3JSC17BytecodeGeneratorD2Ev
+__ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
+__ZN3JSC11ProgramNodeD0Ev
+__ZN3JSC9ScopeNodeD2Ev
+__ZN3JSC9ScopeNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17ExprStatementNodeD0Ev
+__ZN3JSC12FuncExprNodeD0Ev
+__ZN3JSC12FuncExprNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12NodeReleaser21adoptFunctionBodyNodeERN3WTF6RefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC13ParameterNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ParameterNodeD0Ev
+__ZN3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC7UString3Rep7destroyEv
+__ZN3JSC10Identifier6removeEPNS_7UString3RepE
+__ZN3JSC9CodeBlockD1Ev
+__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC21UStringSourceProviderD0Ev
+__ZN3JSC17AssignResolveNodeD0Ev
+__ZN3JSC17AssignResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10StringNodeD0Ev
+__ZN3JSC19FunctionCallDotNodeD0Ev
+__ZN3JSC19FunctionCallDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ArgumentsNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16ArgumentListNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ArgumentsNodeD0Ev
+__ZN3JSC16ArgumentListNodeD0Ev
+__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
+__ZN3JSC11Interpreter11resolveBaseEPNS_9ExecStateEPNS_11InstructionE
+__ZN3JSC11Interpreter13resolveGlobalEPNS_9ExecStateEPNS_11InstructionERNS_10JSValuePtrE
+__ZN3JSC11Interpreter15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_10JSValuePtrERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC11Interpreter15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_10JSValuePtrERKNS_15PutPropertySlotE
+__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectES6_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
+__ZNK3JSC8JSString8toStringEPNS_9ExecStateE
+__ZNK3JSC9CodeBlock15derefStructuresEPNS_11InstructionE
+__ZN3JSC14JSGlobalObject16stopTimeoutCheckEv
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE15reserveCapacityEm
+__ZN3JSC20ParserRefCountedDataIN3WTF6VectorINS1_6RefPtrINS_12FuncDeclNodeEEELm0EEEED0Ev
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EEaSERKS5_
+__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
+__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
+__ZN3JSC9Structure6removeERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
+__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC13AssignDotNodeD0Ev
+__ZN3JSC13AssignDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12FuncDeclNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC12FuncDeclNodeD0Ev
+__ZN3JSC12FuncDeclNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC4Heap9unprotectENS_10JSValuePtrE
+__ZN3JSC5Lexer7record8Ei
+__ZL26appendToVarDeclarationListPvRPN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE15reserveCapacityEm
+__ZL20makeVarStatementNodePvPN3JSC14ExpressionNodeE
+__ZN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED0Ev
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EEaSERKS5_
+__ZNK3JSC7UString14toStrictUInt32EPb
+__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16VarStatementNodeD0Ev
+__ZN3JSC16VarStatementNode12releaseNodesERNS_12NodeReleaserE
+__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b
+__ZNK3JSC10NumberNode8isNumberEv
+__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
+__ZN3WTF7HashMapIdN3JSC10JSValuePtrENS_9FloatHashIdEENS_10HashTraitsIdEENS5_IS2_EEE3addERKdRKS2_
+__ZN3WTF9HashTableIdSt4pairIdN3JSC10JSValuePtrEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6rehashEi
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
+__ZNK3JSC7AddNode8opcodeIDEv
+__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
+__ZNK3JSC8MultNode8opcodeIDEv
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC10NumberNodeD0Ev
+__ZN3JSC11NewExprNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11NewExprNodeD0Ev
+__ZN3JSC7AddNodeD0Ev
+__ZN3JSC8MultNodeD0Ev
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC6JSCell8isObjectEPKNS_9ClassInfoE
+__ZNK3JSC12DateInstance9classInfoEv
+__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12JSNumberCell8toNumberEPNS_9ExecStateE
+__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11BooleanNodeD0Ev
+__ZN3JSC4Heap7collectEv
+__ZN3JSC4Heap30markStackObjectsConservativelyEv
+__ZN3JSC4Heap31markCurrentThreadConservativelyEv
+__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv
+__ZN3JSC4Heap18markConservativelyEPvS1_
+__ZN3JSC4Heap20markProtectedObjectsEv
+__ZN3JSC8JSObject4markEv
+__ZN3JSC6JSCell4markEv
+__ZN3JSC14JSGlobalObject4markEv
+__ZN3JSC7JSArray4markEv
+__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC18GlobalEvalFunction4markEv
+__ZN3JSC12SmallStrings4markEv
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC17PrototypeFunctionD1Ev
+__ZN3JSC15ObjectPrototypeD1Ev
+__ZN3JSC14ArrayPrototypeD1Ev
+__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC16BooleanPrototypeD1Ev
+__ZN3JSC15NumberPrototypeD1Ev
+__ZN3JSC13DatePrototypeD1Ev
+__ZN3JSC12DateInstanceD2Ev
+__ZN3JSC15RegExpPrototypeD1Ev
+__ZN3JSC14ErrorPrototypeD1Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC17RegExpConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
+__ZN3JSC22NativeErrorConstructorD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC18GlobalEvalFunctionD1Ev
+__ZN3JSC12DateInstanceD1Ev
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8newLabelEv
+__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
+__ZN3JSC6IfNodeD0Ev
+__ZN3JSC6IfNode12releaseNodesERNS_12NodeReleaserE
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZN3JSC10JSFunction4markEv
+__ZN3JSC16FunctionBodyNode4markEv
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator19emitResolveFunctionEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZNK3JSC12NotEqualNode8opcodeIDEv
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC8LessNode8opcodeIDEv
+__ZN3JSC23FunctionCallResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC23FunctionCallResolveNodeD0Ev
+__ZN3JSC12NotEqualNodeD0Ev
+__ZN3JSC13LogicalOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13LogicalOpNodeD0Ev
+__ZN3JSC8LessNodeD0Ev
+__ZN3JSC11Interpreter18resolveBaseAndFuncEPNS_9ExecStateEPNS_11InstructionERNS_10JSValuePtrE
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11JSImmediate12nonInlineNaNEv
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSString12toThisStringEPNS_9ExecStateE
+__ZNK3JSC7UString4findERKS0_i
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_10JSValuePtrE
+__ZNK3JSC13StatementNode12isReturnNodeEv
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
+__ZNK3JSC13StatementNode7isBlockEv
+__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZN3JSC9EqualNodeD0Ev
+__ZN3JSC11concatenateEPNS_7UString3RepES2_
+__ZNK3JSC9CodeBlock13refStructuresEPNS_11InstructionE
+__ZN3JSC9CodeBlock4markEv
+__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE
+__ZN3JSC7UString4fromEd
+__ZN3WTF4dtoaEdiPiS0_PPc
+__ZN3WTFL3d2bEdPiS0_
+__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC19BracketAccessorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC19BracketAccessorNodeD0Ev
+__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
+__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZNK3JSC19BracketAccessorNode10isLocationEv
+__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
+__ZNK3JSC7ForNode6isLoopEv
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC7ForNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC7ForNodeD0Ev
+__ZN3JSC18PostfixResolveNodeD0Ev
+__ZN3JSC17AssignBracketNodeD0Ev
+__ZN3JSC17AssignBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC8ThisNodeD0Ev
+__ZN3JSC8JSObject17createInheritorIDEv
+__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSC21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSCL12getDSTOffsetEdd
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11concatenateEPNS_7UString3RepEi
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyResolveNodeD0Ev
+__ZN3JSC21ReadModifyResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10LessEqNode8opcodeIDEv
+__ZN3JSC10IfElseNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10IfElseNodeD0Ev
+__ZN3JSC10LessEqNodeD0Ev
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC13GreaterEqNode8opcodeIDEv
+__ZN3JSC13GreaterEqNodeD0Ev
+__ZN3JSC9ArgumentsD1Ev
+__ZN3JSC9ArgumentsD2Ev
+__ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
+__ZNK3JSC11GreaterNode8opcodeIDEv
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14LogicalNotNode8opcodeIDEv
+__ZN3JSC8WithNodeD0Ev
+__ZN3JSC8WithNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11GreaterNodeD0Ev
+__ZN3JSC11UnaryOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC14LogicalNotNodeD0Ev
+__ZN3JSC14ExpressionNodeD2Ev
+__ZN3JSC10JSValuePtr13equalSlowCaseEPNS_9ExecStateES0_S0_
+__ZN3JSC11Interpreter7resolveEPNS_9ExecStateEPNS_11InstructionERNS_10JSValuePtrE
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC8NullNodeD0Ev
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataERKNS_10IdentifierEPNS_14ExpressionNodeES7_PNS_13StatementNodeEiii
+__ZNK3JSC9ForInNode6isLoopEv
+__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_PNS_5LabelE
+__ZN3JSC9ForInNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ForInNodeD0Ev
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9Structure26getEnumerablePropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayEPNS_8JSObjectE
+__ZN3JSC9Structure35getEnumerableNamesFromPropertyTableERNS_17PropertyNameArrayE
+__ZNK3JSC6JSCell9classInfoEv
+__ZN3JSC14StructureChainC1EPNS_9StructureE
+__ZN3JSC14StructureChainC2EPNS_9StructureE
+__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE
+__ZN3JSC7UString4fromEi
+__ZN3JSC7UString6appendERKS0_
+__ZN3JSC22JSPropertyNameIterator10invalidateEv
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZN3JSC18EmptyStatementNodeD0Ev
+__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
+__ZN3JSCL15dateToDayInYearEiii
+__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_10JSValuePtrERKNS_7ArgListEib
+__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCplERKNS_7UStringES2_
+__ZN3JSC10formatTimeERKNS_17GregorianDateTimeEb
+__ZN3JSC22JSPropertyNameIteratorD1Ev
+__ZN3JSC8JSObjectD1Ev
+__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC9parseDateERKNS_7UStringE
+__ZNK3JSC7UString10UTF8StringEb
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC7JSArrayC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7ArgListE
+__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC9WhileNode6isLoopEv
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC9WhileNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13PrefixDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13PrefixDotNodeD0Ev
+__ZN3JSC20EvalFunctionCallNodeD0Ev
+__ZN3JSC20EvalFunctionCallNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9WhileNodeD0Ev
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivationC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC7DivNode8opcodeIDEv
+__ZN3JSC15ConditionalNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC15ConditionalNodeD0Ev
+__ZN3JSC7DivNodeD0Ev
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjEPNS3_9StructureENS3_28StructureTransitionTableHashENS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEE3addERKS7_RKS9_
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_PNS3_9StructureEENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E6rehashEi
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter22resolveBaseAndPropertyEPNS_9ExecStateEPNS_11InstructionERNS_10JSValuePtrE
+__ZN3JSC9Structure22materializePropertyMapEv
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC12JSActivationD2Ev
+__ZN3JSC11Interpreter14uncachePutByIDEPNS_9CodeBlockEPNS_11InstructionE
+__ZN3JSC12StringObjectD1Ev
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3WTF11fastReallocILb0EEEPvS1_m
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZNK3JSC7ModNode8opcodeIDEv
+__ZN3JSC7ModNodeD0Ev
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_10JSValuePtrE
+__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7UString6appendEt
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_10JSValuePtrE
+__ZN3JSC5Lexer10scanRegExpEv
+__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE
+__ZNK3JSC9BitOrNode8opcodeIDEv
+__ZN3JSC9BitOrNodeD0Ev
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
+__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF16weakRandomNumberEv
+__ZNK3JSC13UnaryPlusNode8opcodeIDEv
+__ZN3JSC13UnaryPlusNodeD0Ev
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZNK3JSC7UString8toDoubleEbb
+__ZNK3JSC7UString10getCStringERN3WTF6VectorIcLm32EEE
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL13jsAddSlowCaseEPNS_9ExecStateENS_10JSValuePtrES2_
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7UString4fromEj
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16VarDeclCommaNodeD0Ev
+__ZN3JSC7UStringC2EPtib
+__ZN3JSC11concatenateEPNS_7UString3RepEd
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
+__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
+__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
+__ZL11checkEscapePPKtS0_P9ErrorCodeib
+__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
+__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC6RegExpEEELm0EE14expandCapacityEm
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
+__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
+__ZL17bracketIsAnchoredPKh
+__ZL32branchFindFirstAssertedCharacterPKhb
+__ZL20branchNeedsLineStartPKhjj
+__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17ObjectLiteralNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17ObjectLiteralNodeD0Ev
+__ZN3JSC10RegExpNodeD0Ev
+__ZN3JSC9ArrayNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ArrayNodeD0Ev
+__ZN3JSC16PropertyListNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12PropertyNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16PropertyListNodeD0Ev
+__ZN3JSC12PropertyNodeD0Ev
+__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
+__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
+__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
+__ZNK3JSC14ExpressionNode10isLocationEv
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21FunctionCallValueNodeD0Ev
+__ZN3JSC21FunctionCallValueNode12releaseNodesERNS_12NodeReleaserE
+__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EESA_E6rehashEi
+__ZN3JSC11ElementNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11ElementNodeD0Ev
+__ZNK3JSC12JSActivation14isDynamicScopeEv
+__ZN3JSC4Heap24setGCProtectNeedsLockingEv
+__ZN3WTF15ThreadConditionD1Ev
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17PrefixResolveNodeD0Ev
+__ZNK3JSC7UString8toUInt32EPbb
+__ZN3JSC7UString17expandPreCapacityEi
+__ZN3WTF17TCMalloc_PageHeap3NewEm
+__ZN3JSC6JSCell9getObjectEv
+__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_10JSValuePtrE
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZNK3JSC12RegExpObject9classInfoEv
+__ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
+__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF11OwnArrayPtrIiEE
+__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
+__ZL5matchPKtPKhiR9MatchData
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ThrowNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ThrowNodeD0Ev
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17DeleteBracketNodeD0Ev
+__ZN3JSC17DeleteBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZNK3JSC6JSCell9getUInt32ERj
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC11Interpreter14uncacheGetByIDEPNS_9CodeBlockEPNS_11InstructionE
+__ZNK3JSC6JSCell17getTruncatedInt32ERi
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
+__ZNK3JSC12JSNumberCell9toBooleanEPNS_9ExecStateE
+__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
+__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
+__ZN3JSC7UString6appendEPKc
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
+__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC13StatementNode6setLocEii
+__ZN3JSC16FunctionBodyNode14copyParametersEv
+__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
+__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3JSC9CodeBlock43hasGlobalResolveInstructionAtBytecodeOffsetEj
+__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC9Arguments9classInfoEv
+__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_7ArgListE
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
+__ZN3JSC7TryNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC7TryNodeD0Ev
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE
+__ZN3JSCltERKNS_7UStringES2_
+__ZN3JSC9BreakNodeD0Ev
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZNK3JSC10ScopeChain10localDepthEv
+__ZNK3JSC12JSActivation9classInfoEv
+__ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE15reserveCapacityEm
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF12detachThreadEj
+__ZN3WTFL26pthreadHandleForIdentifierEj
+__ZN3WTFL31clearPthreadHandleForIdentifierEj
+__ZN3JSC18RegExpMatchesArrayD1Ev
+__ZN3JSC12RegExpObjectD1Ev
+__Z12jsRegExpFreeP8JSRegExp
+__ZN3JSC6RegExpD1Ev
+__ZN3WTF19initializeThreadingEv
__ZN3WTF10fastMallocEm
+__ZN3WTF10fastMallocILb1EEEPvm
__ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
-__ZN3WTF15InitSizeClassesEv
+__ZN3WTFL15InitSizeClassesEv
__Z20TCMalloc_SystemAllocmPmm
-__ZN3WTF17TCMalloc_PageHeap4initEv
__ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
__ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi
__ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
__ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
__ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
-__ZN3WTF13MetaDataAllocEm
-__ZN3WTF17TCMalloc_PageHeap19IncrementalScavengeEm
+__ZN3WTFL13MetaDataAllocEm
+__ZN3WTF20initializeMainThreadEv
+__ZN3WTF5MutexC1Ev
+__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3JSC19initializeThreadingEv
+__ZN3JSCL23initializeThreadingOnceEv
+__ZN3JSC17initializeUStringEv
+__ZN3JSC12initDateMathEv
+__ZN3WTF11currentTimeEv
+__ZN3WTF15ThreadConditionC1Ev
+__ZN3WTF5Mutex4lockEv
+__ZN3WTF5Mutex6unlockEv
__ZN3WTF8fastFreeEPv
+__ZN3WTF12createThreadEPFPvS0_ES0_PKc
+__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
+__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t
+__ZN3WTFL16threadEntryPointEPv
+__ZN3WTF7HashMapIjP17_opaque_pthread_tNS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3addERKjRKS2_
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
__ZN3WTF16fastZeroedMallocEm
+__ZN3WTF5MutexD1Ev
+__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
-__ZN3KJS8Bindings10RootObject19setCreateRootObjectEPFN3WTF10PassRefPtrIS1_EEPvE
-__ZN3KJS8Bindings8Instance21setDidExecuteFunctionEPFvPNS_9ExecStateEPNS_8JSObjectEE
-_kjs_strtod
-__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
-__Z30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
-__Z11checkEscapePPKtS0_P9ErrorCodeib
-__Z13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
-__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZN3WTF13currentThreadEv
+__ZN3WTF16callOnMainThreadEPFvPvES0_
+__ZN3WTF6VectorINS_19FunctionWithContextELm0EE14expandCapacityEm
+__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
+__ZN3WTF15ThreadCondition4waitERNS_5MutexE
+__ZN3JSC8DebuggerC2Ev
+__ZN3WTF6strtodEPKcPPc
+__ZN3WTF15ThreadCondition6signalEv
+__ZN3WTF15ThreadCondition9broadcastEv
+__ZN3JSC12JSGlobalData12createLeakedEv
+__ZN3JSC12JSGlobalDataC2Eb
+__ZN3JSC11InterpreterC1Ev
+__ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_10JSValuePtrE
+__ZN3WTF7HashMapIPvN3JSC8OpcodeIDENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS6_IS3_EEE3addERKS1_RKS3_
+__ZN3WTF9HashTableIPvSt4pairIS1_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS5_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTraitsIS1_EENSB_IS4_EEEESC_E6expandEv
+__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE
+__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayD0Ev
+__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
+__ZN3JSC9StructureD1Ev
+__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC21createIdentifierTableEv
+__ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
+__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E4findIS2_NS_22IdentityHashTranslatorIS2_S9_SD_EEEENS_17HashTableIteratorIS2_S9_SB_SD_SI_SG_EERKT_
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E6expandEv
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E4findIS4_NS_22IdentityHashTranslatorIS4_S4_S8_EEEENS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EERKT_
+__ZN3JSC12SmallStringsC1Ev
+__ZN3JSC5LexerC1EPNS_12JSGlobalDataE
+__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
+__ZN3JSC19ExecutableAllocator17intializePageSizeEv
+__ZN3JSC14ExecutablePool11systemAllocEm
+__ZN3JSC27startProfilerServerIfNeededEv
++[ProfilerServer sharedProfileServer]
+-[ProfilerServer init]
+__ZN3JSC11Interpreter10initializeEPNS_12JSGlobalDataE
+__ZN3JSC3JITC1EPNS_12JSGlobalDataEPNS_9CodeBlockE
+__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEv
+__ZN3JSC15AssemblerBuffer11ensureSpaceEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDE
+__ZN3JSC14MacroAssembler4pokeENS_3X8610RegisterIDEi
+__ZN3JSC3JIT32compileOpCallInitializeCallFrameEv
+__ZN3JSC14MacroAssembler5jnz32ENS_3X8610RegisterIDENS0_5Imm32E
__ZN3WTF11fastReallocEPvm
-__ZN3KJS6JSLock4lockEv
-__ZN3KJS20createDidLockJSMutexEv
-__ZN3KJS6JSLock14registerThreadEv
-__ZN3KJS9Collector14registerThreadEv
-__ZN3KJS29initializeRegisteredThreadKeyEv
-__ZN3KJS6JSLock6unlockEv
-__ZN3KJS15SavedPropertiesC1Ev
-__ZN3KJS6JSCellnwEm
-__ZN3KJS9Collector12heapAllocateILNS0_8HeapTypeE0EEEPvm
-__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectE
-__ZN3KJS17CommonIdentifiers6sharedEv
-__ZN3KJS17CommonIdentifiersC2Ev
-__ZN3KJS10IdentifierC1EPKc
-__ZN3KJS10Identifier3addEPKc
-__ZN3WTF7HashSetIPN3KJS7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
-__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
-__ZN3KJS14JSGlobalObject4initEv
-__ZN3KJS14JSGlobalObject5resetEPNS_7JSValueE
-__ZN3KJS11PropertyMap5clearEv
-__ZN3KJS17FunctionPrototypeC2EPNS_9ExecStateE
-__ZN3KJS11PropertyMap3putERKNS_10IdentifierEPNS_7JSValueEjb
-__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEPNS_17FunctionPrototypeEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE
-__ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE
-__ZN3KJS11PropertyMap11createTableEv
-__ZN3KJS15ObjectPrototypeC2EPNS_9ExecStateEPNS_17FunctionPrototypeE
-__ZN3KJS11PropertyMap6rehashEj
-__ZN3KJS14ArrayPrototypeC1EPNS_9ExecStateEPNS_15ObjectPrototypeE
-__ZN3KJS13ArrayInstanceC2EPNS_8JSObjectEj
-__ZN3KJS15StringPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeE
-__ZN3KJS8jsStringEPKc
-__ZN3KJS16BooleanPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE
-__ZN3KJS15NumberPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE
-__ZN3KJS13DatePrototypeC1EPNS_9ExecStateEPNS_15ObjectPrototypeE
-__ZN3KJS12jsNumberCellEd
-__ZN3KJS9Collector12heapAllocateILNS0_8HeapTypeE1EEEPvm
-__ZN3KJS15RegExpPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE
-__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E4findIS4_NS_22IdentityHashTranslatorIS4_S4_S8_EEEENS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EERKT_
-__ZN3KJS14ErrorPrototypeC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE
-__ZN3KJS7UStringC1EPKc
-__ZN3KJS20NativeErrorPrototypeC1EPNS_9ExecStateEPNS_14ErrorPrototypeERKNS_7UStringES7_
-__ZN3KJS8jsStringERKNS_7UStringE
-__ZN3KJS15ObjectObjectImpC2EPNS_9ExecStateEPNS_15ObjectPrototypeEPNS_17FunctionPrototypeE
-__ZN3KJS17FunctionObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeE
-__ZNK3KJS19InternalFunctionImp9classInfoEv
-__ZN3KJS14ArrayObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_14ArrayPrototypeE
-__ZNK3KJS14ArrayPrototype9classInfoEv
-__ZN3KJS15StringObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15StringPrototypeE
-__ZNK3KJS15StringPrototype9classInfoEv
-__ZN3KJS19StringObjectFuncImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeERKNS_10IdentifierE
-__ZN3KJS16BooleanObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_16BooleanPrototypeE
-__ZNK3KJS15BooleanInstance9classInfoEv
-__ZN3KJS15NumberObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15NumberPrototypeE
-__ZNK3KJS14NumberInstance9classInfoEv
-__ZN3KJS13DateObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_13DatePrototypeE
-__ZNK3KJS13DatePrototype9classInfoEv
-__ZN3KJS15RegExpObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_15RegExpPrototypeE
-__ZN3KJS14ErrorObjectImpC2EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_14ErrorPrototypeE
-__ZNK3KJS13ErrorInstance9classInfoEv
-__ZN3KJS14NativeErrorImpC1EPNS_9ExecStateEPNS_17FunctionPrototypeEPNS_20NativeErrorPrototypeE
-__ZNK3KJS11PropertyMap3getERKNS_10IdentifierE
-__ZNK3KJS9StringImp4typeEv
-__ZN3KJS10Identifier11addSlowCaseEPNS_7UString3RepE
-__ZN3WTF9HashTableIPN3KJS7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E3addIS4_S4_NS_17HashSetTranslatorILb1ES4_SA_SA_S8_EEEESt4pairINS_17HashTableIteratorIS4_S4_S6_S8_SA_SA_EEbERKT_RKT0_
-__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS13MathObjectImpC1EPNS_9ExecStateEPNS_15ObjectPrototypeE
-__ZN3KJS8JSObject17putDirectFunctionEPNS_19InternalFunctionImpEi
-__ZNK3KJS8JSObject4typeEv
-__ZN3KJS9Collector23collectOnMainThreadOnlyEPNS_7JSValueE
-__ZN3KJS9Collector7protectEPNS_7JSValueE
-__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E3addIPN3KJS8JSObjectEjNS_17HashMapTranslatorILb1ES1_ISF_jENS_18PairBaseHashTraitsINS8_ISF_EENS8_IjEEEESA_NS_7PtrHashISF_EEEEEES1_INS_17HashTableIteratorIiS2_S4_S6_SA_S9_EEbERKT_RKT0_
-__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E6rehashEi
-__ZN3KJS6JSCell9getObjectEv
-__ZN3KJS8Bindings10RootObject6createEPKvPNS_14JSGlobalObjectE
-__ZN3KJS8Bindings10RootObjectC2EPKvPNS_14JSGlobalObjectE
-__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E6rehashEi
-__ZN3KJS8Bindings10RootObject9gcProtectEPNS_8JSObjectE
-__ZNK3KJS14JSGlobalObject12saveBuiltinsERNS_13SavedBuiltinsE
-__ZN3KJS21SavedBuiltinsInternalC2Ev
-__ZNK3KJS11PropertyMap4saveERNS_15SavedPropertiesE
-__ZN3KJS30comparePropertyMapEntryIndicesEPKvS1_
-__ZN3WTF9HashTableIiSt4pairIiiENS_18PairFirstExtractorIS2_EENS_7IntHashIiEENS_14PairHashTraitsINS_10HashTraitsIiEES9_EES9_E4findIiNS_22IdentityHashTranslatorIiS2_S6_EEEENS_17HashTableIteratorIiS2_S4_S6_SA_S9_EERKT_
-__ZNK3KJS16JSVariableObject16saveLocalStorageERNS_15SavedPropertiesE
-__ZN3KJS13ActivationImpD0Ev
-__ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE
-__ZN3KJS11PropertyMap6removeERKNS_10IdentifierE
-__ZN3KJS7UString3Rep7destroyEv
-__ZN3KJS10Identifier6removeEPNS_7UString3RepE
-__ZN3KJS8Bindings10RootObject10invalidateEv
-__ZN3KJS9Collector9unprotectEPNS_7JSValueE
-__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E4findIiNS_22IdentityHashTranslatorIiiS4_EEEENS_17HashTableIteratorIiiS2_S4_S6_S6_EERKT_
-__ZN3KJS8Bindings10RootObjectD1Ev
-__ZN3KJS14JSGlobalObject10globalExecEv
-__ZN3KJS14JSGlobalObject17startTimeoutCheckEv
-__ZN3KJS7UStringC1EPKNS_5UCharEi
-__ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE
-__ZN3KJS6ParserC2Ev
-__ZN3KJS6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_
-__ZN3KJS6Parser5parseEiPKNS_5UCharEjPiS4_PNS_7UStringE
-__ZN3KJS7UStringaSEPKc
-__ZN3KJS5LexerC2Ev
-__ZN3WTF6VectorIcLm0EE15reserveCapacityEm
-__ZN3WTF6VectorIN3KJS5UCharELm0EE15reserveCapacityEm
-__ZN3WTF6VectorIPN3KJS7UStringELm0EE15reserveCapacityEm
-__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE15reserveCapacityEm
-__Z10kjsyyparsev
-__Z8kjsyylexv
-__ZN3KJS5Lexer3lexEv
-__ZN3KJS5Lexer14makeIdentifierERKN3WTF6VectorINS_5UCharELm0EEE
-__ZN3KJS10Identifier3addEPKNS_5UCharEi
-__ZN3KJS5Lexer15matchPunctuatorEiiii
-__ZN3KJS7UStringC2ERKN3WTF6VectorINS_5UCharELm0EEE
-__ZN3KJS14ExpressionNodeC2ENS_6JSTypeE
-__ZN3KJS16ParserRefCountedC2Ev
-__ZN3KJS7UStringC1ERKS0_
-__ZN3KJS4NodeC2Ev
-__ZN3KJS10IdentifierC1ERKS0_
-__ZN3WTF6RefPtrIN3KJS14ExpressionNodeEEC1EPS2_
-__ZN3KJS16ParserRefCounted3refEv
-__ZN3WTF6RefPtrIN3KJS12PropertyNodeEEC1EPS2_
-__ZN3WTF10ListRefPtrIN3KJS16PropertyListNodeEEC1Ev
-__ZN3KJS11ResolveNodeC1ERKNS_10IdentifierE
-__ZN3KJS14ExpressionNodeC2Ev
-__ZN3WTF10ListRefPtrIN3KJS16ArgumentListNodeEEC1Ev
-__Z20makeFunctionCallNodePN3KJS14ExpressionNodeEPNS_13ArgumentsNodeE
-__ZNK3KJS15DotAccessorNode10isLocationEv
-__ZNK3KJS14ExpressionNode13isResolveNodeEv
-__ZNK3KJS14ExpressionNode21isBracketAccessorNodeEv
-__Z14makeNumberNoded
-__Z14makeNegateNodePN3KJS14ExpressionNodeE
-__ZNK3KJS10NumberNode8isNumberEv
-__ZN3KJS19ImmediateNumberNode8setValueEd
-__ZN3KJS5lexerEv
-__ZN3KJS5Lexer10scanRegExpEv
-__ZN3KJS6RegExp6createERKNS_7UStringES3_
-__ZNK3KJS7UString4findENS_5UCharEi
-__ZN3KJS17ObjectLiteralNodeC1EPNS_16PropertyListNodeE
-__Z14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
-__ZN3KJS16FunctionBodyNode6createEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
-__ZN3KJS16FunctionBodyNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
-__ZN3KJS9ScopeNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
-__ZN3KJS9BlockNodeC1EPNS_14SourceElementsE
-__ZN3KJS13StatementNodeC2Ev
-__ZN3WTF6RefPtrIN3KJS13ParameterNodeEEC1EPS2_
-__ZN3WTF6RefPtrIN3KJS16FunctionBodyNodeEEC1EPS2_
-__ZN3KJS12FuncExprNode9addParamsEv
-__ZN3WTF10ListRefPtrIN3KJS13ParameterNodeEEC1Ev
-__ZN3KJS10ReturnNodeC1EPNS_14ExpressionNodeE
-__Z23allowAutomaticSemicolonv
-__ZN3KJS14SourceElementsC1Ev
-__ZN3WTF10PassRefPtrIN3KJS13StatementNodeEEC1EPS2_
-__ZN3KJS14SourceElements6appendEN3WTF10PassRefPtrINS_13StatementNodeEEE
-__ZNK3KJS13StatementNode16isEmptyStatementEv
-__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EE14expandCapacityEm
-__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EE15reserveCapacityEm
-__ZN3WTF6VectorIN3KJS10IdentifierELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3KJS10IdentifierELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3KJS10IdentifierELm0EE15reserveCapacityEm
-__ZN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEC1Ev
-__Z26appendToVarDeclarationListRPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEERKS4_j
-__Z20makeVarStatementNodePN3KJS14ExpressionNodeE
-__Z14makeAssignNodePN3KJS14ExpressionNodeENS_8OperatorES1_
-__ZN3KJS17ExprStatementNodeC1EPNS_14ExpressionNodeE
-__ZN3KJS6IfNodeC2EPNS_14ExpressionNodeEPNS_13StatementNodeE
-__Z21mergeDeclarationListsIPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm16EEEEEET_SA_SA_
-__Z21mergeDeclarationListsIPN3KJS20ParserRefCountedDataIN3WTF6VectorIPNS0_12FuncDeclNodeELm16EEEEEET_S9_S9_
-__ZNK3KJS11ResolveNode10isLocationEv
-__ZNK3KJS11ResolveNode13isResolveNodeEv
-__Z22combineVarInitializersPN3KJS14ExpressionNodeEPNS_17AssignResolveNodeE
-__ZN3KJS14ExpressionNode28optimizeForUnnecessaryResultEv
-__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIPN3KJS10IdentifierELm0EE14expandCapacityEm
-__ZN3KJS12FuncDeclNode9addParamsEv
-__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EEC1Ev
-__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE6appendIS4_EEvPKT_m
-__ZN3KJS16ParserRefCounted5derefEv
-__ZN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEED1Ev
-__Z12makeLessNodePN3KJS14ExpressionNodeES1_
-__Z15makePostfixNodePN3KJS14ExpressionNodeENS_8OperatorE
-__ZN3WTF6RefPtrIN3KJS13StatementNodeEEC1EPS2_
-__ZN3KJS18PostIncResolveNode28optimizeForUnnecessaryResultEv
-__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EEaSERKS5_
-__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EEaSERKS4_
-__ZNK3KJS14ExpressionNode10isLocationEv
-__ZNK3KJS19BracketAccessorNode10isLocationEv
-__ZNK3KJS19BracketAccessorNode21isBracketAccessorNodeEv
-__ZN3KJS9ForInNodeC1ERKNS_10IdentifierEPNS_14ExpressionNodeES5_PNS_13StatementNodeE
-__ZN3KJS9ThrowNodeC1EPNS_14ExpressionNodeE
-__Z14makeTypeOfNodePN3KJS14ExpressionNodeE
-__ZN3WTF6VectorINS_6RefPtrIN3KJS13StatementNodeEEELm0EEC1Ev
-__ZN3WTF6RefPtrIN3KJS14CaseClauseNodeEEC1EPS2_
-__ZN3WTF10ListRefPtrIN3KJS14ClauseListNodeEEC1Ev
-__ZN3KJS13CaseBlockNodeC2EPNS_14ClauseListNodeEPNS_14CaseClauseNodeES2_
-__Z11makeAddNodePN3KJS14ExpressionNodeES1_
-__ZN3WTF10ListRefPtrIN3KJS11ElementNodeEEC1Ev
-__ZN3WTF6RefPtrIN3KJS11ElementNodeEEC1EPS2_
-__ZNK3KJS18EmptyStatementNode16isEmptyStatementEv
-__ZN3KJS9BreakNodeC1Ev
-__Z32branchFindFirstAssertedCharacterPKhb
-__Z20branchNeedsLineStartPKhjj
-__ZN3KJS10IdentifierC1ERKNS_7UStringE
-__ZN3WTF6RefPtrIN3KJS7UString3RepEED1Ev
-__ZN3KJS9CommaNodeC2EPNS_14ExpressionNodeES2_
-__Z14makePrefixNodePN3KJS14ExpressionNodeENS_8OperatorE
-__ZN3WTF6RefPtrIN3KJS13ArgumentsNodeEEC1EPS2_
-__ZN3WTF6VectorIPN3KJS7UStringELm0EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIPN3KJS7UStringELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3KJS5UCharELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3KJS5UCharELm0EE14expandCapacityEm
-__ZNK3KJS14ExpressionNode8isNumberEv
-__ZN3KJS19PlaceholderTrueNodeC1Ev
-__ZN3KJS18EmptyStatementNodeC1Ev
-__Z14makeDeleteNodePN3KJS14ExpressionNodeE
-__Z15isCountedRepeatPKtS0_
-__ZN3KJS12ContinueNodeC1Ev
-__ZN3KJS9ForInNodeC1EPNS_14ExpressionNodeES2_PNS_13StatementNodeE
-__ZN3KJS18PostDecResolveNode28optimizeForUnnecessaryResultEv
-__Z17bracketIsAnchoredPKh
-__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE14expandCapacityEmPKS4_
-__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE14expandCapacityEm
-__ZN3WTF6VectorISt4pairIN3KJS10IdentifierEjELm16EE15reserveCapacityEm
-__ZN3KJS7UString4fromEd
-_kjs_dtoa
-_d2b
-_Balloc
-__ZN3KJS6parserEv
-__ZN3KJS6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEEPNS3_INS5_IPNS_12FuncDeclNodeELm16EEEEEi
-__ZN3KJS5Lexer5clearEv
-__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC4Heap8allocateEm
+__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv
+__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject5resetENS_10JSValuePtrE
+__ZN3JSC4Heap12heapAllocateILNS_8HeapTypeE0EEEPvm
+__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
+__ZN3JSC7UStringC1EPKc
+__ZN3JSCL9createRepEPKc
+__ZN3JSC8JSObject9putDirectERKNS_10IdentifierENS_10JSValuePtrEjbRNS_15PutPropertySlotE
+__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure3getERKNS_10IdentifierERj
+__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure3putERKNS_10IdentifierEj
+__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj
+__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC9Structure26rehashPropertyMapHashTableEj
+__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSCL13allocateBlockILNS_8HeapTypeE1EEEPNS_14CollectorBlockEv
+__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev
+__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringES9_
+__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeE
+__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
+__ZNK3JSC16InternalFunction9classInfoEv
+__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeE
+__ZNK3JSC14ArrayPrototype9classInfoEv
+__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
+__ZNK3JSC15StringPrototype9classInfoEv
+__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
+__ZNK3JSC13BooleanObject9classInfoEv
+__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
+__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
+__ZNK3JSC13DatePrototype9classInfoEv
+__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
+__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
+__ZNK3JSC13ErrorInstance9classInfoEv
+__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
+__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC12SmallStrings24singleCharacterStringRepEh
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEE3addEPS4_RKS6_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E6rehashEi
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE
+__ZN3JSC9Structure17copyPropertyTableEv
+__ZN3JSC14JSGlobalObject14setTimeoutTimeEj
+__ZN3JSC14JSGlobalObject10globalExecEv
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
+__ZN3JSC4Heap4heapENS_10JSValuePtrE
+__ZN3JSC4Heap7protectENS_10JSValuePtrE
+__ZN3WTF7HashMapIPN3JSC6JSCellEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC6JSCellnwEmPNS_9ExecStateE
+__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
+__ZN3JSC11Interpreter17resetTimeoutCheckEv
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC6JSLock4lockEb
+__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
+__ZN3JSC7UStringaSEPKc
+__Z10jscyyparsePv
+__ZN3JSC5Lexer3lexEPvS1_
+__ZN3WTF6VectorItLm0EE15reserveCapacityEm
+__ZN3WTF6VectorItLm0EE6appendItEEvRKT_
+__ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
+__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
+__ZN3WTF7HashSetIPN3JSC16ParserRefCountedENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC16ParserRefCountedES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC16ParserRefCountedC2EPNS_12JSGlobalDataE
+__ZN3JSC16ParserRefCounted3refEv
+__ZL20makeFunctionCallNodePvN3JSC8NodeInfoIPNS0_14ExpressionNodeEEENS1_IPNS0_13ArgumentsNodeEEEiii
+__ZNK3JSC15DotAccessorNode10isLocationEv
+__ZNK3JSC14ExpressionNode13isResolveNodeEv
+__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
+__ZN3WTF7HashMapIPN3JSC16ParserRefCountedEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC16ParserRefCountedESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC14SourceElements6appendEN3WTF10PassRefPtrINS_13StatementNodeEEE
+__ZNK3JSC13StatementNode16isEmptyStatementEv
+__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEEEPNS3_INS5_INS4_6RefPtrINS_12FuncDeclNodeEEELm0EEEEEjii
+__ZN3JSC5Lexer5clearEv
+__ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
+__ZN3WTF15deleteAllValuesIPN3JSC16ParserRefCountedEKNS_9HashTableIS3_S3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EESA_EEEEvRT0_
+__ZN3JSC15DotAccessorNodeD1Ev
+__ZN3JSC12NodeReleaser15releaseAllNodesEPNS_16ParserRefCountedE
+__ZN3JSC15DotAccessorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12NodeReleaser5adoptEN3WTF10PassRefPtrINS_16ParserRefCountedEEE
+__ZN3JSC16ParserRefCounted9hasOneRefEv
+__ZN3JSC16ParserRefCounted5derefEv
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS9_INS8_6RefPtrINS_12FuncDeclNodeEEELm0EEEji
+__ZN3WTF6VectorINS_6RefPtrIN3JSC13StatementNodeEEELm0EE14shrinkCapacityEm
+__ZN3JSC14SourceElementsD1Ev
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_10JSValuePtrE
+__ZN3JSC11ProgramNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
+__ZN3WTF7HashSetIPN3JSC16ProgramCodeBlockENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm
+__ZN3JSC9Structure22toDictionaryTransitionEPS0_
+__ZN3JSC17BytecodeGenerator11newRegisterEv
+__ZN3JSC9Structure24fromDictionaryTransitionEPS0_
+__ZN3JSC17BytecodeGenerator8generateEv
+__ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
+__ZN3JSC17BytecodeGenerator11addConstantENS_10JSValuePtrE
+__ZN3WTF9HashTableIPN3JSC23JSValueEncodedAsPointerESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEEESC_E6expandEv
+__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEm
+__ZNK3JSC13StatementNode6isLoopEv
+__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
+__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESD_E6expandEv
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
+__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC9CodeBlock11shrinkToFitEv
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
+__ZN3JSC17ExprStatementNodeD1Ev
+__ZN3JSC19FunctionCallDotNodeD1Ev
+__ZN3JSC19FunctionCallDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC16ParserRefCountedEEELm0EE14expandCapacityEm
+__ZN3JSC16ParserRefCounted12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ArgumentsNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11ResolveNodeD1Ev
+__ZN3JSC13ArgumentsNodeD1Ev
+__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
+__ZN3JSC3JIT14privateCompileEv
+__ZN3JSC3JIT22privateCompileMainPassEv
+__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
+__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEm
+__ZN3JSC3JIT22privateCompileLinkPassEv
+__ZN3JSC3JIT23privateCompileSlowCasesEv
+__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEj
+__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
+__ZN3JSC3JIT22compileOpCallSetupArgsEPNS_11InstructionE
+__ZN3JSC12X86Assembler3jneEv
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE6appendIS2_EEvRKT_
+__ZN3JSC9CodeBlock10setJITCodeERNS_10JITCodeRefE
+__ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
+__ZN3WTF10RefCountedIN3JSC14ExecutablePoolEE5derefEv
+ctiTrampoline
+__ZN3JSC11Interpreter16cti_op_get_by_idEPvz
+__ZNK3JSC10JSValuePtr3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectES6_RKNS_7ArgListEE
+__ZN3JSC27ctiPatchCallByReturnAddressEPvS0_
+__ZN3JSC11Interpreter25cti_op_call_NotJSFunctionEPvz
+__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF12randomNumberEv
+__ZN3JSC11ProgramNodeD1Ev
+__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC17StructureStubInfo5derefEv
+__ZN3JSC9ScopeNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC14JSGlobalObject16stopTimeoutCheckEv
+__ZN3JSC4Heap9unprotectENS_10JSValuePtrE
+__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE
+__ZN3JSC7UString4fromEd
+__ZN3WTF4dtoaEdiPiS0_PPc
+__ZN3WTFL3d2bEdPiS0_
+__ZN3WTFL8pow5multEPNS_6BigintEi
+__ZN3WTFL4multEPNS_6BigintES1_
+__ZN3WTFL6lshiftEPNS_6BigintEi
+__ZN3WTFL6quoremEPNS_6BigintES1_
+__ZN3WTFL4diffEPNS_6BigintES1_
+__ZN3JSC7UString3Rep7destroyEv
+-[WTFMainThreadCaller call]
+__ZN3WTF31dispatchFunctionsFromMainThreadEv
+__ZN3JSC4Heap7collectEv
+__ZN3JSC4Heap30markStackObjectsConservativelyEv
+__ZN3JSC4Heap31markCurrentThreadConservativelyEv
+__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv
+__ZN3JSC4Heap18markConservativelyEPvS1_
+__ZN3JSC4Heap20markProtectedObjectsEv
+__ZN3JSC12SmallStrings4markEv
+__ZN3JSC6JSCell4markEv
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3JSC17FunctionPrototypeD0Ev
+__ZN3JSC17PrototypeFunctionD0Ev
+__ZN3JSC16BooleanPrototypeD0Ev
+__ZN3JSC15NumberPrototypeD0Ev
+__ZN3JSC14ErrorPrototypeD0Ev
+__ZN3JSC17ObjectConstructorD0Ev
+__ZN3JSC16ArrayConstructorD0Ev
+__ZN3JSC17StringConstructorD0Ev
+__ZN3JSC18BooleanConstructorD0Ev
+__ZN3JSC17NumberConstructorD0Ev
+__ZN3JSC17RegExpConstructorD0Ev
+__ZN3JSC16ErrorConstructorD0Ev
+__ZN3JSC22NativeErrorConstructorD0Ev
+__ZN3JSC18GlobalEvalFunctionD0Ev
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv
__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
-__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
-__ZN3WTF15deleteAllValuesIPN3KJS16ParserRefCountedEKNS_9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEESA_EEEEvRT0_
-__ZN3KJS19BracketAccessorNodeD1Ev
-__ZN3KJS11ProgramNodeC2EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE
-__ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE
-__ZN3KJS11ProgramNode7executeEPNS_9ExecStateE
-__ZN3KJS11ProgramNode21initializeSymbolTableEPNS_9ExecStateE
-__ZN3WTF6VectorImLm0EE6resizeEm
-__ZN3WTF6VectorImLm0EE14expandCapacityEm
-__ZN3WTF6VectorImLm0EE15reserveCapacityEm
-__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E3addIS5_mNS_17HashMapTranslatorILb1ES7_NS_18PairBaseHashTraitsISC_SD_EESE_SA_EEEES6_INS_17HashTableIteratorIS5_S7_S9_SA_SE_SC_EEbERKT_RKT0_
-__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E6rehashEi
-__ZN3KJS14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3WTF7HashMapINS_6RefPtrIN3KJS7UString3RepEEEmNS2_17IdentifierRepHashENS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEE3getEPS4_
-__ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE
-__ZN3KJS6Lookup9findEntryEPKNS_9HashTableERKNS_10IdentifierE
-__ZNK3KJS7UString14toStrictUInt32EPb
-__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EE15reserveCapacityEm
-__ZN3KJS11FunctionImpC2EPNS_9ExecStateERKNS_10IdentifierEPNS_16FunctionBodyNodeERKNS_10ScopeChainE
-__ZN3KJS15ObjectObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS9ScopeNode22optimizeVariableAccessEPNS_9ExecStateE
-__ZN3WTF6VectorIPN3KJS4NodeELm16EE14expandCapacityEm
-__ZN3WTF6VectorIPN3KJS4NodeELm16EE15reserveCapacityEm
-__ZN3KJS16VarStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17AssignResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17ObjectLiteralNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS16PropertyListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS12PropertyNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS4Node22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPS0_Lm16EEE
-__ZN3KJS14LogicalNotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14LogicalAndNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS15DotAccessorNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS11ResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS11GreaterNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS19FunctionCallDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13ArgumentsNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS16ArgumentListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9EqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18NotStrictEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS6IfNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17ExprStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13AssignDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13LogicalOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS8WithNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9BlockNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS23FunctionCallResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS21FunctionCallValueNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9ArrayNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS11ElementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10IfElseNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS7AddNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS6InNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS11NewExprNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS16VarStatementNode7executeEPNS_9ExecStateE
-__ZN3KJS18AssignLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17ObjectLiteralNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16PropertyListNode8evaluateEPNS_9ExecStateE
-__ZN3KJS10StringNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13jsOwnedStringERKNS_7UStringE
-__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS14LogicalNotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14LogicalNotNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS14LogicalAndNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS15DotAccessorNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS11ResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS11GreaterNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19FunctionCallDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15DotAccessorNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9ExecState19lexicalGlobalObjectEv
-__ZNK3KJS9StringImp8toObjectEPNS_9ExecStateE
-__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS20staticFunctionGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE
-__ZNK3KJS19InternalFunctionImp14implementsCallEv
-__ZN3KJS16ArgumentListNode12evaluateListEPNS_9ExecStateERNS_4ListE
-__ZN3KJS17PrototypeFunction14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS14StringInstance9classInfoEv
-__ZNK3KJS9StringImp8toStringEPNS_9ExecStateE
-__ZNK3KJS7JSValue9toIntegerEPNS_9ExecStateE
-__ZNK3KJS7UString4findERKS0_i
-__ZN3KJS19ImmediateNumberNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14LogicalAndNode8evaluateEPNS_9ExecStateE
-__ZN3KJS9EqualNode8evaluateEPNS_9ExecStateE
-__ZN3KJS5equalEPNS_9ExecStateEPNS_7JSValueES3_
-__ZN3KJS19FunctionCallDotNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS10RegExpNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15RegExpObjectImp15createRegExpImpEPNS_9ExecStateEN3WTF10PassRefPtrINS_6RegExpEEE
-__ZN3KJS20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS9RegExpImp9classInfoEv
-__ZN3KJS15RegExpObjectImp12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
-__ZN3KJS6RegExp5matchERKNS_7UStringEiPN3WTF11OwnArrayPtrIiEE
-__Z5matchPKtPKhiR9MatchData
-__ZNK3KJS8JSObject9toBooleanEPNS_9ExecStateE
-__ZN3KJS18NotStrictEqualNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS7UString8toUInt32EPbb
-__ZNK3KJS7UString8toDoubleEbb
-__ZN3KJS11strictEqualEPNS_9ExecStateEPNS_7JSValueES3_
-__ZN3KJS12FuncExprNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14JSGlobalObject17tearOffActivationEPNS_9ExecStateEb
-__ZN3KJS6IfNode7executeEPNS_9ExecStateE
-__ZN3KJS18LocalVarAccessNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17ExprStatementNode7executeEPNS_9ExecStateE
-__ZN3KJS13AssignDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS11FunctionImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17FunctionExecStateC1EPNS_14JSGlobalObjectEPNS_8JSObjectEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_11FunctionImpERKNS_4ListE
-__ZN3KJS14JSGlobalObject14pushActivationEPNS_9ExecStateE
-__ZN3KJS13ActivationImp4initEPNS_9ExecStateE
-__ZN3KJS16FunctionBodyNode7executeEPNS_9ExecStateE
-__ZN3KJS16FunctionBodyNode21initializeSymbolTableEPNS_9ExecStateE
-__ZN3KJS9ForInNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17AssignBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS19BracketAccessorNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10ReturnNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9ForInNode7executeEPNS_9ExecStateE
-__ZN3KJS8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZNK3KJS11PropertyMap26getEnumerablePropertyNamesERNS_17PropertyNameArrayE
-__ZNK3KJS8JSObject9classInfoEv
-__ZN3KJS13ActivationImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS13ActivationImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS17AssignBracketNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS6JSCell9getUInt32ERj
-__ZN3KJS19BracketAccessorNode8evaluateEPNS_9ExecStateE
-__ZN3KJS10ReturnNode7executeEPNS_9ExecStateE
-__ZN3KJS14JSGlobalObject13popActivationEv
-__ZN3KJS11FunctionImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS10NumberNode8evaluateEPNS_9ExecStateE
-__ZN3KJS9CommaNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13ActivationImpC1ERKNS0_14ActivationDataEb
-__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EEC2ERKS3_
-__ZN3KJS13ActivationImp15argumentsGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS13ActivationImp21createArgumentsObjectEPNS_9ExecStateE
-__ZN3KJS9ArgumentsC2EPNS_9ExecStateEPNS_11FunctionImpERKNS_4ListEPNS_13ActivationImpE
-__ZN3KJS14IndexToNameMapC2EPNS_11FunctionImpERKNS_4ListE
-__ZN3KJS11FunctionImp16getParameterNameEi
-__ZN3KJS7UString4fromEj
-__ZN3KJS9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS9CommaNode8evaluateEPNS_9ExecStateE
-__ZN3KJS8ThisNode8evaluateEPNS_9ExecStateE
-__ZN3KJS23FunctionCallResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS9WhileNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18PostDecResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18LocalVarAccessNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13LogicalOrNode8evaluateEPNS_9ExecStateE
-__ZN3KJS11NewExprNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS14ArrayObjectImp19implementsConstructEv
-__ZN3KJS14ArrayObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS9WhileNode7executeEPNS_9ExecStateE
-__ZN3KJS19PostDecLocalVarNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3KJS13ArrayInstance3putEPNS_9ExecStateEjPNS_7JSValueEi
-__ZN3KJS15RegExpObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS15RegExpObjectImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS7ForNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS8LessNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17PreIncResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS8NullNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13ArrayInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3KJS17TypeOfResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18LocalVarTypeOfNode8evaluateEPNS_9ExecStateE
-__ZN3KJS18typeStringForValueEPNS_7JSValueE
-__ZNK3KJS8JSObject21masqueradeAsUndefinedEv
-__ZNK3KJS8JSObject14implementsCallEv
-__ZN3KJS12FuncDeclNode7executeEPNS_9ExecStateE
-__ZN3KJS11FunctionImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS9ArrayNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13ArrayInstanceC2EPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13ArrayInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS13ArrayInstance9setLengthEj
-__ZN3KJS7ForNode7executeEPNS_9ExecStateE
-__ZN3KJS8LessNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13ArrayInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS13ArrayInstance12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8TrueNode8evaluateEPNS_9ExecStateE
-__ZN3KJS9BlockNode7executeEPNS_9ExecStateE
-__ZN3KJS18PreIncLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3KJS13LogicalOrNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS8WithNode7executeEPNS_9ExecStateE
-__ZN3KJS15NumberObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS24LocalVarFunctionCallNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15ConditionalNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS7replaceEPNS_9ExecStateEPNS_9StringImpEPNS_7JSValueES5_
-__ZNK3KJS7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
-__ZN3KJS15ConditionalNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9StringImp9toBooleanEPNS_9ExecStateE
-__ZN3KJS20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS7UString6substrEii
-__ZN3KJS7UString3Rep6createEN3WTF10PassRefPtrIS1_EEii
-__ZN3KJS7TryNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS15LessNumbersNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS15DotAccessorNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS10NumberNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS7TryNode7executeEPNS_9ExecStateE
-__ZN3KJS21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS18PostIncResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18PostIncResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13ActivationImp18isActivationObjectEv
-__ZN3KJS13MathObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS21FunctionCallValueNode8evaluateEPNS_9ExecStateE
-__ZN3KJS12NotEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9FalseNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13ArrayInstance14deletePropertyEPNS_9ExecStateEj
-__ZNK3KJS11FunctionImp19implementsConstructEv
-__ZN3KJS11FunctionImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS9EqualNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS11FunctionImp9classInfoEv
-__ZNK3KJS4Node8toStringEv
-__ZNK3KJS9ScopeNode8streamToERNS_12SourceStreamE
-__ZN3KJS7UString6appendEt
-__ZN3KJS7UString6appendERKS0_
-__ZN3KJS7UString6appendEPKc
-__ZN3KJS7UString14expandCapacityEi
-__ZN3KJS12SourceStreamlsEPKNS_4NodeE
-__ZNK3KJS17ExprStatementNode8streamToERNS_12SourceStreamE
-__ZNK3KJS4Node21needsParensIfLeftmostEv
-__ZNK3KJS23FunctionCallResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13ArgumentsNode8streamToERNS_12SourceStreamE
-__ZNK3KJS16ArgumentListNode8streamToERNS_12SourceStreamE
-__ZNK3KJS11ResolveNode10precedenceEv
-__ZNK3KJS11ResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13AssignDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8ThisNode10precedenceEv
-__ZNK3KJS8ThisNode8streamToERNS_12SourceStreamE
-__ZNK3KJS19FunctionCallDotNode10precedenceEv
-__ZNK3KJS19FunctionCallDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS16FunctionBodyNode11paramStringEv
-__ZNK3KJS15RegExpObjectImp14arrayOfMatchesEPNS_9ExecStateE
-__ZN3KJS9Arguments17mappedIndexGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS13ArrayInstance9classInfoEv
-__ZN3KJS24substituteBackreferencesERKNS_7UStringES2_PiPNS_6RegExpE
-__ZNK3KJS15DotAccessorNode10precedenceEv
-__ZNK3KJS15DotAccessorNode8streamToERNS_12SourceStreamE
-__ZNK3KJS16VarStatementNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17AssignResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS6IfNode8streamToERNS_12SourceStreamE
-__ZNK3KJS14LogicalNotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9ArrayNode10precedenceEv
-__ZNK3KJS9ArrayNode8streamToERNS_12SourceStreamE
-__ZNK3KJS11ElementNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10StringNode10precedenceEv
-__ZNK3KJS10StringNode8streamToERNS_12SourceStreamE
-__ZN3KJS29escapeStringForPrettyPrintingERKNS_7UStringE
-__ZNK3KJS9BlockNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17AssignBracketNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10IfElseNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9EqualNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9EqualNode10precedenceEv
-__ZN3KJS35streamLeftAssociativeBinaryOperatorERNS_12SourceStreamENS_10PrecedenceEPKcPKNS_4NodeES7_
-__ZNK3KJS17ReadModifyDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7AddNode10precedenceEv
-__ZNK3KJS7AddNode8streamToERNS_12SourceStreamE
-__ZNK3KJS15ConditionalNode10precedenceEv
-__ZNK3KJS15ConditionalNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10RegExpNode10precedenceEv
-__ZNK3KJS10RegExpNode8streamToERNS_12SourceStreamE
-__ZNK3KJS21ReadModifyResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7TryNode8streamToERNS_12SourceStreamE
-__ZNK3KJS11NewExprNode10precedenceEv
-__ZNK3KJS11NewExprNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10NumberNode10precedenceEv
-__ZNK3KJS10NumberNode8streamToERNS_12SourceStreamE
-__ZN3KJS12SourceStreamlsEd
-__ZNK3KJS13LogicalOrNode10precedenceEv
-__ZNK3KJS13LogicalOrNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8NullNode10precedenceEv
-__ZNK3KJS8NullNode8streamToERNS_12SourceStreamE
-__ZNK3KJS14LogicalAndNode8streamToERNS_12SourceStreamE
-__ZNK3KJS14LogicalAndNode10precedenceEv
-__ZNK3KJS14LogicalNotNode10precedenceEv
-__ZN3KJS7UString17expandPreCapacityEi
-__ZN3KJS19BracketAccessorNode17evaluateToBooleanEPNS_9ExecStateE
-__ZNK3KJS11GreaterNode10precedenceEv
-__ZNK3KJS11GreaterNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17ObjectLiteralNode10precedenceEv
-__ZNK3KJS17ObjectLiteralNode8streamToERNS_12SourceStreamE
-__ZNK3KJS16PropertyListNode8streamToERNS_12SourceStreamE
-__ZNK3KJS12PropertyNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8LessNode10precedenceEv
-__ZNK3KJS8LessNode8streamToERNS_12SourceStreamE
-__ZNK3KJS19BracketAccessorNode10precedenceEv
-__ZNK3KJS19BracketAccessorNode8streamToERNS_12SourceStreamE
-__ZNK3KJS15TypeOfValueNode10precedenceEv
-__ZNK3KJS15TypeOfValueNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7ForNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9CommaNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17AssignResolveNode10precedenceEv
-__ZNK3KJS23FunctionCallResolveNode10precedenceEv
-__ZNK3KJS12FuncExprNode10precedenceEv
-__ZNK3KJS12FuncExprNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13ParameterNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9ForInNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10ReturnNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13GreaterEqNode10precedenceEv
-__ZNK3KJS13GreaterEqNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8TrueNode10precedenceEv
-__ZNK3KJS8TrueNode8streamToERNS_12SourceStreamE
-__ZNK3KJS21FunctionCallValueNode8streamToERNS_12SourceStreamE
-__ZN3KJS11ElementNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS8MultNode10precedenceEv
-__ZNK3KJS8MultNode8streamToERNS_12SourceStreamE
-__ZN3KJS21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS4List8getSliceEiRS0_
-__ZN3KJS10IfElseNode7executeEPNS_9ExecStateE
-__ZN3KJS6InNode17evaluateToBooleanEPNS_9ExecStateE
-__ZNK3KJS12NotEqualNode10precedenceEv
-__ZNK3KJS12NotEqualNode8streamToERNS_12SourceStreamE
-__ZN3KJS17AssignResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13DeleteDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS12ContinueNode7executeEPNS_9ExecStateE
-__ZN3KJS13DeleteDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS11FunctionImp14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3KJS11PropertyMap3getERKNS_10IdentifierERj
-__ZN3KJS11GreaterNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13PrefixDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13PreIncDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZNK3KJS8JSObject8toStringEPNS_9ExecStateE
-__ZNK3KJS8JSObject11toPrimitiveEPNS_9ExecStateENS_6JSTypeE
-__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
-__ZN3KJS22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3WTF9HashTableIiiNS_17IdentityExtractorIiEENS_7IntHashIiEENS_10HashTraitsIiEES6_E3addIPN3KJS16RuntimeObjectImpESB_NS_17HashSetTranslatorILb1ESB_NS5_ISB_EES6_NS_7PtrHashISB_EEEEEESt4pairINS_17HashTableIteratorIiiS2_S4_S6_S6_EEbERKT_RKT0_
-__ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE
-__ZN3KJS12NotEqualNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS14ErrorObjectImp19implementsConstructEv
-__ZN3KJS14ErrorObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS9Collector7collectEv
-__ZN3KJS9Collector31markCurrentThreadConservativelyEv
-__ZN3KJS9Collector30markStackObjectsConservativelyEPvS1_
-__ZN3KJS6JSCell4markEv
-__ZN3KJS8JSObject4markEv
-__ZNK3KJS11PropertyMap4markEv
-__ZN3KJS11FunctionImp4markEv
-__ZN3KJS14JSGlobalObject4markEv
-__ZN3KJS16JSVariableObject4markEv
-__ZN3KJS13ArrayInstance4markEv
-__ZN3KJS15JSWrapperObject4markEv
-__ZN3KJS13ActivationImp4markEv
-__ZN3KJS13ActivationImp12markChildrenEv
-__ZN3KJS14NativeErrorImp4markEv
-__ZN3KJS9Arguments4markEv
-__ZN3KJS9Collector20markProtectedObjectsEv
-__ZN3KJS9Collector5sweepILNS0_8HeapTypeE0EEEmb
-__ZN3KJS11PropertyMapD1Ev
-__ZN3KJS11FunctionImpD0Ev
-__ZN3KJS9StringImpD0Ev
-__ZN3KJS9RegExpImpD0Ev
-__ZN3KJS13ArrayInstanceD0Ev
-__ZN3KJS9ArgumentsD0Ev
-__ZN3KJS9Collector5sweepILNS0_8HeapTypeE1EEEmb
-__ZN3KJS14AddStringsNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17AddStringLeftNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9StringImp11toPrimitiveEPNS_9ExecStateENS_6JSTypeE
-__ZN3KJS7AddNode8evaluateEPNS_9ExecStateE
-__ZN3KJS21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS7UString8toUInt32EPb
-__ZN3KJS22ReadModifyLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19PostIncLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17PreDecResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18PreDecLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS8MultNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS9NumberImp4typeEv
-__ZN3KJS20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS7SubNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS9StringImp8toNumberEPNS_9ExecStateE
-__ZN3KJS18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS7JSValue15toInt32SlowCaseEPNS_9ExecStateERb
-__ZN3KJS24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS10formatTimeERKNS_17GregorianDateTimeEb
-__ZNK3KJS15RegExpObjectImp19implementsConstructEv
-__ZN3KJS15RegExpObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3KJS35stringInstanceNumericPropertyGetterEPNS_9ExecStateEPNS_8JSObjectEjRKNS_12PropertySlotE
-__ZN3KJS23FunctionCallResolveNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
-__ZN3KJS15dateToDayInYearEiii
-__ZN3KJS21ReadModifyBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZNK3KJS15ObjectObjectImp19implementsConstructEv
-__ZN3KJS21ReadModifyBracketNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9ExecState12hadExceptionEv
-__ZNK3KJS7JSValue8toObjectEPNS_9ExecStateE
-__ZNK3KJS7JSValue8toStringEPNS_9ExecStateE
-__ZN3KJS7UStringD1Ev
-__ZN3KJS8JSObject15getPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3KJS12PropertySlot8getValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierE
-__ZNK3WTF6RefPtrIN3KJS14ExpressionNodeEE3getEv
-__ZN3KJS3addEPNS_9ExecStateEPNS_7JSValueES3_
-__ZN3KJS10IdentifierD1Ev
-__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14ExpressionNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS9BreakNode7executeEPNS_9ExecStateE
-__ZN3KJS18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE
-__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3KJS5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEiiS6_
-__ZN3KJS14NativeErrorImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZNK3KJS6JSCell17getTruncatedInt32ERi
-__ZN3KJS15StringObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9Collector15recordExtraCostEm
-__ZN3KJS22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS8JSObject9classNameEv
-__ZN3KJS14PostDecDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS9CommaNodeD1Ev
-__ZN3KJS28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS6decodeEPNS_9ExecStateERKNS_4ListEPKcb
-__ZN3KJS19BracketAccessorNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS15TypeOfValueNodeD1Ev
-__ZN3KJS17PrototypeFunctionD0Ev
-__ZN3KJS13ErrorInstanceD0Ev
-__ZN3KJS18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23FunctionCallResolveNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS13GreaterEqNodeD1Ev
-__ZN3KJS7ModNodeD1Ev
-__ZN3KJS24LocalVarFunctionCallNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS4List15expandAndAppendEPNS_7JSValueE
-__ZN3WTF6VectorIPN3KJS7JSValueELm8EE15reserveCapacityEm
-__ZN3KJS10SwitchNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13CaseBlockNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14ClauseListNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14CaseClauseNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10SwitchNode7executeEPNS_9ExecStateE
-__ZN3KJS13CaseBlockNode12executeBlockEPNS_9ExecStateEPNS_7JSValueE
-__ZN3KJS18NotStrictEqualNode17evaluateToBooleanEPNS_9ExecStateE
-__Z23_NPN_CreateScriptObjectP4_NPPPN3KJS8JSObjectEN3WTF10PassRefPtrINS1_8Bindings10RootObjectEEE
-__NPN_CreateObject
-__Z10jsAllocateP4_NPPP7NPClass
-__NPN_RetainObject
-__NPN_Evaluate
-__ZNK3KJS8Bindings10RootObject12globalObjectEv
-__ZN3KJS8Bindings22convertNPStringToUTF16EPK9_NPStringPPtPj
-__ZN3KJS8Bindings36convertUTF8ToUTF16WithLatin1FallbackEPKciPPtPj
-__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
-__ZN3KJS11Interpreter8evaluateEPNS_9ExecStateERKNS_7UStringEiS5_PNS_7JSValueE
-__ZN3KJS8Bindings23convertValueToNPVariantEPNS_9ExecStateEPNS_7JSValueEP10_NPVariant
-__ZN3KJS11JSImmediate4typeEPKNS_7JSValueE
-__NPN_GetStringIdentifier
-__ZN3KJS8Bindings26identifierFromNPIdentifierEPKc
-__NPN_Invoke
-__ZN3KJS8Bindings14findRootObjectEPNS_14JSGlobalObjectE
-__NPN_ReleaseVariantValue
-__ZNK3KJS7UString10UTF8StringEb
+__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
+__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
+__ZN3JSC7UStringC1EPKti
+__ZN3JSC5Lexer7record8Ei
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE15reserveCapacityEm
+__ZN3JSC10Identifier6removeEPNS_7UString3RepE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EEaSERKS5_
+__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
+__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
+__ZN3JSC9Structure6removeERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC3JIT11emitCTICallEPFvPvzE
+__ZN3JSC11Interpreter15cti_op_new_funcEPvz
+__ZN3JSC12FuncDeclNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC11Interpreter10cti_op_endEPvz
+__ZN3JSC12FuncDeclNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12NodeReleaser21adoptFunctionBodyNodeERN3WTF6RefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC8JSObject4markEv
+__ZN3JSC14JSGlobalObject4markEv
+__ZN3JSC7JSArray4markEv
+__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC18GlobalEvalFunction4markEv
+__ZNK3JSC10NumberNode8isNumberEv
+__ZN3JSC5Lexer10scanRegExpEv
+__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE
+__ZL26appendToVarDeclarationListPvRPN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE15reserveCapacityEm
+__ZL20makeVarStatementNodePvPN3JSC14ExpressionNodeE
+__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii
+__Z21mergeDeclarationListsIPN3JSC20ParserRefCountedDataIN3WTF6VectorINS2_6RefPtrINS0_12FuncDeclNodeEEELm0EEEEEET_SA_SA_
+__ZN3JSC20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED1Ev
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZNK3JSC14ExpressionNode10isLocationEv
+__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
+__ZNK3JSC14ExpressionNode8isNumberEv
+__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8newLabelEv
+__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZNK3JSC14LogicalNotNode8opcodeIDEv
+__ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
+__ZN3WTF6VectorIjLm0EE15reserveCapacityEm
+__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
+__ZNK3JSC11GreaterNode8opcodeIDEv
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
+__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
+__ZN3JSC4WREC9Generator13compileRegExpEPNS_12JSGlobalDataERKNS_7UStringEPjPPKcRN3WTF6RefPtrINS_14ExecutablePoolEEEbb
+__ZN3JSC4WREC9Generator13generateEnterEv
+__ZN3JSC4WREC9Generator17generateSaveIndexEv
+__ZN3JSC4WREC6Parser16parseDisjunctionERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC6Parser16parseAlternativeERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC9Generator32generatePatternCharacterSequenceERNS_14MacroAssembler8JumpListEPim
+__ZN3JSC4WREC9Generator28generatePatternCharacterPairERNS_14MacroAssembler8JumpListEii
+__ZN3WTF6VectorIN3JSC14MacroAssembler4JumpELm16EE6appendIS3_EEvRKT_
+__ZN3JSC12X86Assembler7cmpl_irEiNS_3X8610RegisterIDE
+__ZN3JSC4WREC9Generator24generatePatternCharacterERNS_14MacroAssembler8JumpListEi
+__ZN3JSC4WREC9Generator21generateLoadCharacterERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC14CharacterClass7newlineEv
+__ZN3JSC4WREC6Parser29parseCharacterClassQuantifierERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassEb
+__ZN3JSC4WREC6Parser17consumeQuantifierEv
+__ZN3JSC4WREC9Generator24generateGreedyQuantifierERNS_14MacroAssembler8JumpListERNS0_19GenerateAtomFunctorEjj
+__ZN3JSC4WREC29GenerateCharacterClassFunctor12generateAtomEPNS0_9GeneratorERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC9Generator22generateCharacterClassERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassEb
+__ZN3JSC4WREC9Generator30generateCharacterClassInvertedERNS_14MacroAssembler8JumpListERKNS0_14CharacterClassE
+__ZN3JSC4WREC29GenerateCharacterClassFunctor9backtrackEPNS0_9GeneratorE
+__ZN3JSC4WREC9Generator18generateBacktrack1Ev
+__ZN3JSC15AssemblerBuffer4growEv
+__ZN3JSC12X86Assembler7addl_irEiNS_3X8610RegisterIDE
+__ZN3JSC4WREC9Generator21generateReturnSuccessEv
+__ZN3JSC4WREC9Generator22generateIncrementIndexEPNS_14MacroAssembler4JumpE
+__ZN3JSC4WREC9Generator27generateJumpIfNotEndOfInputENS_14MacroAssembler5LabelE
+__ZN3JSC4WREC9Generator21generateReturnFailureEv
+__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC18NotStrictEqualNode8opcodeIDEv
+__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC4WREC9Generator20generateAssertionBOLERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC6Parser13consumeEscapeEb
+__ZN3WTF6VectorIiLm8EE14expandCapacityEm
+__ZN3JSC4WREC6Parser16parseParenthesesERNS_14MacroAssembler8JumpListE
+__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
+__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
+__ZL11checkEscapePPKtS0_P9ErrorCodeib
+__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
+__ZN3JSC4WREC14CharacterClass6spacesEv
+__ZN3JSC4WREC6Parser23parseNonCharacterEscapeERNS_14MacroAssembler8JumpListERKNS0_6EscapeE
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDE
+__ZN3JSC4WREC9Generator35generateCharacterClassInvertedRangeERNS_14MacroAssembler8JumpListES4_PKNS0_14CharacterRangeEjPjPKtj
+__ZN3JSC4WREC9Generator20terminateAlternativeERNS_14MacroAssembler8JumpListES4_
+__ZN3JSC4WREC6Parser19parseCharacterClassERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC14CharacterClass8wordcharEv
+__ZN3JSC4WREC25CharacterClassConstructor6appendERKNS0_14CharacterClassE
+__ZN3JSC4WREC25CharacterClassConstructor5flushEv
+__ZN3JSC4WREC25CharacterClassConstructor9addSortedERN3WTF6VectorItLm0EEEt
+__ZN3WTF6VectorItLm0EE14expandCapacityEm
+__ZN3JSC4WREC25CharacterClassConstructor14addSortedRangeERN3WTF6VectorINS0_14CharacterRangeELm0EEEtt
+__ZN3WTF6VectorIN3JSC4WREC14CharacterRangeELm0EE14expandCapacityEm
+__ZN3JSC4WREC25CharacterClassConstructor3putEt
+__ZN3JSC4WREC9Generator20terminateDisjunctionERNS_14MacroAssembler8JumpListE
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
+__ZN3JSC16VarStatementNodeD1Ev
+__ZN3JSC16VarStatementNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17AssignResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17ObjectLiteralNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16PropertyListNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12PropertyNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11UnaryOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13LogicalOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12BinaryOpNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17AssignResolveNodeD1Ev
+__ZN3JSC17ObjectLiteralNodeD1Ev
+__ZN3JSC16PropertyListNodeD1Ev
+__ZN3JSC12PropertyNodeD1Ev
+__ZN3JSC14LogicalNotNodeD1Ev
+__ZN3JSC10RegExpNodeD1Ev
+__ZN3JSC13LogicalOpNodeD1Ev
+__ZN3JSC9EqualNodeD1Ev
+__ZN3JSC18NotStrictEqualNodeD1Ev
+__ZN3JSC6IfNodeD1Ev
+__ZN3JSC6IfNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13AssignDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC8WithNodeD1Ev
+__ZN3JSC8WithNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC21FunctionCallValueNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC21FunctionCallValueNodeD1Ev
+__ZN3JSC9ArrayNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ArrayNodeD1Ev
+__ZN3JSC11ElementNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10IfElseNodeD1Ev
+__ZN3JSC10IfElseNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC7AddNodeD1Ev
+__ZN3JSC11NewExprNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11NewExprNodeD1Ev
+__ZN3JSC3JIT21compilePutByIdHotPathEiPNS_10IdentifierEij
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE6appendIS2_EEvRKT_
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDES4_ii
+__ZN3JSC3JIT11emitCTICallEPFPNS_23JSValueEncodedAsPointerEPvzE
+__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
+__ZN3JSC3JIT23compileFastArith_op_addEPNS_11InstructionE
+__ZN3JSC3JIT22compilePutByIdSlowCaseEiPNS_10IdentifierEiRPNS_13SlowCaseEntryEj
+__ZN3JSC3JIT27compileOpConstructSetupArgsEPNS_11InstructionE
+__ZN3JSC3JIT11emitCTICallEPFPNS_8JSObjectEPvzE
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZN3JSC11Interpreter17cti_op_new_objectEPvz
+__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter16cti_op_put_by_idEPvz
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC11Interpreter12cti_op_jtrueEPvz
+__ZN3JSC11Interpreter10cti_op_notEPvz
+__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjEPNS3_9StructureENS3_28StructureTransitionTableHashENS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEE3addERKS7_RKS9_
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_PNS3_9StructureEENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E6rehashEi
+__ZN3JSC11Interpreter21cti_op_resolve_globalEPvz
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSString12toThisStringEPNS_9ExecStateE
+__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE
+__ZN3JSC11JSImmediate12nonInlineNaNEv
+__ZNK3JSC7UString4findERKS0_i
+__ZN3JSC11Interpreter11cti_op_lessEPvz
+__ZN3JSC11Interpreter17cti_op_new_regexpEPvz
+__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
+__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC6JSCell8isObjectEPKNS_9ClassInfoE
+__ZNK3JSC12RegExpObject9classInfoEv
+__ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
+__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF11OwnArrayPtrIiEE
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZNK3JSC7UString8toUInt32EPbb
+__ZNK3JSC7UString8toDoubleEbb
+__ZN3WTF6VectorIcLm32EE6resizeEm
+__ZN3JSC11Interpreter16cti_op_nstricteqEPvz
+__ZN3JSC10JSValuePtr19strictEqualSlowCaseES0_S0_
+__ZN3JSC11Interpreter19cti_op_new_func_expEPvz
+__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZNK3JSC19BracketAccessorNode10isLocationEv
+__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
+__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataERKNS_10IdentifierEPNS_14ExpressionNodeES7_PNS_13StatementNodeEiii
+__ZN3JSC19BracketAccessorNodeD1Ev
+__ZN3JSC19BracketAccessorNode12releaseNodesERNS_12NodeReleaserE
+__ZNK3JSC9ForInNode6isLoopEv
+__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC20EvalFunctionCallNodeD1Ev
+__ZN3JSC20EvalFunctionCallNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC3JIT26compileOpCallEvalSetupArgsEPNS_11InstructionE
+__ZN3JSC11Interpreter24cti_op_resolve_with_baseEPvz
+__ZN3JSC11Interpreter16cti_op_call_evalEPvz
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_10JSValuePtrE
+__ZNK3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3getEPS4_
+__ZN3JSC7UString3Rep11computeHashEPKti
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS1_INS2_8EvalNodeEEEENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6rehashEi
+__ZN3JSC9ExecState9thisValueEv
+__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_10JSValuePtrE
+__ZN3JSC8EvalNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
+__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC10formatTimeERKNS_17GregorianDateTimeEb
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZN3JSC9BreakNodeD1Ev
+__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZL18makeRightShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC4WREC14CharacterClass6digitsEv
+__ZNK3JSC14RightShiftNode8opcodeIDEv
+__ZN3JSC14RightShiftNodeD1Ev
+__ZN3JSC3JIT26compileFastArith_op_rshiftEjjj
+__ZN3JSC3JIT30compileFastArithSlow_op_rshiftEjjjRPNS_13SlowCaseEntryE
+__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
+__ZN3JSCL15dateToDayInYearEiii
+__ZN3JSC8EvalNode4markEv
+__ZN3JSC19JSStaticScopeObjectD0Ev
+__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18PostfixBracketNodeD1Ev
+__ZN3JSC18PostfixBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataEPNS_14ExpressionNodeES4_PNS_13StatementNodeE
+__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyBracketNodeD1Ev
+__ZN3JSC21ReadModifyBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSObject9classNameEv
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter28cti_op_get_by_id_string_failEPvz
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter16cti_op_is_numberEPvz
+__ZNK3JSC12StringObject9classInfoEv
+__ZN3JSC11Interpreter16cti_op_is_objectEPvz
+__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_14StructureChainEmmPNS_9ExecStateE
+__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
+__ZNK3JSC6JSCell17getTruncatedInt32ERi
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZNK3JSC12JSNumberCell9toBooleanEPNS_9ExecStateE
+__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
+__ZN3JSC11Interpreter10cti_op_subEPvz
+__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
+__ZNK3JSC7UString10UTF8StringEb
__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
-__Z35NPN_InitializeVariantWithStringCopyP10_NPVariantPK9_NPString
-__ZN3KJS7CStringD1Ev
-__NPN_ReleaseObject
-__Z12jsDeallocateP8NPObject
-__ZN3KJS8Bindings10RootObject11gcUnprotectEPNS_8JSObjectE
-__ZN3KJS6JSLock12DropAllLocksC1Ev
-__ZN3KJS6JSLock12DropAllLocksD1Ev
-_pow5mult
-_quorem
-_diff
-__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE14expandCapacityEm
-__ZN3WTF6VectorIPN3KJS12FuncDeclNodeELm16EE15reserveCapacityEm
-__ZN3KJS10NumberNode8setValueEd
-__ZN3KJS11ResolveNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS12NotEqualNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14InstanceOfNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS17PreIncResolveNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9NumberImp9toBooleanEPNS_9ExecStateE
-__ZN3KJS10LessEqNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS10LessEqNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13UnaryPlusNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17DeleteBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17DeleteBracketNode8evaluateEPNS_9ExecStateE
-__ZN3KJS20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17staticValueGetterINS_13MathObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3KJS13MathObjectImp16getValuePropertyEPNS_9ExecStateEi
-__NPN_DeallocateObject
-__ZN3KJS14PostIncDotNodeD1Ev
-__ZN3KJS22ReadModifyLocalVarNodeD1Ev
-__ZN3KJS10LessEqNodeD1Ev
-__ZN3KJS18PostDecResolveNodeD1Ev
-__ZN3KJS17DeleteBracketNodeD1Ev
-__ZN3KJS18PostIncResolveNodeD1Ev
-__ZN3KJS14InstanceOfNodeD1Ev
-__ZN3KJS10NegateNodeD1Ev
-__ZN3KJS17PreDecResolveNodeD1Ev
-__ZN3KJS21ReadModifyBracketNodeD1Ev
-__ZN3KJS10BitAndNodeD1Ev
-__ZN3KJS9BitOrNodeD1Ev
-__ZN3KJS14RightShiftNodeD1Ev
-__ZN3KJS13LeftShiftNodeD1Ev
-__ZN3KJS13UnaryPlusNodeD1Ev
-__ZN3KJS13MathObjectImpD0Ev
-__ZN3KJS14NativeErrorImpD0Ev
-__ZN3KJS14ErrorObjectImpD0Ev
-__ZN3KJS15RegExpObjectImpD0Ev
-__ZN3KJS17DateObjectFuncImpD0Ev
-__ZN3KJS13DateObjectImpD0Ev
-__ZN3KJS15NumberObjectImpD0Ev
-__ZN3KJS16BooleanObjectImpD0Ev
-__ZN3KJS19StringObjectFuncImpD0Ev
-__ZN3KJS15StringObjectImpD0Ev
-__ZN3KJS14ArrayObjectImpD0Ev
-__ZN3KJS17FunctionObjectImpD0Ev
-__ZN3KJS15ObjectObjectImpD0Ev
-__ZN3KJS20NativeErrorPrototypeD0Ev
-__ZN3KJS15RegExpPrototypeD0Ev
-__ZN3KJS15NumberPrototypeD0Ev
-__ZN3KJS16BooleanPrototypeD0Ev
-__ZN3KJS15StringPrototypeD0Ev
-__ZN3KJS15ObjectPrototypeD0Ev
-__ZN3KJS17FunctionPrototypeD0Ev
-__ZN3KJS13PreIncDotNodeD1Ev
-__ZN3KJS17staticValueGetterINS_15RegExpObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3KJS15RegExpObjectImp16getValuePropertyEPNS_9ExecStateEi
-__ZNK3KJS15RegExpObjectImp10getBackrefEj
-__ZN3KJS16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17staticValueGetterINS_15NumberObjectImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3KJS15NumberObjectImp16getValuePropertyEPNS_9ExecStateEi
-__ZN3KJS10NegateNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10NegateNode8evaluateEPNS_9ExecStateE
-__ZN3KJS25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS10LessEqNode8evaluateEPNS_9ExecStateE
-__ZN3KJS8JSObject15getPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZNK3KJS12PropertySlot8getValueEPNS_9ExecStateEPNS_8JSObjectEj
-__ZN3KJS16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS10Identifier5equalEPKNS_7UString3RepEPKc
-__ZN3KJS11addSlowCaseEPNS_9ExecStateEPNS_7JSValueES3_
-__ZN3KJS8LessNode8evaluateEPNS_9ExecStateE
-__ZN3KJS7DivNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS10NegateNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS7AddNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3WTF6VectorIPN3KJS9ExecStateELm16EE14expandCapacityEm
-__ZN3WTF6VectorIPN3KJS9ExecStateELm16EE15reserveCapacityEm
-__ZN3KJS17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS6encodeEPNS_9ExecStateERKNS_4ListEPKc
-__ZN3KJS17PrefixBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17PreIncBracketNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14AddNumbersNode8evaluateEPNS_9ExecStateE
-__ZN3KJS18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13ArrayInstance4sortEPNS_9ExecStateEPNS_8JSObjectE
-__ZN3KJS13ArrayInstance17compactForSortingEv
-__ZN3KJS34compareWithCompareFunctionForQSortEPKvS1_
-__ZN3KJS13ArrayInstance4sortEPNS_9ExecStateE
-__ZN3KJS16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15NumberObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS9NumberImp8toObjectEPNS_9ExecStateE
-__ZN3KJS16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14ExpressionNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS11DoWhileNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13PreDecDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS18PostfixBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18PostIncBracketNode8evaluateEPNS_9ExecStateE
-__ZN3KJS13LeftShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NegateNode8opcodeIDEv
+__ZN3JSC10NegateNodeD1Ev
+__ZN3JSC11Interpreter13cti_op_negateEPvz
+__ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11JSImmediate12toThisObjectENS_10JSValuePtrEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter12cti_op_jlessEPvz
+__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
+__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12JSNumberCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE
+__ZN3JSC11Interpreter10cti_op_modEPvz
+__ZL17makeLeftShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZNK3JSC13LeftShiftNode8opcodeIDEv
+__ZN3JSC13LeftShiftNodeD1Ev
+__ZN3JSC3JIT26compileFastArith_op_lshiftEjjj
+__ZN3JSC3JIT30compileFastArithSlow_op_lshiftEjjjRPNS_13SlowCaseEntryE
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC10BitAndNode8opcodeIDEv
+__ZN3JSC10BitAndNodeD1Ev
+__ZN3JSC3JIT26compileFastArith_op_bitandEjjj
+__ZN3JSC3JIT30compileFastArithSlow_op_bitandEjjjRPNS_13SlowCaseEntryE
+__ZN3JSC11Interpreter13cti_op_bitandEPvz
+__ZNK3JSC14BitwiseNotNode8opcodeIDEv
+__ZN3JSC14BitwiseNotNodeD1Ev
+__ZN3JSC11Interpreter13cti_op_lshiftEPvz
+__ZN3JSC11Interpreter13cti_op_bitnotEPvz
+__ZNK3JSC22UnsignedRightShiftNode8opcodeIDEv
+__ZNK3JSC10BitXOrNode8opcodeIDEv
+__ZN3JSC22UnsignedRightShiftNodeD1Ev
+__ZN3JSC10BitXOrNodeD1Ev
+__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter14cti_op_urshiftEPvz
+__ZNK3JSC12JSNumberCell18getTruncatedUInt32ERj
+__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC6JSCell18getTruncatedUInt32ERj
+__ZN3JSC11Interpreter12cti_op_bitorEPvz
+__ZNK3JSC12JSNumberCell17getTruncatedInt32ERi
+__ZNK3JSC9BitOrNode8opcodeIDEv
+__ZN3JSC9BitOrNodeD1Ev
+__ZN3JSC11Interpreter13cti_op_rshiftEPvz
+__ZN3JSC11Interpreter13cti_op_bitxorEPvz
+__ZN3JSC9parseDateERKNS_7UStringE
+__ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter19cti_op_resolve_skipEPvz
+__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
+__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
+__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
+__ZNK3JSC10StringNode8isStringEv
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
+__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
+__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
+__ZN3JSC10SwitchNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13CaseBlockNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC14ClauseListNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC14CaseClauseNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10SwitchNodeD1Ev
+__ZN3JSC13CaseBlockNodeD1Ev
+__ZN3JSC14ClauseListNodeD1Ev
+__ZN3JSC14CaseClauseNodeD1Ev
+__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
+__ZN3WTF6VectorIPvLm0EE15reserveCapacityEm
+__ZN3JSC11Interpreter18cti_op_switch_charEPvz
+__ZN3JSC8EvalNodeD1Ev
+__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF6VectorIcLm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEm
+__ZN3WTF17TCMalloc_PageHeap3NewEm
+__ZN3JSC7JSArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState10arrayTableEPS0_
+__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC7ArgList10slowAppendENS_10JSValuePtrE
+__ZN3WTF7HashSetIPN3JSC7ArgListENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC7ArgListES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF6VectorIN3JSC8RegisterELm8EE15reserveCapacityEm
+__ZN3JSC22JSPropertyNameIterator4markEv
+__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataE
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
+__ZN3JSCltERKNS_7UStringES2_
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
+__ZN3JSC4WREC9Generator29generateAssertionWordBoundaryERNS_14MacroAssembler8JumpListEb
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDES3_ii
+__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
__ZN3WTF7Unicode18UTF8SequenceLengthEc
__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
-__ZN3KJS9StringImp18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
-__ZN3KJSltERKNS_7UStringES2_
-__ZN3KJS15ConditionalNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS10BitAndNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10BitAndNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS15DotAccessorNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS19ImmediateNumberNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS13ArrayInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS18LocalVarAccessNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS13LeftShiftNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS19BracketAccessorNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS14RightShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14RightShiftNode8evaluateEPNS_9ExecStateE
-__ZN3KJS7AddNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS19ImmediateNumberNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS13LeftShiftNode8evaluateEPNS_9ExecStateE
-__ZN3KJS18LocalVarAccessNode16evaluateToUInt32EPNS_9ExecStateE
-__ZNK3KJS9NumberImp17getTruncatedInt32ERi
-__ZN3KJS19BracketAccessorNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS16BooleanObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14BitwiseNotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9BitOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9BitOrNode8evaluateEPNS_9ExecStateE
-__ZN3KJS10BitAndNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14BitwiseNotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15NumberObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Bindings9CInstanceC2EP8NPObjectN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Bindings8InstanceC2EN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZNK3KJS8Bindings8Instance10rootObjectEv
-__ZN3KJS8Bindings8Instance19createRuntimeObjectEPS1_
-__ZN3KJS16RuntimeObjectImpC2EPNS_8Bindings8InstanceE
-__ZN3KJS8Bindings10RootObject16addRuntimeObjectEPNS_16RuntimeObjectImpE
-__ZN3KJS16RuntimeObjectImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS8Bindings9CInstance5beginEv
-__ZNK3KJS8Bindings9CInstance8getClassEv
-__ZN3KJS8Bindings6CClass11classForIsAEP7NPClass
-__ZN3KJS8Bindings6CClassC2EP7NPClass
-__ZNK3KJS8Bindings6CClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE
-__ZNK3KJS7UString5asciiEv
-__ZNK3KJS8Bindings6CClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE
-__NPN_UTF8FromIdentifier
-__ZN3KJS8Bindings5Class14fallbackObjectEPNS_9ExecStateEPNS0_8InstanceERKNS_10IdentifierE
-__ZN3KJS8Bindings9CInstance3endEv
-__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE14expandCapacityEmPKS4_
-__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE14expandCapacityEm
-__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EE15reserveCapacityEm
-__ZN3KJS16RuntimeObjectImp12methodGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS13RuntimeMethodC2EPNS_9ExecStateERKNS_10IdentifierERN3WTF6VectorIPNS_8Bindings6MethodELm0EEE
-__ZN3WTF6VectorIPN3KJS8Bindings6MethodELm0EEC2ERKS5_
-__ZN3KJS13RuntimeMethod14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS16RuntimeObjectImp9classInfoEv
-__ZN3KJS8Bindings9CInstance12invokeMethodEPNS_9ExecStateERKN3WTF6VectorIPNS0_6MethodELm0EEERKNS_4ListE
-__ZNK3KJS8Bindings7CMethod4nameEv
-__ZN3KJS8Bindings23convertNPVariantToValueEPNS_9ExecStateEPK10_NPVariantPNS0_10RootObjectE
-__ZN3KJS16RuntimeObjectImpD2Ev
-__ZN3KJS8Bindings10RootObject19removeRuntimeObjectEPNS_16RuntimeObjectImpE
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_RKNS_10IdentifierE
-__ZN3KJS10substituteERNS_7UStringERKS0_
-__ZN3KJS4Node16rethrowExceptionEPNS_9ExecStateE
-__ZN3KJS4Node15handleExceptionEPNS_9ExecStateEPNS_7JSValueE
-__ZN3KJS16RuntimeObjectImp10invalidateEv
-__ZN3KJS16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS14JSGlobalObjectD2Ev
-__ZN3KJS15GlobalExecStateD1Ev
-__ZN3KJS14BitwiseNotNodeD1Ev
-__ZN3KJSplERKNS_7UStringES2_
-__ZN3KJS5Lexer14convertUnicodeEiiii
-__ZN3KJS14ArrayObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9Arguments3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_E3addIjS2_NS_22IdentityHashTranslatorIjS2_S6_EEEES1_INS_17HashTableIteratorIjS2_S4_S6_SB_S9_EEbERKT_RKT0_
-__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_EC2ERKSC_
-__ZN3KJS23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3WTF9HashTableIjSt4pairIjiENS_18PairFirstExtractorIS2_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENS8_IiEEEES9_E4findIjNS_22IdentityHashTranslatorIjS2_S6_EEEENS_17HashTableIteratorIjS2_S4_S6_SB_S9_EERKT_
-__ZN3KJS10BitXOrNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS10BitXOrNode8evaluateEPNS_9ExecStateE
-__ZN3KJS14RightShiftNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS10BitXOrNodeD1Ev
-__ZN3KJS17DateObjectFuncImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9parseDateERKNS_7UStringE
-__ZN3KJS6RegExp6createERKNS_7UStringE
-__ZN3KJS7ModNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS16RuntimeObjectImp14implementsCallEv
-__ZNK3KJS8Bindings9CInstance14implementsCallEv
-__ZN3KJS11Interpreter21shouldPrintExceptionsEv
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcRKNS_10IdentifierE
-__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_
-__ZN3KJS15SavedPropertiesD1Ev
-__ZN3KJS8JSObject18isActivationObjectEv
-__ZN3KJS19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS14JSGlobalObject15restoreBuiltinsERKNS_13SavedBuiltinsE
-__ZN3KJS11PropertyMap7restoreERKNS_15SavedPropertiesE
-__ZN3KJS16JSVariableObject19restoreLocalStorageERKNS_15SavedPropertiesE
-__ZN3WTF6VectorIN3KJS17LocalStorageEntryELm32EE6resizeEm
-__ZNK3KJS23FunctionCallBracketNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17TypeOfResolveNode10precedenceEv
-__ZNK3KJS17TypeOfResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13AssignDotNode10precedenceEv
-__ZNK3KJS12ContinueNode8streamToERNS_12SourceStreamE
-__ZN3KJS11FunctionImp12callerGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS9BreakNodeC1ERKNS_10IdentifierE
-__ZN3KJS13StatementNode9pushLabelERKNS_10IdentifierE
-__ZN3KJS10LabelStack4pushERKNS_10IdentifierE
-__ZN3KJS9ThrowNode7executeEPNS_9ExecStateE
-__ZNK3KJS15NumberObjectImp19implementsConstructEv
-__ZN3KJS22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8VoidNodeD1Ev
-__ZN3KJS14ErrorObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21ReadModifyResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15StrictEqualNode8evaluateEPNS_9ExecStateE
-__ZN3KJS27compareByStringPairForQSortEPKvS1_
-__ZN3KJS7compareERKNS_7UStringES2_
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_S8_
-__ZN3KJS21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS15StringObjectImp19implementsConstructEv
-__ZN3KJS15StringObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS18PostDecResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23setNewValueFromDateArgsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListEib
-__ZN3KJS20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23setNewValueFromTimeArgsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListEib
-__ZN3KJS23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
-__ZN3KJS20dateProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS18integer_part_noexpEd
-__ZN3KJS14AddNumbersNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS14InstanceOfNode10precedenceEv
-__ZNK3KJS14InstanceOfNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE
-__Z15kjs_pcre_xclassiPKh
-__ZN3KJS10NumberNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS18PostDecBracketNodeD1Ev
-__ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE
-__ZN3KJS22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13LeftShiftNode15evaluateToInt32EPNS_9ExecStateE
-__ZNK3KJS9RegExpImp14implementsCallEv
-__ZN3KJS22stringProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15ConditionalNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS11DoWhileNode7executeEPNS_9ExecStateE
-__ZN3KJS8Bindings23convertObjcValueToValueEPNS_9ExecStateEPvNS0_13ObjcValueTypeEPNS0_10RootObjectE
-__ZN3KJS8Bindings17webUndefinedClassEv
-__ZN3KJS8Bindings20webScriptObjectClassEv
-__ZN3KJS8Bindings8Instance19createRuntimeObjectENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Bindings12ObjcInstanceC2EP11objc_objectN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Bindings8Instance18didExecuteFunctionEv
-__ZN3KJS8Bindings12ObjcInstance5beginEv
-__ZNK3KJS8Bindings12ObjcInstance8getClassEv
-__ZN3KJS8Bindings9ObjcClass11classForIsAEP10objc_class
-__ZN3KJS8Bindings9ObjcClassC2EP10objc_class
-__ZNK3KJS8Bindings9ObjcClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE
-__ZNK3KJS8Bindings9ObjcClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE
-__ZN3KJS8Bindings25convertJSMethodNameToObjcEPKcPcm
-__ZN3KJS8Bindings10ObjcMethodC2EP10objc_classPKc
-__ZN3KJS8Bindings12ObjcInstance3endEv
-__ZN3KJS8Bindings12ObjcInstance12invokeMethodEPNS_9ExecStateERKN3WTF6VectorIPNS0_6MethodELm0EEERKNS_4ListE
-__ZNK3KJS8Bindings10ObjcMethod18getMethodSignatureEv
-__ZNK3KJS8Bindings10ObjcMethod4nameEv
-__ZN3KJS8Bindings20objcValueTypeForTypeEPKc
-__ZN3KJS8Bindings23convertValueToObjcValueEPNS_9ExecStateEPNS_7JSValueENS0_13ObjcValueTypeE
-__ZNK3KJS6JSCell9getStringEv
-__ZN3KJS8Bindings23convertNSStringToStringEP8NSString
-__ZN3KJS8Bindings12ObjcInstanceD1Ev
-__ZN3KJS9LabelNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS9LabelNode7executeEPNS_9ExecStateE
-__ZN3KJS12ContinueNodeC1ERKNS_10IdentifierE
-__ZN3KJS11FunctionImp12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS9BitOrNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS18EmptyStatementNode7executeEPNS_9ExecStateE
-__ZN3KJS22UnsignedRightShiftNodeD1Ev
-__ZN3KJS7ModNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS6InNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS10LessEqNode10precedenceEv
-__ZNK3KJS10LessEqNode8streamToERNS_12SourceStreamE
-__ZNK3KJS18NotStrictEqualNode10precedenceEv
-__ZNK3KJS18NotStrictEqualNode8streamToERNS_12SourceStreamE
-__ZN3KJS14StringInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3KJS7UString4fromEi
-__ZN3KJS14StringInstance11indexGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22UnsignedRightShiftNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS11ResolveNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS19FunctionCallDotNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS22UnsignedRightShiftNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS11ResolveNode16evaluateToUInt32EPNS_9ExecStateE
-__ZNK3KJS9NumberImp18getTruncatedUInt32ERj
-__ZN3KJS10NumberNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS7SubNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS14BitwiseNotNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS10BitAndNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS7AddNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS7SubNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS8VoidNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS8VoidNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17DeleteResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18LocalVarDeleteNodeD1Ev
-__ZN3KJS11FunctionImp15argumentsGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS18LocalVarDeleteNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17DeleteResolveNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS16RuntimeObjectImp6canPutEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS13UnaryPlusNode8evaluateEPNS_9ExecStateE
-__ZN3KJS24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS11NewExprNode16evaluateToNumberEPNS_9ExecStateE
-__Z22kjs_pcre_ucp_othercasej
-__ZN3KJS17PreDecResolveNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS7JSValue7toFloatEPNS_9ExecStateE
-__ZN3KJS14ExpressionNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS4List26markProtectedListsSlowCaseEv
-__ZNK3KJS6JSCell9getStringERNS_7UStringE
-__ZN3KJS8TrueNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS9RegExpImp3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-__ZNK3KJS9NumberImp9getUInt32ERj
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueEPS0_
-__ZN3KJS23FunctionCallResolveNode15evaluateToInt32EPNS_9ExecStateE
-__ZNK3KJS6JSCell18getTruncatedUInt32ERj
-__ZNK3KJS9LabelNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17ObjectLiteralNode21needsParensIfLeftmostEv
-__ZNK3KJS11DoWhileNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17PreDecResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13PreIncDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13PreDecDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17DeleteResolveNode8streamToERNS_12SourceStreamE
-__ZN3KJS9FalseNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS14PostIncDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS8Bindings12ObjcInstance14implementsCallEv
-__ZN3KJS8Bindings9ObjcClass14fallbackObjectEPNS_9ExecStateEPNS0_8InstanceERKNS_10IdentifierE
-__ZN3KJS16BooleanObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS11jsUndefinedEv
-___tcf_2
-___tcf_6
-___tcf_0
-___tcf_5
-___tcf_3
-___tcf_4
+__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC12JSNumberCell8toObjectEPNS_9ExecStateE
+__ZN3JSC15constructNumberEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12JSNumberCell11getJSNumberEv
+__ZN3JSCL16integerPartNoExpEd
+__ZN3JSC11Interpreter27cti_op_get_by_id_proto_failEPvz
+__ZN3WTF6VectorIPN3JSC10RegisterIDELm32EE14expandCapacityEm
+__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7JSArray3popEv
+__ZNK3JSC11DoWhileNode6isLoopEv
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11DoWhileNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11DoWhileNodeD1Ev
+__ZN3JSC11Interpreter17cti_op_switch_immEPvz
+__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
+__ZN3JSC13UnaryPlusNodeD1Ev
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callNumberConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter15cti_op_post_incEPvz
+__ZN3JSCL23stringProtoFuncFontsizeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_10JSValuePtrERKNS_7ArgListEib
+__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter21cti_op_loop_if_lesseqEPvz
+__ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC4WREC9Generator36generateParenthesesInvertedAssertionERNS_14MacroAssembler8JumpListE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC11Interpreter17cti_op_is_booleanEPvz
+__ZNK3JSC12JSNumberCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC4WREC14CharacterClass9nonspacesEv
+__ZN3JSC4Heap15recordExtraCostEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE15reserveCapacityEm
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_14OffsetLocationEENS_18PairFirstExtractorIS8_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSE_IS7_EEEESF_EC2ERKSI_
+__ZN3JSC11Interpreter20cti_op_switch_stringEPvz
+__ZNK3JSC12JSNumberCell12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12NumberObject11getJSNumberEv
+__ZNK3JSC13UnaryPlusNode8opcodeIDEv
+__ZN3WTF12detachThreadEj
+__ZN3WTFL26pthreadHandleForIdentifierEj
+__ZN3WTFL31clearPthreadHandleForIdentifierEj
+__ZN3WTF15ThreadConditionD1Ev
+__ZN3WTF23waitForThreadCompletionEjPPv
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3WTF14FastMallocZone10statisticsEP14_malloc_zone_tP19malloc_statistics_t
+__ZN3JSC4Heap26protectedGlobalObjectCountEv
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE
+__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12newTemporaryEv
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS7_EEEESE_E6expandEv
+__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10StringNodeD1Ev
+__ZN3JSC16ArgumentListNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16ArgumentListNodeD1Ev
+__ZN3JSC11Interpreter19cti_op_resolve_baseEPvz
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZNK3JSC8JSString8toStringEPNS_9ExecStateE
+__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC13ParameterNode12releaseNodesERNS_12NodeReleaserE
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EEaSERKS5_
+__ZNK3JSC7UString14toStrictUInt32EPb
+__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
+__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC14ExpressionNode14stripUnaryPlusEv
+__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
+__ZN3WTF9HashTableIdSt4pairIdN3JSC10JSValuePtrEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
+__ZNK3JSC7AddNode8opcodeIDEv
+__ZNK3JSC8MultNode8opcodeIDEv
+__ZN3JSC10NumberNodeD1Ev
+__ZN3JSC8MultNodeD1Ev
+__ZN3JSC3JIT23compileFastArith_op_mulEPNS_11InstructionE
+__ZN3JSC14MacroAssembler4jz32ENS_3X8610RegisterIDENS0_5Imm32E
+__ZN3JSC12X86Assembler7subl_irEiNS_3X8610RegisterIDE
+__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE
+__ZN3JSC9CodeBlock19isKnownNotImmediateEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDEi
+__ZN3JSC12X86Assembler8sarl_i8rEiNS_3X8610RegisterIDE
+__ZN3JSC15AssemblerBuffer7putByteEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDE
+__ZN3JSC3JIT42putDoubleResultToJSNumberCellOrJSImmediateENS_3X8613XMMRegisterIDENS1_10RegisterIDEjPNS_12X86Assembler6JmpSrcES2_S3_S3_
+__ZN3JSC3JIT27compileFastArithSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT27compileFastArithSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesE
+__ZN3JSC11Interpreter31cti_op_construct_NotJSConstructEPvz
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12DateInstance9classInfoEv
+__ZN3JSC11Interpreter10cti_op_addEPvz
+__ZN3JSC12jsNumberCellEPNS_12JSGlobalDataEd
+__ZNK3JSC12JSNumberCell8toNumberEPNS_9ExecStateE
+__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC9BlockNode7isBlockEv
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9BlockNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10JSFunction4markEv
+__ZN3JSC16FunctionBodyNode4markEv
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator19emitResolveFunctionEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZNK3JSC12NotEqualNode8opcodeIDEv
+__ZNK3JSC8LessNode8opcodeIDEv
+__ZN3JSC23FunctionCallResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC23FunctionCallResolveNodeD1Ev
+__ZN3JSC12NotEqualNodeD1Ev
+__ZN3JSC8LessNodeD1Ev
+__ZN3JSC11Interpreter19cti_op_resolve_funcEPvz
+__ZN3JSC11Interpreter22cti_op_call_JSFunctionEPvz
+__ZN3JSC16FunctionBodyNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser14reparseInPlaceEPNS_12JSGlobalDataEPNS_16FunctionBodyNodeE
+__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_10JSValuePtrE
+__ZNK3JSC13StatementNode12isReturnNodeEv
+__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
+__ZN3JSC11Interpreter23cti_vm_dontLazyLinkCallEPvz
+__ZN3JSC11Interpreter23cti_register_file_checkEPvz
+__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
+__ZNK3JSC13StatementNode7isBlockEv
+__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZN3JSC10ReturnNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC10ReturnNodeD1Ev
+__ZN3JSC11concatenateEPNS_7UString3RepES2_
+__ZN3JSC11Interpreter23cti_op_get_by_id_secondEPvz
+__ZN3JSC11Interpreter18tryCTICacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_10JSValuePtrERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_mPvPNS_9ExecStateE
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiPv
+__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC9CodeBlock4markEv
+__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter28cti_op_construct_JSConstructEPvz
+__ZN3JSC8JSObject17createInheritorIDEv
+__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZNK3JSC7ForNode6isLoopEv
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC7ForNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC7ForNodeD1Ev
+__ZN3JSC18PostfixResolveNodeD1Ev
+__ZN3JSC17AssignBracketNodeD1Ev
+__ZN3JSC17AssignBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC8ThisNodeD1Ev
+__ZN3JSC3JIT27compileFastArith_op_pre_incEj
+__ZN3JSC12X86Assembler2joEv
+__ZN3JSC3JIT19emitSlowScriptCheckEv
+__ZN3JSC3JIT31compileFastArithSlow_op_pre_incEjRPNS_13SlowCaseEntryE
+__ZN3JSC11Interpreter22cti_op_call_arityCheckEPvz
+__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter17cti_op_get_by_valEPvz
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC11Interpreter17cti_op_put_by_valEPvz
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC11Interpreter24cti_op_get_by_id_genericEPvz
+__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSC21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSCL12getDSTOffsetEdd
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11concatenateEPNS_7UString3RepEi
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyResolveNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZL11makeSubNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10LessEqNode8opcodeIDEv
+__ZNK3JSC7SubNode8opcodeIDEv
+__ZN3JSC10LessEqNodeD1Ev
+__ZN3JSC7SubNodeD1Ev
+__ZN3JSC3JIT23compileFastArith_op_subEPNS_11InstructionE
+__ZN3JSC3JIT27compileFastArithSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter13cti_op_lesseqEPvz
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC13GreaterEqNode8opcodeIDEv
+__ZN3JSC13GreaterEqNodeD1Ev
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E4findIS5_NS_22IdentityHashTranslatorIS5_S8_SB_EEEENS_17HashTableIteratorIS5_S8_SA_SB_SG_SE_EERKT_
+__ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
+__ZN3JSC11Interpreter9cti_op_eqEPvz
+__ZN3JSCeqERKNS_7UStringES2_
+__ZN3JSC11Interpreter17cti_op_push_scopeEPvz
+__ZN3JSC11Interpreter14cti_op_resolveEPvz
+__ZN3JSC11Interpreter16cti_op_pop_scopeEPvz
+__ZN3JSC8NullNodeD1Ev
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_PNS_5LabelE
+__ZN3JSC9ForInNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter17cti_op_get_pnamesEPvz
+__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9Structure26getEnumerablePropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayEPNS_8JSObjectE
+__ZN3JSC9Structure34getEnumerablePropertyNamesInternalERNS_17PropertyNameArrayE
+__ZNK3JSC6JSCell9classInfoEv
+__ZN3JSC9Structure26createCachedPrototypeChainEv
+__ZN3JSC14StructureChainC1EPNS_9StructureE
+__ZN3JSC11Interpreter17cti_op_next_pnameEPvz
+__ZN3JSC23structureChainsAreEqualEPNS_14StructureChainES1_
+__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC11Interpreter10cti_op_neqEPvz
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE
+__ZN3JSC7UString4fromEi
+__ZN3JSC7UString6appendERKS0_
+__ZN3JSC22JSPropertyNameIterator10invalidateEv
+__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCplERKNS_7UStringES2_
+__ZN3JSC14ExecutablePool13systemReleaseERKNS0_10AllocationE
+__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
+__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC9WhileNode6isLoopEv
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9WhileNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13PrefixDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13PrefixDotNodeD1Ev
+__ZN3JSC9WhileNodeD1Ev
+__ZN3JSC3JIT28compileFastArith_op_post_incEjj
+__ZN3JSC3JIT32compileFastArithSlow_op_post_incEjjRPNS_13SlowCaseEntryE
+__ZN3JSC11Interpreter22cti_op_push_activationEPvz
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC7DivNode8opcodeIDEv
+__ZN3JSC15ConditionalNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC15ConditionalNodeD1Ev
+__ZN3JSC7DivNodeD1Ev
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj
+__ZN3JSC11Interpreter23cti_op_put_by_val_arrayEPvz
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter10cti_op_divEPvz
+__ZN3JSC3JIT16patchGetByIdSelfEPNS_17StructureStubInfoEPNS_9StructureEmPv
+__ZN3JSC3JIT33privateCompilePatchGetArrayLengthEPv
+__ZN3JSC11Interpreter23cti_op_put_by_id_secondEPvz
+__ZN3JSC11Interpreter18tryCTICachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_10JSValuePtrERKNS_15PutPropertySlotE
+__ZN3JSCL19cachePrototypeChainEPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainEPv
+__ZN3JSC9Structure22materializePropertyMapEv
+__ZN3JSC3JIT19patchPutByIdReplaceEPNS_17StructureStubInfoEPNS_9StructureEmPv
+__ZN3JSCL21resizePropertyStorageEPNS_8JSObjectEii
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC11Interpreter14cti_op_pre_incEPvz
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
+__ZN3JSC11Interpreter26cti_op_tear_off_activationEPvz
+__ZN3JSC11Interpreter21cti_op_ret_scopeChainEPvz
+__ZN3JSC11Interpreter27cti_op_get_by_id_proto_listEPvz
+__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_mPNS_9ExecStateE
+__ZN3JSC12JSActivationD0Ev
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3WTF11fastReallocILb0EEEPvS1_m
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZNK3JSC7ModNode8opcodeIDEv
+__ZN3JSC7ModNodeD1Ev
+__ZN3JSC3JIT23compileFastArith_op_modEjjj
+__ZN3JSC3JIT27compileFastArithSlow_op_modEjjjRPNS_13SlowCaseEntryE
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_10JSValuePtrE
+__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7UString6appendEt
+__ZN3JSC11Interpreter19cti_vm_lazyLinkCallEPvz
+__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockEPvPNS_12CallLinkInfoEi
+__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC12X86Assembler7cmpl_imEiiNS_3X8610RegisterIDE
+__ZN3JSC9CodeBlock13unlinkCallersEv
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
+__ZN3JSC11Interpreter10cti_op_mulEPvz
+__ZN3JSC11Interpreter18cti_op_to_jsnumberEPvz
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL13jsAddSlowCaseEPNS_9ExecStateENS_10JSValuePtrES2_
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7UString4fromEj
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
+__ZN3JSC7UString17expandPreCapacityEi
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16VarDeclCommaNodeD1Ev
+__ZN3JSC7UStringC1EPtib
+__ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
+__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZN3JSC7UString6appendEPKc
+__ZN3JSC3JIT10unlinkCallEPNS_12CallLinkInfoE
+__ZN3JSC11Interpreter24cti_op_put_by_id_genericEPvz
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncExprNodeEEELm0EE15reserveCapacityEm
+__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EESA_E6expandEv
+__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
+__ZN3JSC4WREC9Generator20generateAssertionEOLERNS_14MacroAssembler8JumpListE
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC4WREC31GeneratePatternCharacterFunctor12generateAtomEPNS0_9GeneratorERNS_14MacroAssembler8JumpListE
+__ZN3JSC4WREC31GeneratePatternCharacterFunctor9backtrackEPNS0_9GeneratorE
+__ZL20branchNeedsLineStartPKhjj
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
+__ZL17bracketIsAnchoredPKh
+__ZL32branchFindFirstAssertedCharacterPKhb
+__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC11concatenateEPNS_7UString3RepEd
+__ZNK3JSC12JSActivation14isDynamicScopeEv
+__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
+__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15TypeOfValueNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17TypeOfResolveNodeD1Ev
+__ZN3JSC15StrictEqualNodeD1Ev
+__ZN3JSC12ContinueNodeD1Ev
+__ZN3JSC15TypeOfValueNodeD1Ev
+__ZN3JSC11Interpreter33cti_op_create_arguments_no_paramsEPvz
+__ZN3JSC11Interpreter13cti_op_typeofEPvz
+__ZN3JSCL20jsTypeStringForValueEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE15reserveCapacityEm
+__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC7JSArray9classInfoEv
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter27cti_op_get_by_id_array_failEPvz
+__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC14PostfixDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter32cti_op_get_by_id_proto_list_fullEPvz
+__ZN3JSC12FuncExprNodeD1Ev
+__ZN3JSC12FuncExprNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter26cti_op_get_by_id_self_failEPvz
+__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEm
+__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter25cti_op_tear_off_argumentsEPvz
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
+__ZN3JSCL44countPrototypeChainEntriesAndCheckForProxiesEPNS_9ExecStateENS_10JSValuePtrERKNS_12PropertySlotE
+__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17DeleteBracketNodeD1Ev
+__ZN3JSC17DeleteBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter17cti_op_del_by_valEPvz
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC6JSCell9getUInt32ERj
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
+__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17ReadModifyDotNodeD1Ev
+__ZN3JSC17ReadModifyDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE
+__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
+__ZNK3JSC10ScopeChain10localDepthEv
+__ZNK3JSC12JSActivation9classInfoEv
+__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC13StatementNode6setLocEii
+__ZN3JSC16FunctionBodyNode14copyParametersEv
+__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
+__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3JSC9CodeBlock36hasGlobalResolveInfoAtBytecodeOffsetEj
+__ZN3JSC6RegExpD1Ev
__Z12jsRegExpFreeP8JSRegExp
-__ZN3KJS25CollectorHeapIntrospector4sizeEP14_malloc_zone_tPKv
-__ZN3WTF9HashTableINS_6RefPtrIN3KJS7UString3RepEEESt4pairIS5_mENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS2_23IdentifierRepHashTraitsENS2_26SymbolTableIndexHashTraitsEEESC_E4findIS5_NS_22IdentityHashTranslatorIS5_S7_SA_EEEENS_17HashTableIteratorIS5_S7_S9_SA_SE_SC_EERKT_
-__ZN3KJS18AssignLocalVarNodeD1Ev
-__ZN3KJS8TrueNodeD1Ev
-__ZN3KJS11NewExprNodeD1Ev
-__ZN3KJS19ImmediateNumberNodeD1Ev
-__ZN3KJS17AssignBracketNodeD1Ev
-__ZN3KJS18LocalVarAccessNodeD1Ev
-__ZN3KJS16ParserRefCounted8refcountEv
-__ZN3KJS14JSGlobalObject16stopTimeoutCheckEv
-__ZN3KJS11GreaterNodeD1Ev
-__ZN3KJS16ArgumentListNodeD1Ev
-__ZN3KJS17FunctionObjectImp9constructEPNS_9ExecStateERKNS_4ListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3KJS6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_
-__ZN3KJS8JSObject4callEPNS_9ExecStateEPS0_RKNS_4ListE
-__ZN3KJS18AddStringRightNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS13DateObjectImp19implementsConstructEv
-__ZN3KJS13DateObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS12DateInstance9classInfoEv
-__ZNK3KJS9NumberImp8toNumberEPNS_9ExecStateE
-__ZNK3KJS9NumberImp8toStringEPNS_9ExecStateE
-__ZN3KJS9BlockNodeD1Ev
-__ZN3KJS21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
-__ZN3KJS12getUTCOffsetEv
-__ZN3KJS12getDSTOffsetEdd
-__ZN3KJS15ConditionalNodeD1Ev
-__ZN3KJS7DivNodeD1Ev
-__ZN3KJS9EqualNodeD1Ev
-__ZN3KJS8NullNodeD1Ev
-__ZN3KJS9FalseNodeD1Ev
-__ZN3KJS12NotEqualNodeD1Ev
-__ZN3KJS7SubNodeD1Ev
-__ZN3KJS7SubNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS24LocalVarFunctionCallNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS21ReadModifyResolveNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14StringInstance12lengthGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS7DivNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS7DivNode8evaluateEPNS_9ExecStateE
-__ZN3KJS18LocalVarAccessNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS8MultNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS8MultNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19FunctionCallDotNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS7SubNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9NumberImp11toPrimitiveEPNS_9ExecStateENS_6JSTypeE
-__ZN3KJS18AddStringRightNodeD1Ev
-__ZN3KJS7AddNodeD1Ev
-__ZN3KJS13LogicalOrNodeD1Ev
-__ZN3KJS17PreIncResolveNodeD1Ev
-__ZN3KJS8MultNodeD1Ev
-__ZN3KJS8LessNodeD1Ev
-__ZN3KJS14LogicalAndNodeD1Ev
-__ZN3KJS10NumberNodeD1Ev
-__ZN3KJS13GreaterEqNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14LogicalNotNodeD1Ev
-__ZN3KJS7ModNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14JSGlobalObject12checkTimeoutEv
-__ZN3KJS7ModNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15LessNumbersNode8evaluateEPNS_9ExecStateE
-__ZN3KJS20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8ThisNodeD1Ev
-__ZN3KJS19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS13GreaterEqNode8evaluateEPNS_9ExecStateE
-__ZN3KJS20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23stringProtoFuncFontsizeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS11ResolveNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13GreaterEqNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS9NumberImp18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE
-__ZN3KJS19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9ArrayNodeD1Ev
-__ZN3KJS11ElementNodeD1Ev
-__ZN3KJS17ObjectLiteralNodeD1Ev
-__ZN3KJS14PostfixDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS14PostIncDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19PlaceholderTrueNodeD1Ev
-__ZN3KJS19PostDecLocalVarNode8evaluateEPNS_9ExecStateE
-__ZN3KJS17ReadModifyDotNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS17ReadModifyDotNode8evaluateEPNS_9ExecStateE
-__ZN3KJS21FunctionCallValueNodeD1Ev
-__ZN3KJS10BitAndNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS14AddNumbersNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS10BitXOrNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS22UnsignedRightShiftNode8evaluateEPNS_9ExecStateE
-__ZN3KJS8MultNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS7DivNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS19StringObjectFuncImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS7ModNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS10BitAndNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS14RightShiftNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS14AddNumbersNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EERKNS_7UStringEiPKNS_5UCharEjPiSD_PS7_
-__ZN3KJS13EvalExecStateC1EPNS_14JSGlobalObjectEPNS_8EvalNodeEPNS_9ExecStateE
-__ZN3KJS8EvalNode7executeEPNS_9ExecStateE
-__ZN3KJS8EvalNodeD1Ev
-__ZN3KJS23FunctionCallBracketNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS23FunctionCallBracketNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16PropertyListNodeD1Ev
-__ZN3KJS12PropertyNodeD1Ev
-__ZN3KJS13CaseBlockNodeD1Ev
-__ZN3KJS14CaseClauseNodeD1Ev
-__ZN3KJS14ClauseListNodeD1Ev
-__ZN3KJS9RegExpImp18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS17staticValueGetterINS_9RegExpImpEEEPNS_7JSValueEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3KJS9RegExpImp16getValuePropertyEPNS_9ExecStateEi
-__ZN3KJS9ThrowNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS15StrictEqualNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9RegExpImp5matchEPNS_9ExecStateERKNS_4ListE
-__ZN3KJS15StrictEqualNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS18NotStrictEqualNodeD1Ev
-__ZN3KJS15StrictEqualNodeD1Ev
-__ZN3KJS18LocalVarTypeOfNodeD1Ev
-__ZN3KJS19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17TypeOfResolveNode8evaluateEPNS_9ExecStateE
-__ZN3KJS26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
-__ZNK3KJS7UString5rfindERKS0_i
-__ZN3KJS15TypeOfValueNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS15TypeOfValueNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS17FunctionObjectImp19implementsConstructEv
-__ZN3KJS17FunctionObjectImp9constructEPNS_9ExecStateERKNS_4ListE
-__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8JSObject3putEPNS_9ExecStateEjPNS_7JSValueEi
-__ZN3KJS6InNodeD1Ev
-__ZNK3KJS9Arguments9classInfoEv
-__ZN3KJS10BitXOrNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS19addSlowCaseToNumberEPNS_9ExecStateEPNS_7JSValueES3_
-__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZNK3KJS9WhileNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9FalseNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7DivNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7DivNode10precedenceEv
-__ZNK3KJS15StrictEqualNode8streamToERNS_12SourceStreamE
-__ZNK3KJS15StrictEqualNode10precedenceEv
-__ZNK3KJS16VarDeclCommaNode10precedenceEv
-__ZNK3KJS17PreIncResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9FalseNode10precedenceEv
-__ZN3KJS14InstanceOfNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZNK3KJS19InternalFunctionImp21implementsHasInstanceEv
-__ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
-__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
-__ZN3KJS25CollectorHeapIntrospector9forceLockEP14_malloc_zone_t
-__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
-__ZN3KJS25CollectorHeapIntrospector11forceUnlockEP14_malloc_zone_t
-__ZNK3KJS23FunctionCallBracketNode10precedenceEv
-__ZN3KJS14InstanceOfNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS9ThrowNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7SubNode10precedenceEv
-__ZNK3KJS7SubNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10NegateNode10precedenceEv
-__ZNK3KJS10NegateNode8streamToERNS_12SourceStreamE
-__ZNK3KJS12FuncDeclNode8streamToERNS_12SourceStreamE
-__ZNK3KJS18PostDecResolveNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9BreakNode8streamToERNS_12SourceStreamE
-__ZNK3KJS6InNode10precedenceEv
-__ZNK3KJS6InNode8streamToERNS_12SourceStreamE
-__ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE
-__ZN3KJS18PostDecBracketNode8evaluateEPNS_9ExecStateE
-__ZN3KJS28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS18PostIncResolveNode8streamToERNS_12SourceStreamE
-__ZN3KJS13ArrayInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS14StringInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS15AssignErrorNodeD1Ev
-__ZN3WTF6VectorIcLm0EE14expandCapacityEmPKc
-__ZN3WTF6VectorIcLm0EE14expandCapacityEm
-_JSContextGetGlobalObject
-_JSClassCreate
+__ZN3JSC12JSActivation4markEv
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ThrowNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC9ThrowNodeD1Ev
+__ZNK3JSC21UStringSourceProvider6lengthEv
+__ZNK3JSC21UStringSourceProvider4dataEv
+__ZN3JSC21UStringSourceProviderD1Ev
+__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmmPvPNS_9ExecStateE
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF6VectorItLm256EE14expandCapacityEm
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3JSC3JIT28compileFastArith_op_post_decEjj
+__ZN3JSC3JIT27compileFastArith_op_pre_decEj
+__ZN3JSC3JIT32compileFastArithSlow_op_post_decEjjRPNS_13SlowCaseEntryE
+__ZN3JSC3JIT31compileFastArithSlow_op_pre_decEjRPNS_13SlowCaseEntryE
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC9Arguments4markEv
+__ZN3JSC11Interpreter17cti_timeout_checkEPvz
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC19JSStaticScopeObject4markEv
+__ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC6InNode8opcodeIDEv
+__ZN3JSC11Interpreter9cti_op_inEPvz
+__ZN3JSC11Interpreter21cti_op_put_by_id_failEPvz
+__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC11Interpreter18cti_op_is_functionEPvz
+__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
+__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC13DeleteDotNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter16cti_op_del_by_idEPvz
+__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
+__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3WTF6VectorIN3JSC14MacroAssembler4JumpELm16EE14expandCapacityEm
+__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
+__ZN3JSC14InstanceOfNodeD1Ev
+__ZN3JSC11JSImmediate8toObjectENS_10JSValuePtrEPNS_9ExecStateE
+__ZNK3JSC12NumberObject9classInfoEv
+__ZN3JSC11Interpreter17cti_op_instanceofEPvz
+__ZNK3JSC7UString6substrEii
+__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZNK3JSC17ExprStatementNode15isExprStatementEv
+__ZNK3JSC12FuncExprNode14isFuncExprNodeEv
+__ZN3JSC7ArgList9markListsERN3WTF7HashSetIPS0_NS1_7PtrHashIS3_EENS1_10HashTraitsIS3_EEEE
+__ZN3JSC9CommaNodeD1Ev
+__ZN3JSC11Interpreter12cti_op_throwEPvz
+__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_10JSValuePtrEjb
+__ZNK3JSC8JSObject22isNotAnObjectErrorStubEv
+__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
+__ZNK3JSC8JSObject19isWatchdogExceptionEv
+__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
+__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_10JSValuePtrERjRPNS_9CodeBlockE
+__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataEPvRS2_
+__ZN3JSC19ctiSetReturnAddressEPPvS0_
+ctiVMThrowTrampoline
+__ZN3JSC11Interpreter12cti_vm_throwEPvz
+__ZN3JSC11Interpreter21cti_op_push_new_scopeEPvz
+__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC4WREC9Generator27generateNonGreedyQuantifierERNS_14MacroAssembler8JumpListERNS0_19GenerateAtomFunctorEjj
+__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7UString6appendEPKti
+__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC10JSValuePtr20toIntegerPreserveNaNEPNS_9ExecStateE
+__Z22jsc_pcre_ucp_othercasej
+__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv
+__ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZN3WTF9HashTableIjSt4pairIjN3JSC10JSValuePtrEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_EC2ERKSE_
+__ZN3JSC11Interpreter14cti_op_pre_decEPvz
+__ZN3JSC11Interpreter16cti_op_new_arrayEPvz
+__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_10JSValuePtrE
+__ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9LabelNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter15cti_op_stricteqEPvz
+__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZL5matchPKtPKhiR9MatchData
+__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC23FunctionCallBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC23FunctionCallBracketNodeD1Ev
+__ZN3JSC11Interpreter16cti_op_is_stringEPvz
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
+__ZN3JSC7TryNode12releaseNodesERNS_12NodeReleaserE
+__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE14expandCapacityEm
+__ZN3JSC11Interpreter19cti_op_loop_if_lessEPvz
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
+__Z15jsc_pcre_xclassiPKh
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC7JSArray9setLengthEj
+__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC11Interpreter19cti_op_is_undefinedEPvz
+__ZNK3JSC9Arguments9classInfoEv
+__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_7ArgListE
+__ZN3JSC11Interpreter23cti_op_create_argumentsEPvz
+__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7PtrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6expandEv
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
+__ZN3JSC11Interpreter19cti_op_convert_thisEPvz
+__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17PrefixBracketNodeD1Ev
+__ZN3JSC17PrefixBracketNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC10JSFunction9classInfoEv
+__ZN3JSC7CStringD1Ev
+__ZN3JSC6JSLock12DropAllLocksC1Eb
+__ZN3JSCL17createJSLockCountEv
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
+__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
+__ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
+__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_10JSValuePtrENS_7UStringE
+__ZNK3JSC7UString5asciiEv
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3WTF13tryFastCallocEmm
+__ZN3JSC13JSNotAnObjectD0Ev
+__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatERKNS_7ArgListE
+__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
+__ZNK3JSC6JSCell9getStringERNS_7UStringE
+__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_10JSValuePtrEjPNS_9CodeBlockE
+__ZN3JSC11Interpreter17cti_op_jmp_scopesEPvz
+__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE
+__ZN3WTF6VectorIN3JSC3JIT7JSRInfoELm0EE14expandCapacityEm
+__ZN3JSC18RegExpMatchesArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE
+__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZN3JSC9Structure22getterSetterTransitionEPS0_
+__ZN3JSCL27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC6JSCell14isGetterSetterEv
+__ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZNK3JSC12GetterSetter14isGetterSetterEv
+__ZN3JSC12GetterSetter4markEv
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
+__ZN3JSC17BytecodeGenerator21emitComplexJumpScopesEPNS_5LabelEPNS_18ControlFlowContextES4_
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_10JSValuePtrE
+__ZN3JSC12PropertySlot14functionGetterEPNS_9ExecStateERKNS_10IdentifierERKS0_
+__ZN3JSC7JSArray4sortEPNS_9ExecStateE
+__ZN3JSC7JSArray17compactForSortingEv
+__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8VoidNodeD1Ev
+__ZN3JSC8VoidNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSCL27compareByStringPairForQSortEPKvS1_
+__ZN3JSC6Parser7reparseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
+__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC8EvalNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithNumberConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZNK3JSC8JSObject16isVariableObjectEv
+__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSC13BooleanObjectD0Ev
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_14OffsetLocationEENS_18PairFirstExtractorIS8_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSE_IS7_EEEESF_E4findIPS4_NS_29RefPtrHashMapRawKeyTranslatorISK_S8_SH_SC_EEEENS_17HashTableIteratorIS5_S8_SA_SC_SH_SF_EERKT_
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
+__ZN3JSC14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeEPNS_10JSValuePtrE
+__ZN3JSC11Interpreter19cti_op_put_by_indexEPvz
+__ZN3JSCL25numberConstructorMaxValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC18RegExpMatchesArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC16ErrorConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callErrorConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC4WREC9Generator28generateParenthesesAssertionERNS_14MacroAssembler8JumpListE
+__ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE
+__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_10JSValuePtrEjPNS_9CodeBlockE
+__ZN3JSC15isStrWhiteSpaceEt
+__ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL7dateUTCEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateENS_10JSValuePtrERKNS_7ArgListEib
+__ZN3JSCL23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC7CStringaSERKS0_
+__ZN3JSCL22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC7UString8toUInt32EPb
+__ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
+__ZNK3JSC8JSObject14isGlobalObjectEv
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
+__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEb
+__ZN3WTF6VectorIN3JSC10JSValuePtrELm0EE14expandCapacityEm
+__ZN3JSC18BooleanConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL31constructWithBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC16constructBooleanEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC12JSNumberCell9getUInt32ERj
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSCL23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
+__ZNK3JSC21UStringSourceProvider8getRangeEii
+__ZN3JSC22NativeErrorConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+JSClassCreate
__ZN13OpaqueJSClass6createEPK17JSClassDefinition
__ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_
-_JSClassRetain
-_JSObjectMake
-__ZN13OpaqueJSClass9prototypeEPK15OpaqueJSContext
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE
-_JSStringCreateWithUTF8CString
-_JSObjectSetProperty
-_JSStringRelease
-__Z30makeGetterOrSetterPropertyNodeRKN3KJS10IdentifierES2_PNS_13ParameterNodeEPNS_16FunctionBodyNodeE
-__ZN3KJS8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
-__ZN3KJS8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
-__ZNK3KJS15GetterSetterImp4typeEv
-__ZNK3KJS8JSObject6canPutEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS13ConstDeclNodeC1ERKNS_10IdentifierEPNS_14ExpressionNodeE
-__Z26appendToVarDeclarationListRPN3KJS20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEEEPNS_13ConstDeclNodeE
-__ZN3KJS18ConstStatementNodeC1EPNS_13ConstDeclNodeE
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEE20staticFunctionGetterEPNS_9ExecStateEPS1_RKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3KJS18JSCallbackFunctionC1EPNS_9ExecStateEPFPK13OpaqueJSValuePK15OpaqueJSContextPS3_S9_mPKS5_PS5_ERKNS_10IdentifierE
-__ZN3KJS18JSCallbackFunction14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-_JSObjectGetPrivate
-__ZNK3KJS16JSCallbackObjectINS_8JSObjectEE9classInfoEv
-_JSStringCreateWithCharacters
-_JSValueMakeString
-__ZN3KJS12PropertySlot14functionGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_
-__ZN3WTF10fastCallocEmm
-_JSObjectGetProperty
-_JSValueToObject
-_JSValueProtect
-_JSObjectCallAsFunction
-_JSValueMakeNumber
-_JSValueMakeBoolean
-_JSObjectCallAsConstructor
-__ZN3KJS15GetterSetterImp4markEv
-_JSValueMakeUndefined
-_JSValueUnprotect
-_JSValueIsNumber
-_JSValueToNumber
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEED0Ev
-__Z25clearReferenceToPrototypeP13OpaqueJSValue
-_JSClassRelease
-_JSStringIsEqualToUTF8CString
-_JSStringIsEqual
-__ZN3KJSeqERKNS_7UStringES2_
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateEPS1_RKNS_10IdentifierERKNS_12PropertySlotE
-_JSStringCreateWithCFString
-__ZN3KJS7UStringC2EPNS_5UCharEib
-__ZN3KJS16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
-_JSObjectSetPrivate
-__ZN3KJS15GetterSetterImpD0Ev
-__ZN3KJS27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS17PreIncResolveNode10precedenceEv
-__ZNK3KJS10SwitchNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13CaseBlockNode8streamToERNS_12SourceStreamE
-__ZNK3KJS14CaseClauseNode8streamToERNS_12SourceStreamE
-__ZN3KJS18ConstStatementNodeD1Ev
-__ZN3KJS17PreDecBracketNodeD1Ev
-__ZN3KJS11Interpreter24setShouldPrintExceptionsEb
-__ZN3KJS9Collector26protectedGlobalObjectCountEv
-__ZN3KJS9Collector4sizeEv
-__ZN3KJS9Collector17globalObjectCountEv
-__ZN3KJS9Collector20protectedObjectCountEv
-__ZN3KJS9Collector25protectedObjectTypeCountsEv
-__ZNK3KJS15NumberObjectImp9classInfoEv
-__ZNK3KJS15RegExpPrototype9classInfoEv
-__ZNK3KJS15RegExpObjectImp9classInfoEv
-__ZNK3KJS14NativeErrorImp9classInfoEv
-__ZNK3KJS13MathObjectImp9classInfoEv
-__ZN3WTF6VectorIPN3KJS7JSValueELm8EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIPN3KJS7JSValueELm8EE14expandCapacityEm
-__ZN3KJS15ConditionalNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS9Arguments14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3KJS17DeleteBracketNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9BitOrNode10precedenceEv
-__ZNK3KJS9BitOrNode8streamToERNS_12SourceStreamE
-__ZNK3KJS7ModNode10precedenceEv
-__ZNK3KJS7ModNode8streamToERNS_12SourceStreamE
-__ZN3KJS31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS16formatLocaleDateEPNS_9ExecStateEdbbRKNS_4ListE
-__ZN3KJS31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9BitOrNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS7DivNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS14BitwiseNotNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS13ActivationImp14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3KJS27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17PreDecBracketNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS16BooleanObjectImp19implementsConstructEv
-__ZN3KJS27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE
-__ZN3KJS10StringNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS13UnaryPlusNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS17FunctionObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15DeleteValueNodeD1Ev
-__ZN3KJS15RegExpObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8MultNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS4Node18setErrorCompletionEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3KJS10StringNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS22UnsignedRightShiftNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS18PostIncResolveNode10precedenceEv
-__ZNK3KJS21ReadModifyResolveNode10precedenceEv
-__ZNK3KJS21FunctionCallValueNode10precedenceEv
-__ZN3KJS4Node15handleExceptionEPNS_9ExecStateE
-__ZNK3KJS13UnaryPlusNode10precedenceEv
-__ZNK3KJS13UnaryPlusNode8streamToERNS_12SourceStreamE
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcPNS_7JSValueERKNS_10IdentifierE
-__ZNK3KJS15DotAccessorNode17isDotAccessorNodeEv
-__ZNK3KJS14PostfixDotNode10precedenceEv
-__ZN3KJS23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS14PostDecDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS9CommaNode10precedenceEv
-__ZNK3KJS17ReadModifyDotNode10precedenceEv
-__ZNK3KJS13DeleteDotNode8streamToERNS_12SourceStreamE
-__ZNK3KJS19PlaceholderTrueNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17AssignBracketNode10precedenceEv
-__ZNK3KJS8WithNode8streamToERNS_12SourceStreamE
-__ZNK3KJS17DeleteBracketNode10precedenceEv
-__ZN3KJS15ObjectObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-_KJS_JSCreateNativeJSObject
-__ZN3KJS8Bindings12JavaJSObject6invokeEPNS0_19JSObjectCallContextE
-__ZN3KJS8Bindings12JavaJSObject12createNativeEx
-__ZN3KJS8Bindings24findProtectingRootObjectEPNS_8JSObjectE
-_KJS_JSObject_JSObjectEval
-__ZN3KJS8Bindings12JavaJSObjectC1Ex
-__ZNK3KJS8Bindings12JavaJSObject4evalEP8_jstring
-__ZN3KJS8Bindings9getJNIEnvEv
-__ZN3KJS8Bindings9getJavaVMEv
-__ZN3KJS8Bindings30getUCharactersFromJStringInEnvEP7JNIEnv_P8_jstring
-__ZN3KJS8Bindings33releaseUCharactersForJStringInEnvEP7JNIEnv_P8_jstringPKt
-__ZNK3KJS8Bindings12JavaJSObject21convertValueToJObjectEPNS_7JSValueE
-__ZN7JNIEnv_9NewObjectEP7_jclassP10_jmethodIDz
-_KJS_JSObject_JSFinalize
-__ZN3KJS19stringProtoFuncBoldEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS15RegExpObjectImp15getRightContextEv
-__ZNK3KJS15RegExpObjectImp14getLeftContextEv
-__ZN3KJS13LeftShiftNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS7ModNode15evaluateToInt32EPNS_9ExecStateE
-__ZNK3KJS18PostDecResolveNode10precedenceEv
-__ZN3KJS28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS32stringProtoFuncToLocaleLowerCaseEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__NPN_SetException
-__ZN3KJS18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS8Bindings12JavaInstanceC2EP8_jobjectN3WTF10PassRefPtrINS0_10RootObjectEEE
-__ZN3KJS8Bindings12JavaInstance5beginEv
-__ZNK3KJS8Bindings12JavaInstance8getClassEv
-__ZN3KJS8Bindings9JavaClassC2EP8_jobject
-__ZN3KJS8Bindings19callJNIObjectMethodEP8_jobjectPKcS4_z
-__ZN3KJS8Bindings13callJNIMethodE7JNITypeP8_jobjectPKcS5_Pc
-__ZN3KJS8Bindings24getCharactersFromJStringEP8_jstring
-__ZN3KJS8Bindings27releaseCharactersForJStringEP8_jstringPKc
-__ZN3KJS8Bindings9JavaFieldC2EP7JNIEnv_P8_jobject
-__ZN3KJS7CStringaSERKS0_
-__ZN3KJS8Bindings20JNITypeFromClassNameEPKc
-__ZN3KJS8Bindings14JObjectWrapperC1EP8_jobject
-__ZNK3KJS8Bindings9JavaField4nameEv
-__ZN3KJS8Bindings10JavaMethodC2EP7JNIEnv_P8_jobject
-__ZN3KJS8Bindings16callJNIIntMethodEP8_jobjectPKcS4_z
-__ZN3KJS8Bindings26callJNIStaticBooleanMethodEP7_jclassPKcS4_z
-__ZN3KJS8Bindings19callJNIStaticMethodE7JNITypeP7_jclassPKcS5_Pc
-__ZNK3KJS8Bindings10JavaMethod4nameEv
-__ZN3KJS8Bindings13JavaParameterC2EP7JNIEnv_P8_jstring
-__ZNK3KJS8Bindings9JavaClass10fieldNamedERKNS_10IdentifierEPNS0_8InstanceE
-__ZNK3KJS8Bindings9JavaClass12methodsNamedERKNS_10IdentifierEPNS0_8InstanceE
-__ZN3KJS8Bindings12JavaInstance3endEv
-__ZN3KJS8Bindings12JavaInstanceD1Ev
-__ZN3KJS8Bindings9JavaClassD1Ev
-__ZN3WTF20deleteAllPairSecondsIPN3KJS8Bindings5FieldEKNS_7HashMapINS_6RefPtrINS1_7UString3RepEEES4_NS_7PtrHashIS9_EENS_10HashTraitsIS9_EENSC_IS4_EEEEEEvRT0_
-__ZN3KJS8Bindings14JObjectWrapperD1Ev
-__ZN3KJS35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS12FuncExprNode21needsParensIfLeftmostEv
-__ZN3KJS13DateObjectImp14callAsFunctionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS11NewExprNode17evaluateToBooleanEPNS_9ExecStateE
-__ZN3KJS29numberProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9BitOrNode16evaluateToNumberEPNS_9ExecStateE
-__ZNK3KJS7JSValue8toUInt32EPNS_9ExecStateE
-__ZNK3KJS8JSObject3getEPNS_9ExecStateEj
-__ZNK3KJS7JSValue16toUInt32SlowCaseEPNS_9ExecStateERb
-__ZN3KJS9Collector29markOtherThreadConservativelyEPNS0_6ThreadE
-__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
-__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3KJS23destroyRegisteredThreadEPv
-__ZN3KJS28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15RegExpObjectImp16putValuePropertyEPNS_9ExecStateEiPNS_7JSValueEi
-__ZNK3KJS15RegExpObjectImp12getLastParenEv
-__ZN3KJS10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
-__ZN3KJS18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS9LabelNode9pushLabelERKNS_10IdentifierE
-__ZN3KJS9Collector32reportOutOfMemoryToAllExecStatesEv
-__ZN3KJS5Error6createEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZNK3KJS17PreDecResolveNode10precedenceEv
-__ZN3KJS17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS16PostfixErrorNode8streamToERNS_12SourceStreamE
-__ZNK3KJS15PrefixErrorNode8streamToERNS_12SourceStreamE
-__ZNK3KJS15AssignErrorNode8streamToERNS_12SourceStreamE
-__ZN3KJS16PostfixErrorNode8evaluateEPNS_9ExecStateE
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKcS5_
-__ZN3KJS16PostfixErrorNodeD1Ev
-__ZNK3KJS13LeftShiftNode8streamToERNS_12SourceStreamE
-__ZNK3KJS13LeftShiftNode10precedenceEv
-__ZNK3KJS14RightShiftNode8streamToERNS_12SourceStreamE
-__ZNK3KJS14RightShiftNode10precedenceEv
-__ZNK3KJS22UnsignedRightShiftNode8streamToERNS_12SourceStreamE
-__ZNK3KJS22UnsignedRightShiftNode10precedenceEv
-__ZNK3KJS10BitAndNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10BitAndNode10precedenceEv
-__ZNK3KJS10BitXOrNode8streamToERNS_12SourceStreamE
-__ZNK3KJS10BitXOrNode10precedenceEv
-__ZN3KJS15AssignErrorNode8evaluateEPNS_9ExecStateE
-__ZN3KJS4Node10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3KJS13char_sequenceEci
-__ZN3KJS15LessStringsNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15LessStringsNodeD1Ev
-__ZN3KJS15DeleteValueNode8evaluateEPNS_9ExecStateE
-__ZN3KJS22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15PrefixErrorNode8evaluateEPNS_9ExecStateE
-__ZN3KJS28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS15PrefixErrorNodeD1Ev
-__ZN3KJS19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3WTF6VectorItLm0EE6resizeEm
-__ZN3WTF6VectorItLm0EE14expandCapacityEm
-__ZN3WTF6VectorItLm0EE15reserveCapacityEm
-__ZN3KJS28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS18ConstStatementNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS13ConstDeclNode22optimizeVariableAccessERKN3WTF7HashMapINS1_6RefPtrINS_7UString3RepEEEmNS_17IdentifierRepHashENS_23IdentifierRepHashTraitsENS_26SymbolTableIndexHashTraitsEEERKNS1_6VectorINS_17LocalStorageEntryELm32EEERNSD_IPNS_4NodeELm16EEE
-__ZN3KJS18ConstStatementNode7executeEPNS_9ExecStateE
-__ZN3KJS13ConstDeclNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15AssignConstNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16PostIncConstNode8evaluateEPNS_9ExecStateE
-__ZN3KJS16PostDecConstNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15PreIncConstNode8evaluateEPNS_9ExecStateE
-__ZN3KJS15PreDecConstNode8evaluateEPNS_9ExecStateE
-__ZN3KJS19ReadModifyConstNode8evaluateEPNS_9ExecStateE
-__ZNK3KJS13ActivationImp9classInfoEv
-__ZN3KJS16PostIncConstNodeD1Ev
-__ZN3KJS15PreIncConstNodeD1Ev
-__ZN3KJS15PreDecConstNodeD1Ev
-__ZNK3KJS13DeleteDotNode10precedenceEv
-__ZN3KJS28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZN3KJS10NumberNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS19FunctionCallDotNode16evaluateToUInt32EPNS_9ExecStateE
-__ZNK3KJS21ReadModifyBracketNode8streamToERNS_12SourceStreamE
-__ZN3KJS10BitXOrNode16evaluateToNumberEPNS_9ExecStateE
-___tcf_1
-__ZNK3KJS7UString6is8BitEv
-__ZN3KJS15DotAccessorNode16evaluateToUInt32EPNS_9ExecStateE
-__ZN3KJS24stringProtoFuncFontcolorEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
-__ZNK3KJS14NativeErrorImp19implementsConstructEv
-__ZN3KJS19PostDecLocalVarNode16evaluateToNumberEPNS_9ExecStateE
-__ZN3KJS19PostDecLocalVarNode15evaluateToInt32EPNS_9ExecStateE
-__ZN3KJS13UnaryPlusNode17evaluateToBooleanEPNS_9ExecStateE
+__ZN3JSC7UString3Rep14createFromUTF8EPKc
+__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEP19StaticFunctionEntryNS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3addERKS5_RKS7_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_P19StaticFunctionEntryENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6expandEv
+JSClassRetain
+JSObjectMake
+__ZN3JSC4Heap14registerThreadEv
+__ZN3JSC6JSLockC1EPNS_9ExecStateE
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE
+__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE
+__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE
+__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN24OpaqueJSClassContextDataC2EP13OpaqueJSClass
+JSStringCreateWithCFString
+JSObjectSetProperty
+__ZNK14OpaqueJSString10identifierEPN3JSC12JSGlobalDataE
+JSStringRelease
+__ZL30makeGetterOrSetterPropertyNodePvRKN3JSC10IdentifierES3_PNS0_13ParameterNodeEPNS0_16FunctionBodyNodeERKNS0_10SourceCodeE
+__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator13emitPutGetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC17BytecodeGenerator13emitPutSetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC18ConstStatementNodeD1Ev
+__ZN3JSC18ConstStatementNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ConstDeclNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC11Interpreter17cti_op_put_getterEPvz
+__ZN3JSC11Interpreter17cti_op_put_setterEPvz
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC7UString3Rep13createCopyingEPKti
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE20staticFunctionGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC18JSCallbackFunctionC1EPNS_9ExecStateEPFPK13OpaqueJSValuePK15OpaqueJSContextPS3_S9_mPKS5_PS5_ERKNS_10IdentifierE
+__ZN3JSC18JSCallbackFunction11getCallDataERNS_8CallDataE
+__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
+JSValueIsObjectOfClass
+__ZN3JSC6JSCell9getObjectEv
+__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classInfoEv
+JSObjectGetPrivate
+JSValueMakeString
+__ZNK14OpaqueJSString7ustringEv
+JSValueMakeBoolean
+JSContextGetGlobalObject
+JSStringCreateWithUTF8CString
+JSObjectGetProperty
+JSValueToObject
+JSObjectIsFunction
+JSObjectCallAsFunction
+JSValueMakeUndefined
+__ZN3JSC18JSCallbackFunctionD0Ev
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEED0Ev
+__ZL25clearReferenceToPrototypeP13OpaqueJSValue
+JSClassRelease
+__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC23ThrowableExpressionData14emitThrowErrorERNS_17BytecodeGeneratorENS_9ErrorTypeEPKc
+__ZN3JSC17BytecodeGenerator12emitNewErrorEPNS_10RegisterIDENS_9ErrorTypeENS_10JSValuePtrE
+__ZN3JSC15AssignErrorNodeD1Ev
+__ZN3JSC15AssignErrorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState11stringTableEPS0_
+__ZN3JSCL24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN14OpaqueJSString6createERKN3JSC7UStringE
+JSStringIsEqualToUTF8CString
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+JSValueToStringCopy
+JSStringCopyCFString
+JSValueMakeNumber
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+JSValueToNumber
+JSObjectSetPrivate
+__ZN3JSC8Profiler8profilerEv
+__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC8JSObject15unwrappedObjectEv
+JSStringCreateWithCharacters
+__ZN3JSC9Structure18startIgnoringLeaksEv
+__ZN3JSC9Structure17stopIgnoringLeaksEv
+JSValueProtect
+JSObjectCallAsConstructor
+__ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
+__ZN3JSC9constructEPNS_9ExecStateENS_10JSValuePtrENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+__ZN3JSC10JSFunction9constructEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF8Collator11userDefaultEv
+__ZNK3WTF8Collator7collateEPKtmS2_m
+__ZNK3WTF8Collator14createCollatorEv
+__ZN3WTF8CollatorD1Ev
+__ZN3WTF8Collator15releaseCollatorEv
+__ZNK3JSC22NativeErrorConstructor9classInfoEv
+JSValueUnprotect
+JSValueIsNumber
+__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
+__ZN3WTF7HashSetIPN3JSC14JSGlobalObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC4Heap14primaryHeapEndEv
+__ZN3JSC4Heap16primaryHeapBeginEv
+__ZNK3JSC15RegExpPrototype9classInfoEv
+__ZNK3JSC17NumberConstructor9classInfoEv
+__ZNK3JSC17RegExpConstructor9classInfoEv
+__ZNK3JSC10MathObject9classInfoEv
+__ZNK3JSC18JSCallbackFunction9classInfoEv
+JSValueIsString
+JSStringGetLength
+JSStringGetCharactersPtr
+__ZN3JSC11Interpreter12cti_op_debugEPvz
+__ZN3JSC11Interpreter5debugEPNS_9ExecStateENS_11DebugHookIDEii
+__ZNK3JSC17DebuggerCallFrame4typeEv
+__ZNK3JSC17DebuggerCallFrame12functionNameEv
+__ZNK3JSC17DebuggerCallFrame10thisObjectEv
+__ZN3WTF28setMainThreadCallbacksPausedEb
+__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
+__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3WTF6VectorIN3JSC20FunctionRegisterInfoELm0EE14expandCapacityEm
+__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16ProfileGenerator6createERKNS_7UStringEPNS_9ExecStateEj
+__ZN3JSC16ProfileGeneratorC2ERKNS_7UStringEPNS_9ExecStateEj
+__ZN3JSC7Profile6createERKNS_7UStringEj
+__ZN3JSC11TreeProfile6createERKNS_7UStringEj
+__ZN3JSC7ProfileC2ERKNS_7UStringEj
+__ZN3JSC11ProfileNodeC1ERKNS_14CallIdentifierEPS0_S4_
+__ZN3JSC33getCurrentUTCTimeWithMicrosecondsEv
+__ZN3JSC16ProfileGenerator24addParentForConsoleStartEPNS_9ExecStateE
+__ZN3JSC8Profiler20createCallIdentifierEPNS_12JSGlobalDataENS_10JSValuePtrERKNS_7UStringEi
+__ZN3JSC11ProfileNode10insertNodeEN3WTF10PassRefPtrIS0_EE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC16ProfileGeneratorEEELm0EE14expandCapacityEm
+__ZN3WTF10RefCountedIN3JSC16ProfileGeneratorEE5derefEv
+__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_10JSValuePtrE
+__ZN3JSC16ProfileGenerator11willExecuteERKNS_14CallIdentifierE
+__ZN3JSC11ProfileNode11willExecuteERKNS_14CallIdentifierE
+__ZN3JSC11Interpreter24cti_op_profile_will_callEPvz
+__ZN3JSC11Interpreter23cti_op_profile_did_callEPvz
+__ZN3JSC16ProfileGenerator10didExecuteERKNS_14CallIdentifierE
+__ZN3JSC11ProfileNode10didExecuteEv
+__ZN3JSCL28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter16cti_op_new_errorEPvz
+__ZN3JSC19JSStaticScopeObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC4WREC14CharacterClass11nonwordcharEv
+__ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL23callFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC15PrefixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15PrefixErrorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC15PrefixErrorNodeD1Ev
+__ZN3JSCL19stringProtoFuncBoldEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm512EEELm32EE15reserveCapacityEm
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE
+__ZN3JSCL24regExpConstructorDollar5EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+JSValueIsEqual
+__ZN3JSC10JSValuePtr13equalSlowCaseEPNS_9ExecStateES0_S0_
+__ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC11Interpreter15cti_op_post_decEPvz
+__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC21DebuggerStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21DebuggerStatementNodeD1Ev
+__ZN3JSCL12charSequenceEci
+__ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC4Heap24setGCProtectNeedsLockingEv
+__ZNK3JSC7UString6is8BitEv
+__ZN3WTF9ByteArray6createEm
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter28cti_op_get_by_val_byte_arrayEPvz
+__ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC11Interpreter28cti_op_put_by_val_byte_arrayEPvz
+__ZN3JSCL28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL23throwStackOverflowErrorEPNS_9ExecStateEPNS_12JSGlobalDataEPvRS4_
+__ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC9ExecState9mathTableEPS0_
+__ZN3JSC9ExecState22regExpConstructorTableEPS0_
+__ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar9EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpConstructorInputEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL25setRegExpConstructorInputEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE
+__ZN3JSCL26regExpConstructorLastMatchEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL26regExpConstructorLastParenEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL26regExpConstructorMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrE
+__ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC16PostfixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16PostfixErrorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC16PostfixErrorNodeD1Ev
+__ZN3JSC6JSCell11getJSNumberEv
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj
+__ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
+__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
+__ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC12JSActivation18getArgumentsGetterEv
+__ZN3JSC12JSActivation15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC9ExecState9dateTableEPS0_
+__ZN3JSC23createInvalidParamErrorEPNS_9ExecStateEPKcNS_10JSValuePtrEjPNS_9CodeBlockE
+__ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
+__ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC15DeleteValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DeleteValueNodeD1Ev
+__ZN3JSC15DeleteValueNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEd
+__ZN3JSC4WREC14CharacterClass9nondigitsEv
+__ZNK3JSC19JSStaticScopeObject12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv
+__ZN3JSC12JSGlobalData6createEv
+__ZN3WTF12isMainThreadEv
+__ZN3JSC4Heap7destroyEv
+__ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC11InterpreterD1Ev
+__ZN3JSC12RegisterFileD1Ev
+__ZNK3JSC9HashTable11deleteTableEv
+__ZN3JSC5LexerD1Ev
+__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_EENS8_IS2_EEEEEEvRT0_
+__ZN3JSC17CommonIdentifiersD2Ev
+__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC4HeapD1Ev
+__ZN3JSC12SmallStringsD1Ev
+__ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3WTF8CollatorC1EPKc
+__ZN3WTF8Collator18setOrderLowerFirstEb
+__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
+__ZNK3JSC25InterruptedExecutionError19isWatchdogExceptionEv
VPATH += $$PWD
INCLUDEPATH += tmp
-INCLUDEPATH += $$PWD $$PWD/kjs $$PWD/bindings $$PWD/bindings/c $$PWD/wtf
-DEPENDPATH += $$PWD $$PWD/kjs $$PWD/bindings $$PWD/bindings/c $$PWD/wtf
-DEFINES -= KJS_IDENTIFIER_HIDE_GLOBALS
-qt-port:INCLUDEPATH += $$PWD/bindings/qt
-qt-port:DEFINES += BUILDING_QT__
-gtk-port:DEFINES += BUILDING_GTK__
-
-# http://bugs.webkit.org/show_bug.cgi?id=16406
-# [Gtk] JavaScriptCore needs -lpthread
-gtk-port:!win32-*:LIBS += -lpthread
-
-win32-msvc*: INCLUDEPATH += $$PWD/os-win32
+INCLUDEPATH += $$PWD $$PWD/parser $$PWD/bytecompiler $$PWD/debugger $$PWD/runtime $$PWD/wtf $$PWD/wtf/unicode $$PWD/interpreter $$PWD/jit $$PWD/profiler $$PWD/wrec $$PWD/API $$PWD/.. \
+ $$PWD/ForwardingHeaders $$PWD/bytecode $$PWD/assembler
+DEFINES += BUILDING_QT__
isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
+GENERATED_SOURCES_DIR_SLASH = $$GENERATED_SOURCES_DIR/
+win32-* {
+ GENERATED_SOURCES_DIR_SLASH ~= s|/|\|
+ LIBS += -lwinmm
+}
+
+# Disable the JIT due to numerous observed miscompilations :(
+#CONFIG(release):isEqual(QT_ARCH,i386) {
+# JIT_DEFINES = ENABLE_JIT ENABLE_WREC ENABLE_JIT_OPTIMIZE_CALL ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS ENABLE_JIT_OPTIMIZE_ARITHMETIC
+# # gcc <= 4.1 is known to miscompile, so require >= 4.2, written as major > 3 and minor > 1
+# linux-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,1) {
+# DEFINES += $$JIT_DEFINES
+# SOURCES += wtf/TCSystemAlloc.cpp
+# DEFINES -= USE_SYSTEM_MALLOC
+# }
+# win32-msvc* {
+# DEFINES += $$JIT_DEFINES
+# }
+#}
include(pcre/pcre.pri)
LUT_FILES += \
- kjs/date_object.cpp \
- kjs/number_object.cpp \
- kjs/string_object.cpp \
- kjs/array_object.cpp \
- kjs/math_object.cpp \
- kjs/regexp_object.cpp
+ runtime/DatePrototype.cpp \
+ runtime/NumberConstructor.cpp \
+ runtime/StringPrototype.cpp \
+ runtime/ArrayPrototype.cpp \
+ runtime/MathObject.cpp \
+ runtime/RegExpConstructor.cpp \
+ runtime/RegExpObject.cpp
KEYWORDLUT_FILES += \
- kjs/keywords.table
+ parser/Keywords.table
-KJSBISON += \
- kjs/grammar.y
+JSCBISON += \
+ parser/Grammar.y
SOURCES += \
wtf/Assertions.cpp \
+ wtf/ByteArray.cpp \
wtf/HashTable.cpp \
+ wtf/MainThread.cpp \
+ wtf/RandomNumber.cpp \
+ wtf/RefCountedLeakCounter.cpp \
+ wtf/unicode/CollatorDefault.cpp \
+ wtf/unicode/icu/CollatorICU.cpp \
wtf/unicode/UTF8.cpp \
- bindings/NP_jsobject.cpp \
- bindings/npruntime.cpp \
- bindings/runtime_array.cpp \
- bindings/runtime.cpp \
- bindings/runtime_method.cpp \
- bindings/runtime_object.cpp \
- bindings/runtime_root.cpp \
- bindings/c/c_class.cpp \
- bindings/c/c_instance.cpp \
- bindings/c/c_runtime.cpp \
- bindings/c/c_utility.cpp \
API/JSBase.cpp \
API/JSCallbackConstructor.cpp \
API/JSCallbackFunction.cpp \
API/JSObjectRef.cpp \
API/JSStringRef.cpp \
API/JSValueRef.cpp \
- kjs/JSGlobalObject.cpp \
- kjs/JSVariableObject.cpp
+ API/OpaqueJSString.cpp \
+ runtime/InitializeThreading.cpp \
+ runtime/JSGlobalData.cpp \
+ runtime/JSGlobalObject.cpp \
+ runtime/JSStaticScopeObject.cpp \
+ runtime/JSVariableObject.cpp \
+ runtime/JSActivation.cpp \
+ runtime/JSNotAnObject.cpp \
+ bytecode/CodeBlock.cpp \
+ bytecode/StructureStubInfo.cpp \
+ bytecode/JumpTable.cpp \
+ jit/JIT.cpp \
+ jit/JITCall.cpp \
+ jit/JITArithmetic.cpp \
+ jit/JITPropertyAccess.cpp \
+ jit/ExecutableAllocator.cpp \
+ bytecompiler/BytecodeGenerator.cpp \
+ runtime/ExceptionHelpers.cpp \
+ runtime/JSPropertyNameIterator.cpp \
+ interpreter/Interpreter.cpp \
+ bytecode/Opcode.cpp \
+ bytecode/SamplingTool.cpp \
+ wrec/CharacterClass.cpp \
+ wrec/CharacterClassConstructor.cpp \
+ wrec/WREC.cpp \
+ wrec/WRECFunctors.cpp \
+ wrec/WRECGenerator.cpp \
+ wrec/WRECParser.cpp \
+ interpreter/RegisterFile.cpp
+
+win32-*: SOURCES += jit/ExecutableAllocatorWin.cpp
+else: SOURCES += jit/ExecutableAllocatorPosix.cpp
# AllInOneFile.cpp helps gcc analize and optimize code
# Other compilers may be able to do this at link time
-gtk-port:CONFIG(release) {
-SOURCES += \
- kjs/AllInOneFile.cpp
-} else {
SOURCES += \
- kjs/function.cpp \
- kjs/debugger.cpp \
- kjs/array_instance.cpp \
- kjs/array_object.cpp \
- kjs/bool_object.cpp \
- kjs/collector.cpp \
- kjs/CommonIdentifiers.cpp \
- kjs/date_object.cpp \
- kjs/DateMath.cpp \
- kjs/dtoa.cpp \
- kjs/error_object.cpp \
- kjs/ExecState.cpp \
- kjs/function_object.cpp \
- kjs/identifier.cpp \
- kjs/internal.cpp \
- kjs/interpreter.cpp \
- kjs/JSImmediate.cpp \
- kjs/JSLock.cpp \
- kjs/JSWrapperObject.cpp \
- kjs/lexer.cpp \
- kjs/list.cpp \
- kjs/lookup.cpp \
- kjs/math_object.cpp \
- kjs/nodes.cpp \
- kjs/nodes2string.cpp \
- kjs/number_object.cpp \
- kjs/object.cpp \
- kjs/object_object.cpp \
- kjs/operations.cpp \
- kjs/Parser.cpp \
- kjs/property_map.cpp \
- kjs/property_slot.cpp \
- kjs/PropertyNameArray.cpp \
- kjs/regexp.cpp \
- kjs/regexp_object.cpp \
- kjs/scope_chain.cpp \
- kjs/string_object.cpp \
- kjs/ustring.cpp \
- kjs/value.cpp \
- wtf/FastMalloc.cpp
-
-!qt-port:SOURCES += \
- wtf/TCSystemAlloc.cpp
-}
-
-qt-port:SOURCES += \
- bindings/qt/qt_class.cpp \
- bindings/qt/qt_instance.cpp \
- bindings/qt/qt_runtime.cpp
-
-!CONFIG(QTDIR_build) {
- defineTest(addExtraCompiler) {
- QMAKE_EXTRA_COMPILERS += $$1
- generated_files.depends += compiler_$${1}_make_all
- export(QMAKE_EXTRA_COMPILERS)
- export(generated_files.depends)
- return(true)
- }
-}
+ runtime/ArgList.cpp \
+ runtime/Arguments.cpp \
+ runtime/ArrayConstructor.cpp \
+ runtime/ArrayPrototype.cpp \
+ runtime/BooleanConstructor.cpp \
+ runtime/BooleanObject.cpp \
+ runtime/BooleanPrototype.cpp \
+ runtime/CallData.cpp \
+ runtime/Collector.cpp \
+ runtime/CommonIdentifiers.cpp \
+ runtime/ConstructData.cpp \
+ wtf/CurrentTime.cpp \
+ runtime/DateConstructor.cpp \
+ runtime/DateInstance.cpp \
+ runtime/DateMath.cpp \
+ runtime/DatePrototype.cpp \
+ debugger/Debugger.cpp \
+ debugger/DebuggerCallFrame.cpp \
+ debugger/DebuggerActivation.cpp \
+ wtf/dtoa.cpp \
+ runtime/Error.cpp \
+ runtime/ErrorConstructor.cpp \
+ runtime/ErrorInstance.cpp \
+ runtime/ErrorPrototype.cpp \
+ interpreter/CallFrame.cpp \
+ runtime/FunctionConstructor.cpp \
+ runtime/FunctionPrototype.cpp \
+ runtime/GetterSetter.cpp \
+ runtime/GlobalEvalFunction.cpp \
+ runtime/Identifier.cpp \
+ runtime/InternalFunction.cpp \
+ runtime/Completion.cpp \
+ runtime/JSArray.cpp \
+ runtime/JSByteArray.cpp \
+ runtime/JSCell.cpp \
+ runtime/JSFunction.cpp \
+ runtime/JSGlobalObjectFunctions.cpp \
+ runtime/JSImmediate.cpp \
+ runtime/JSLock.cpp \
+ runtime/JSNumberCell.cpp \
+ runtime/JSObject.cpp \
+ runtime/JSString.cpp \
+ runtime/JSValue.cpp \
+ runtime/JSWrapperObject.cpp \
+ parser/Lexer.cpp \
+ runtime/Lookup.cpp \
+ runtime/MathObject.cpp \
+ runtime/NativeErrorConstructor.cpp \
+ runtime/NativeErrorPrototype.cpp \
+ parser/Nodes.cpp \
+ runtime/NumberConstructor.cpp \
+ runtime/NumberObject.cpp \
+ runtime/NumberPrototype.cpp \
+ runtime/ObjectConstructor.cpp \
+ runtime/ObjectPrototype.cpp \
+ runtime/Operations.cpp \
+ parser/Parser.cpp \
+ runtime/PropertyNameArray.cpp \
+ runtime/PropertySlot.cpp \
+ runtime/PrototypeFunction.cpp \
+ runtime/RegExp.cpp \
+ runtime/RegExpConstructor.cpp \
+ runtime/RegExpObject.cpp \
+ runtime/RegExpPrototype.cpp \
+ runtime/ScopeChain.cpp \
+ runtime/SmallStrings.cpp \
+ runtime/StringConstructor.cpp \
+ runtime/StringObject.cpp \
+ runtime/StringPrototype.cpp \
+ runtime/Structure.cpp \
+ runtime/StructureChain.cpp \
+ runtime/UString.cpp \
+ profiler/HeavyProfile.cpp \
+ profiler/Profile.cpp \
+ profiler/ProfileGenerator.cpp \
+ profiler/ProfileNode.cpp \
+ profiler/Profiler.cpp \
+ profiler/TreeProfile.cpp \
+ wtf/FastMalloc.cpp \
+ wtf/Threading.cpp \
+ wtf/ThreadingQt.cpp \
+ wtf/qt/MainThreadQt.cpp
# GENERATOR 1-A: LUT creator
lut.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.lut.h
-lut.commands = perl $$PWD/kjs/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+lut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
lut.depend = ${QMAKE_FILE_NAME}
lut.input = LUT_FILES
lut.CONFIG += no_link
addExtraCompiler(lut)
# GENERATOR 1-B: particular LUT creator (for 1 file only)
-keywordlut.output = $$GENERATED_SOURCES_DIR/lexer.lut.h
-keywordlut.commands = perl $$PWD/kjs/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+keywordlut.output = $$GENERATED_SOURCES_DIR/Lexer.lut.h
+keywordlut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
keywordlut.depend = ${QMAKE_FILE_NAME}
keywordlut.input = KEYWORDLUT_FILES
keywordlut.CONFIG += no_link
addExtraCompiler(keywordlut)
# GENERATOR 2: bison grammar
-kjsbison.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.cpp
-kjsbison.commands = bison -d -p kjsyy ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_BASE}.tab.c && $(MOVE) ${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) ${QMAKE_FILE_BASE}.tab.h $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.h
-kjsbison.depend = ${QMAKE_FILE_NAME}
-kjsbison.input = KJSBISON
-kjsbison.variable_out = GENERATED_SOURCES
-kjsbison.dependency_type = TYPE_C
-kjsbison.CONFIG = target_predeps
-kjsbison.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE}.h
-addExtraCompiler(kjsbison)
+jscbison.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.cpp
+jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_BASE}.tab.c && $(MOVE) ${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) ${QMAKE_FILE_BASE}.tab.h $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.h
+jscbison.depend = ${QMAKE_FILE_NAME}
+jscbison.input = JSCBISON
+jscbison.variable_out = GENERATED_SOURCES
+jscbison.dependency_type = TYPE_C
+jscbison.CONFIG = target_predeps
+addExtraCompilerWithHeader(jscbison)
+
--- /dev/null
+# JavaScriptCore - qmake build info
+CONFIG += building-libs
+include($$PWD/../WebKit.pri)
+
+TEMPLATE = lib
+CONFIG += staticlib
+TARGET = JavaScriptCore
+
+CONFIG += depend_includepath
+
+contains(QT_CONFIG, embedded):CONFIG += embedded
+
+CONFIG(QTDIR_build) {
+ GENERATED_SOURCES_DIR = $$PWD/generated
+ OLDDESTDIR = $$DESTDIR
+ include($$QT_SOURCE_TREE/src/qbase.pri)
+ INSTALLS =
+ DESTDIR = $$OLDDESTDIR
+ PRECOMPILED_HEADER = $$PWD/../WebKit/qt/WebKit_pch.h
+ DEFINES *= NDEBUG
+}
+
+isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
+GENERATED_SOURCES_DIR_SLASH = $$GENERATED_SOURCES_DIR/
+win32-*: GENERATED_SOURCES_DIR_SLASH ~= s|/|\|
+
+INCLUDEPATH += $$GENERATED_SOURCES_DIR
+
+!CONFIG(QTDIR_build) {
+ OBJECTS_DIR = tmp
+}
+
+include($$OUTPUT_DIR/config.pri)
+
+CONFIG -= warn_on
+*-g++*:QMAKE_CXXFLAGS += -Wreturn-type -fno-strict-aliasing
+#QMAKE_CXXFLAGS += -Wall -Wno-undef -Wno-unused-parameter
+
+CONFIG(release):!CONFIG(QTDIR_build) {
+ contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
+ unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions
+}
+
+linux-*: DEFINES += HAVE_STDINT_H
+freebsd-*: DEFINES += HAVE_PTHREAD_NP_H
+
+DEFINES += BUILD_WEBKIT
+
+win32-*: DEFINES += _HAS_TR1=0
+
+# Pick up 3rdparty libraries from INCLUDE/LIB just like with MSVC
+win32-g++ {
+ TMPPATH = $$quote($$(INCLUDE))
+ QMAKE_INCDIR_POST += $$split(TMPPATH,";")
+ TMPPATH = $$quote($$(LIB))
+ QMAKE_LIBDIR_POST += $$split(TMPPATH,";")
+}
+
+DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1
+
+DEFINES += WTF_CHANGES=1
+
+include(JavaScriptCore.pri)
+
+QMAKE_EXTRA_TARGETS += generated_files
+
+qt-port: lessThan(QT_MINOR_VERSION, 4) {
+ DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
+}
+
+*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
+*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
--- /dev/null
+# The keys in sources are the paths to the directories
+# the values are an array of source files in those directories to compile
+sources = {}
+sources['API'] = [
+ 'API/JSBase.cpp',
+ 'API/JSCallbackConstructor.cpp',
+ 'API/JSCallbackFunction.cpp',
+ 'API/JSCallbackObject.cpp',
+ 'API/JSClassRef.cpp',
+ 'API/JSContextRef.cpp',
+ 'API/JSObjectRef.cpp',
+ 'API/JSProfilerPrivate.cpp',
+ 'API/JSStringRef.cpp',
+ 'API/JSValueRef.cpp',
+ 'API/OpaqueJSString.cpp',
+]
+sources['bytecompiler'] = [
+ 'bytecompiler/BytecodeGenerator.cpp',
+]
+sources['debugger'] = [
+ 'debugger/Debugger.cpp',
+ 'debugger/DebuggerActivation.cpp',
+ 'debugger/DebuggerCallFrame.cpp',
+]
+sources['parser'] = [
+ 'parser/Lexer.cpp',
+ 'parser/Nodes.cpp',
+ 'parser/Parser.cpp',
+]
+sources['pcre'] = [
+ 'pcre/pcre_compile.cpp',
+ 'pcre/pcre_exec.cpp',
+ 'pcre/pcre_tables.cpp',
+ 'pcre/pcre_ucp_searchfuncs.cpp',
+ 'pcre/pcre_xclass.cpp',
+]
+sources['profiler'] = [
+ 'profiler/HeavyProfile.cpp',
+ 'profiler/Profile.cpp',
+ 'profiler/ProfileGenerator.cpp',
+ 'profiler/ProfileNode.cpp',
+ 'profiler/Profiler.cpp',
+ 'profiler/TreeProfile.cpp',
+]
+sources['runtime'] = [
+ 'runtime/ArgList.cpp',
+ 'runtime/Arguments.cpp',
+ 'runtime/ArrayConstructor.cpp',
+ 'runtime/ArrayPrototype.cpp',
+ 'runtime/BooleanConstructor.cpp',
+ 'runtime/BooleanObject.cpp',
+ 'runtime/BooleanPrototype.cpp',
+ 'runtime/CallData.cpp',
+ 'runtime/Collector.cpp',
+ 'runtime/Completion.cpp',
+ 'runtime/CommonIdentifiers.cpp',
+ 'runtime/ConstructData.cpp',
+ 'runtime/DateConstructor.cpp',
+ 'runtime/DateInstance.cpp',
+ 'runtime/DateMath.cpp',
+ 'runtime/DatePrototype.cpp',
+ 'runtime/Error.cpp',
+ 'runtime/ErrorConstructor.cpp',
+ 'runtime/ErrorInstance.cpp',
+ 'runtime/ErrorPrototype.cpp',
+ 'runtime/ExceptionHelpers.cpp',
+ 'runtime/FunctionConstructor.cpp',
+ 'runtime/FunctionPrototype.cpp',
+ 'runtime/GetterSetter.cpp',
+ 'runtime/GlobalEvalFunction.cpp',
+ 'runtime/Identifier.cpp',
+ 'runtime/InitializeThreading.cpp',
+ 'runtime/InternalFunction.cpp',
+ 'runtime/JSActivation.cpp',
+ 'runtime/JSArray.cpp',
+ 'runtime/JSByteArray.cpp',
+ 'runtime/JSCell.cpp',
+ 'runtime/JSFunction.cpp',
+ 'runtime/JSGlobalData.cpp',
+ 'runtime/JSGlobalObject.cpp',
+ 'runtime/JSGlobalObjectFunctions.cpp',
+ 'runtime/JSImmediate.cpp',
+ 'runtime/JSLock.cpp',
+ 'runtime/JSNotAnObject.cpp',
+ 'runtime/JSNumberCell.cpp',
+ 'runtime/JSObject.cpp',
+ 'runtime/JSPropertyNameIterator.cpp',
+ 'runtime/JSStaticScopeObject.cpp',
+ 'runtime/JSString.cpp',
+ 'runtime/JSValue.cpp',
+ 'runtime/JSVariableObject.cpp',
+ 'runtime/JSWrapperObject.cpp',
+ 'runtime/Lookup.cpp',
+ 'runtime/MathObject.cpp',
+ 'runtime/NativeErrorConstructor.cpp',
+ 'runtime/NativeErrorPrototype.cpp',
+ 'runtime/NumberConstructor.cpp',
+ 'runtime/NumberObject.cpp',
+ 'runtime/NumberPrototype.cpp',
+ 'runtime/ObjectConstructor.cpp',
+ 'runtime/ObjectPrototype.cpp',
+ 'runtime/Operations.cpp',
+ 'runtime/PropertyNameArray.cpp',
+ 'runtime/PropertySlot.cpp',
+ 'runtime/PrototypeFunction.cpp',
+ 'runtime/RegExp.cpp',
+ 'runtime/RegExpConstructor.cpp',
+ 'runtime/RegExpObject.cpp',
+ 'runtime/RegExpPrototype.cpp',
+ 'runtime/ScopeChain.cpp',
+ 'runtime/SmallStrings.cpp',
+ 'runtime/StringConstructor.cpp',
+ 'runtime/StringObject.cpp',
+ 'runtime/StringPrototype.cpp',
+ 'runtime/Structure.cpp',
+ 'runtime/StructureChain.cpp',
+ 'runtime/UString.cpp',
+]
+sources['bytecode'] = [
+ 'bytecode/CodeBlock.cpp',
+ 'bytecode/StructureStubInfo.cpp',
+ 'bytecode/JumpTable.cpp',
+ 'bytecode/Opcode.cpp',
+ 'bytecode/SamplingTool.cpp',
+]
+sources['interpreter'] = [
+ 'interpreter/CallFrame.cpp',
+ 'interpreter/Interpreter.cpp',
+ 'interpreter/RegisterFile.cpp',
+]
+sources['jit'] = [
+ 'jit/ExecutableAllocator.cpp',
+ 'jit/JIT.cpp',
+]
+sources['wrec'] = [
+ 'wrec/CharacterClass.cpp',
+ 'wrec/CharacterClassConstructor.cpp',
+ 'wrec/WREC.cpp',
+ 'wrec/WRECFunctors.cpp',
+ 'wrec/WRECGenerator.cpp',
+ 'wrec/WRECParser.cpp',
+]
+sources['wtf'] = [
+ 'wtf/Assertions.cpp',
+ 'wtf/ByteArray.cpp',
+ 'wtf/CurrentTime.cpp',
+ 'wtf/FastMalloc.cpp',
+ 'wtf/HashTable.cpp',
+ 'wtf/RandomNumber.cpp',
+ 'wtf/RefCountedLeakCounter.cpp',
+ 'wtf/Threading.cpp',
+ 'wtf/dtoa.cpp',
+]
+sources['wtf/unicode'] = [
+ 'wtf/unicode/CollatorDefault.cpp',
+ 'wtf/unicode/UTF8.cpp',
+]
+sources['wtf/unicode/icu'] = [
+ 'wtf/unicode/icu/CollatorICU.cpp',
+]
+
+env = Environment()
+
+building_on_win32 = env['PLATFORM'] == 'win32' or env['PLATFORM'] == 'cygwin'
+
+# Scons uses gcc when building under cygwin by default
+# We also have to manually force 8.0 or Scons will try and
+# look up what version to use using the registry and fail
+# due to lack of cygwin-python registry support
+if env['PLATFORM'] == 'cygwin':
+ env['MSVS_VERSION'] = '8.0'
+ # Some systems have PROGRAMFILES, some have ProgramFiles
+ # Scons msvc tool only expects 'ProgramFiles'
+ import os
+ if os.getenv('PROGRAMFILES') and not os.getenv('ProgramFiles'):
+ os.environ['ProgramFiles'] = os.getenv('PROGRAMFILES')
+
+ env.Tool('msvc')
+ env.Tool('mslink')
+ env.Tool('mslib')
+
+# Scons is failing to carry the %PATH% value through correctly
+# Hack IncrediBuild into our path so cl.exe doesn't crash
+if env['PLATFORM'] == 'win32':
+ env.AppendENVPath('PATH', 'c:/Program Files/Xoreax/IncrediBuild')
+
+if env['PLATFORM'] == 'darwin':
+ sources['API'].append('API/JSStringRefCF.cpp')
+ sources['profiler'].append('profiler/ProfilerServer.mm')
+ sources['wtf'].append('wtf/ThreadingPthreads.cpp')
+ sources['wtf'].append('wtf/MainThread.cpp')
+ sources['wtf/mac'] = ['wtf/mac/MainThreadMac.mm']
+ sources['wtf'].append('wtf/TCSystemAlloc.cpp')
+ sources['jit'].append('jit/ExecutableAllocatorPosix.cpp')
+elif building_on_win32:
+ sources['wtf'].append('wtf/ThreadingNone.cpp')
+ sources['jit'].append('jit/ExecutableAllocatorWin.cpp')
+ env.Append(CPPDEFINES = ['ENABLE_JSC_MULTIPLE_THREADS=0'])
+
+derived_sources_path = 'DerivedSources/JavaScriptCore/'
+def DerivedSources(path):
+ return derived_sources_path + path
+
+derived_sources_results = map(DerivedSources, [
+ 'ArrayPrototype.lut.h',
+ 'DatePrototype.lut.h',
+ 'MathObject.lut.h',
+ 'NumberConstructor.lut.h',
+ 'RegExpConstructor.lut.h',
+ 'RegExpObject.lut.h',
+ 'StringPrototype.lut.h'
+ 'chartables.c',
+ 'grammar.cpp',
+ 'grammar.h',
+ 'lexer.lut.h',
+])
+
+derived_sources_sources = [
+ 'runtime/ArrayPrototype.cpp',
+ 'runtime/DatePrototype.cpp',
+ 'runtime/MathObject.cpp',
+ 'runtime/NumberConstructor.cpp',
+ 'runtime/RegExpConstructor.cpp',
+ 'runtime/RegExpObject.cpp',
+ 'runtime/StringPrototype.cpp',
+ 'parser/Grammar.y',
+ 'parser/Lexer.cpp',
+]
+
+# Generate DerivedSources
+# Make sure Windows knows where bash (and all the other cygwin commands) live
+if env['PLATFORM'] == 'win32':
+ env.AppendENVPath('PATH', 'C:/cygwin/bin')
+env.Command(derived_sources_results, derived_sources_sources, 'bash make-generated-sources.sh')
+sources[derived_sources_path] = [DerivedSources('Grammar.cpp')]
+
+# Handle os-version specific build settings
+if env['PLATFORM'] == 'darwin':
+ from subprocess import Popen, PIPE
+ version_pieces = Popen(["sw_vers", "-productVersion"], stdout = PIPE).communicate()[0].split('.')
+ if map(int, version_pieces)[:2] > (10, 5):
+ # Dtrace doesn't exist in Tiger, and was broken in Leopard
+ env.Command(DerivedSources('TracingDtrace.h'), 'runtime/Tracing.d', '/usr/sbin/dtrace -h -o $TARGET -s $SOURCE')
+
+# This build file builds the Chromium port for now, support for
+# others could be added later.
+env.Append(CPPDEFINES = ['BUILDING_CHROMIUM__'])
+
+# I'm not certain how many of these windows defines are actually required.
+if building_on_win32:
+ env.Append(CPPDEFINES = ['_WIN32_WINNT=0x0600', 'WINVER=0x0600', 'WIN32', '_WINDOWS', 'NOMINMAX', 'UNICODE', '_UNICODE', '__STD_C', '_HAS_EXCEPTIONS=0'])
+
+# Scons out-of-the-box only supports precompiled headers for MSVC
+# remove this when we fix Scons to understand GCC precompiled headers
+if env['CC'] == 'gcc':
+ env['CCFLAGS'] = '-include JavaScriptCorePrefix.h'
+# Turns out the MSVC PCH support is badly broken
+# env['PCH'] = 'JavaScriptCorePrefix.h'
+# env['PCHSTOP'] = 'JavaScriptCorePrefix.h'
+
+if env['PLATFORM'] == 'darwin':
+ env['FRAMEWORKS'] = ['CoreFoundation', 'Foundation']
+ env['LIBS'] = ['icucore']
+ # Apple does not ship the ICU headers with Mac OS X, so WebKit includes a copy of 3.2 headers
+ env.Append(CPPPATH = 'icu')
+
+webkit_libraries_path = "../WebKitLibraries/win/"
+def WebKitLibraries(path):
+ return webkit_libraries_path + path
+
+include_paths = ['.', '..', 'ForwardingHeaders'] + sources.keys()
+env.Append(CPPPATH = include_paths)
+if building_on_win32:
+ env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')])
+ env.Prepend(LIBPATH = [WebKitLibraries('lib')])
+ env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm'])
+
+# Save off a copy of the environment for use with jsc
+jsc_env = env.Clone()
+
+if building_on_win32:
+ env.StaticLibrary("JavaScriptCore", sources.values())
+else:
+ env.SharedLibrary("JavaScriptCore", sources.values())
+
+
+env = jsc_env
+
+# Build the jsc testing shell
+shell_sources = ['jsc.cpp']
+build_directory = '.' # This should be changed to point to wherever JavaScriptCore gets built to
+
+# It's hacky to re-use the same environment from JavaScriptCore
+# but it makes building on windows easier for now
+env['CPPPATH'] = include_paths
+env['LIBS'] = ['JavaScriptCore']
+env['LIBPATH'] = [build_directory]
+
+if env['PLATFORM'] == 'darwin':
+ env.Append(LIBS = ['edit'])
+ env.Append(CPPPATH = 'icu')
+elif building_on_win32:
+ env.Append(CPPPATH = ['os-win32', WebKitLibraries('include')])
+ env.Prepend(LIBPATH = [WebKitLibraries('lib')])
+ env.Append(LIBS = ['icuin', 'icuuc', 'user32', 'winmm'])
+
+env.Program('jsc', shell_sources)
#endif
+#if defined(__APPLE__)
+#import <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+#define BUILDING_ON_TIGER 1
+#elif MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+#define BUILDING_ON_LEOPARD 1
+#endif
+#endif
+
#ifdef __cplusplus
#define new ("if you use new/delete make sure to include config.h at the top of the file"())
#define delete ("if you use new/delete make sure to include config.h at the top of the file"())
Source files for JSCore.
-->
<makefile>
- <set append="1" var="JSCORE_SOURCES_API">
+ <set append="1" var="JSCORE_API_SOURCES">
API/JSBase.cpp
API/JSCallbackConstructor.cpp
API/JSCallbackFunction.cpp
API/JSObjectRef.cpp
API/JSStringRef.cpp
API/JSValueRef.cpp
+ API/OpaqueJSString.cpp
</set>
-
- <set append="1" var="JSCORE_SOURCES_BINDINGS">
- bindings/c/c_class.cpp
- bindings/c/c_instance.cpp
- bindings/c/c_runtime.cpp
- bindings/c/c_utility.cpp
- bindings/NP_jsobject.cpp
- bindings/npruntime.cpp
- bindings/runtime.cpp
- bindings/runtime_array.cpp
- bindings/runtime_method.cpp
- bindings/runtime_object.cpp
- bindings/runtime_root.cpp
+ <set append="1" var="JSCORE_BYTECOMPILER_SOURCES">
+ bytecompiler/BytecodeGenerator.cpp
</set>
-
- <set append="1" var="JSCORE_SOURCES_KJS">
- DerivedSources/JavaScriptCore/grammar.cpp
- kjs/array_instance.cpp
- kjs/array_object.cpp
- kjs/bool_object.cpp
- kjs/collector.cpp
- kjs/CommonIdentifiers.cpp
- kjs/date_object.cpp
- kjs/DateMath.cpp
- kjs/debugger.cpp
- kjs/dtoa.cpp
- kjs/error_object.cpp
- kjs/ExecState.cpp
- kjs/function.cpp
- kjs/function_object.cpp
- kjs/identifier.cpp
- kjs/internal.cpp
- kjs/interpreter.cpp
- kjs/JSGlobalObject.cpp
- kjs/JSVariableObject.cpp
- kjs/JSImmediate.cpp
- kjs/JSLock.cpp
- kjs/JSWrapperObject.cpp
- kjs/lexer.cpp
- kjs/list.cpp
- kjs/lookup.cpp
- kjs/math_object.cpp
- kjs/nodes.cpp
- kjs/nodes2string.cpp
- kjs/number_object.cpp
- kjs/object.cpp
- kjs/object_object.cpp
- kjs/operations.cpp
- kjs/Parser.cpp
- kjs/property_map.cpp
- kjs/property_slot.cpp
- kjs/PropertyNameArray.cpp
- kjs/regexp.cpp
- kjs/regexp_object.cpp
- kjs/scope_chain.cpp
- kjs/string_object.cpp
- kjs/ustring.cpp
- kjs/value.cpp
-
+ <set append="1" var="JSCORE_DEBUGGER_SOURCES">
+ debugger/Debugger.cpp
+ debugger/DebuggerActivation.cpp
+ debugger/DebuggerCallFrame.cpp
</set>
- <set append="1" var="JSCORE_SOURCES_PCRE">
+ <set append="1" var="JSCORE_JSC_SOURCES">
+ DerivedSources/JavaScriptCore/Grammar.cpp
+ wtf/dtoa.cpp
+ </set>
+ <set append="1" var="JSCORE_PCRE_SOURCES">
pcre/pcre_compile.cpp
pcre/pcre_exec.cpp
pcre/pcre_tables.cpp
pcre/pcre_ucp_searchfuncs.cpp
pcre/pcre_xclass.cpp
</set>
-
- <set append="1" var="WTF_SOURCES">
+ <set append="1" var="JSCORE_PARSER_SOURCES">
+ parser/Lexer.cpp
+ parser/Nodes.cpp
+ parser/Parser.cpp
+ </set>
+ <set append="1" var="JSCORE_PROFILER_SOURCES">
+ profiler/HeavyProfile.cpp
+ profiler/ProfileGenerator.cpp
+ profiler/ProfileNode.cpp
+ profiler/Profile.cpp
+ profiler/Profiler.cpp
+ profiler/TreeProfile.cpp
+ </set>
+ <set append="1" var="JSCORE_RUNTIME_SOURCES">
+ runtime/ArgList.cpp
+ runtime/Arguments.cpp
+ runtime/ArrayConstructor.cpp
+ runtime/ArrayPrototype.cpp
+ runtime/BooleanConstructor.cpp
+ runtime/BooleanObject.cpp
+ runtime/BooleanPrototype.cpp
+ runtime/CallData.cpp
+ runtime/Collector.cpp
+ runtime/CommonIdentifiers.cpp
+ runtime/ConstructData.cpp
+ runtime/DateConstructor.cpp
+ runtime/DateInstance.cpp
+ runtime/DateMath.cpp
+ runtime/DatePrototype.cpp
+ runtime/Error.cpp
+ runtime/ErrorConstructor.cpp
+ runtime/ErrorInstance.cpp
+ runtime/ErrorPrototype.cpp
+ interpreter/CallFrame.cpp
+ runtime/FunctionConstructor.cpp
+ runtime/FunctionPrototype.cpp
+ runtime/GetterSetter.cpp
+ runtime/GlobalEvalFunction.cpp
+ runtime/Identifier.cpp
+ runtime/InitializeThreading.cpp
+ runtime/InternalFunction.cpp
+ runtime/Completion.cpp
+ runtime/JSActivation.cpp
+ runtime/JSArray.cpp
+ runtime/JSByteArray.cpp
+ runtime/JSCell.cpp
+ runtime/JSFunction.cpp
+ runtime/JSGlobalData.cpp
+ runtime/JSGlobalObject.cpp
+ runtime/JSGlobalObjectFunctions.cpp
+ runtime/JSImmediate.cpp
+ runtime/JSLock.cpp
+ runtime/JSNotAnObject.cpp
+ runtime/JSNumberCell.cpp
+ runtime/JSObject.cpp
+ runtime/JSPropertyNameIterator.cpp
+ runtime/JSStaticScopeObject.cpp
+ runtime/JSString.cpp
+ runtime/JSValue.cpp
+ runtime/JSVariableObject.cpp
+ runtime/JSWrapperObject.cpp
+ runtime/Lookup.cpp
+ runtime/MathObject.cpp
+ runtime/NativeErrorConstructor.cpp
+ runtime/NativeErrorPrototype.cpp
+ runtime/NumberConstructor.cpp
+ runtime/NumberObject.cpp
+ runtime/NumberPrototype.cpp
+ runtime/ObjectConstructor.cpp
+ runtime/ObjectPrototype.cpp
+ runtime/Operations.cpp
+ runtime/PropertyNameArray.cpp
+ runtime/PropertySlot.cpp
+ runtime/PrototypeFunction.cpp
+ runtime/RegExp.cpp
+ runtime/RegExpConstructor.cpp
+ runtime/RegExpObject.cpp
+ runtime/RegExpPrototype.cpp
+ runtime/ScopeChain.cpp
+ runtime/SmallStrings.cpp
+ runtime/StringConstructor.cpp
+ runtime/StringObject.cpp
+ runtime/StringPrototype.cpp
+ runtime/Structure.cpp
+ runtime/StructureChain.cpp
+ runtime/UString.cpp
+ </set>
+ <set append="1" var="JSCORE_VM_SOURCES">
+ bytecode/CodeBlock.cpp
+ bytecode/StructureStubInfo.cpp
+ bytecode/JumpTable.cpp
+ runtime/ExceptionHelpers.cpp
+ interpreter/Interpreter.cpp
+ bytecode/Opcode.cpp
+ bytecode/SamplingTool.cpp
+ interpreter/RegisterFile.cpp
+ </set>
+ <set append="1" var="JSCORE_WTF_SOURCES">
wtf/Assertions.cpp
+ wtf/ByteArray.cpp
+ wtf/CurrentTime.cpp
wtf/FastMalloc.cpp
wtf/HashTable.cpp
+ wtf/MainThread.cpp
+ wtf/RandomNumber.cpp
+ wtf/RefCountedLeakCounter.cpp
wtf/TCSystemAlloc.cpp
+ wtf/Threading.cpp
+ wtf/ThreadingNone.cpp
+ wtf/wx/MainThreadWx.cpp
+ wtf/unicode/CollatorDefault.cpp
+ wtf/unicode/icu/CollatorICU.cpp
wtf/unicode/UTF8.cpp
</set>
--- /dev/null
+SConscript(['JavaScriptCore.scons'])
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AssemblerBuffer_h
+#define AssemblerBuffer_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "stdint.h"
+#include <string.h>
+#include <jit/ExecutableAllocator.h>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+
+namespace JSC {
+
+ class AssemblerBuffer {
+ static const int inlineCapacity = 256;
+ public:
+ AssemblerBuffer()
+ : m_buffer(m_inlineBuffer)
+ , m_capacity(inlineCapacity)
+ , m_size(0)
+ {
+ }
+
+ ~AssemblerBuffer()
+ {
+ if (m_buffer != m_inlineBuffer)
+ fastFree(m_buffer);
+ }
+
+ void ensureSpace(int space)
+ {
+ if (m_size > m_capacity - space)
+ grow();
+ }
+
+ bool isAligned(int alignment) const
+ {
+ return !(m_size & (alignment - 1));
+ }
+
+ void putByteUnchecked(int value)
+ {
+ ASSERT(!(m_size > m_capacity - 4));
+ m_buffer[m_size] = value;
+ m_size++;
+ }
+
+ void putByte(int value)
+ {
+ if (m_size > m_capacity - 4)
+ grow();
+ putByteUnchecked(value);
+ }
+
+ void putShortUnchecked(int value)
+ {
+ ASSERT(!(m_size > m_capacity - 4));
+ *reinterpret_cast<short*>(&m_buffer[m_size]) = value;
+ m_size += 2;
+ }
+
+ void putShort(int value)
+ {
+ if (m_size > m_capacity - 4)
+ grow();
+ putShortUnchecked(value);
+ }
+
+ void putIntUnchecked(int value)
+ {
+ *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
+ m_size += 4;
+ }
+
+ void putInt64Unchecked(int64_t value)
+ {
+ *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
+ m_size += 8;
+ }
+
+ void putInt(int value)
+ {
+ if (m_size > m_capacity - 4)
+ grow();
+ putIntUnchecked(value);
+ }
+
+ void* data() const
+ {
+ return m_buffer;
+ }
+
+ int size() const
+ {
+ return m_size;
+ }
+
+ void* executableCopy(ExecutablePool* allocator)
+ {
+ if (!m_size)
+ return 0;
+
+ void* result = allocator->alloc(m_size);
+
+ if (!result)
+ return 0;
+
+ return memcpy(result, m_buffer, m_size);
+ }
+
+ private:
+ void grow()
+ {
+ m_capacity += m_capacity / 2;
+
+ if (m_buffer == m_inlineBuffer) {
+ char* newBuffer = static_cast<char*>(fastMalloc(m_capacity));
+ m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size));
+ } else
+ m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity));
+ }
+
+ char m_inlineBuffer[inlineCapacity];
+ char* m_buffer;
+ int m_capacity;
+ int m_size;
+ };
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // AssemblerBuffer_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MacroAssembler_h
+#define MacroAssembler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "X86Assembler.h"
+
+namespace JSC {
+
+class MacroAssembler {
+protected:
+ X86Assembler m_assembler;
+
+#if PLATFORM(X86_64)
+ static const X86::RegisterID scratchRegister = X86::r11;
+#endif
+
+public:
+ typedef X86::RegisterID RegisterID;
+
+ // Note: do not rely on values in this enum, these will change (to 0..3).
+ enum Scale {
+ TimesOne = 1,
+ TimesTwo = 2,
+ TimesFour = 4,
+ TimesEight = 8,
+#if PLATFORM(X86)
+ ScalePtr = TimesFour
+#endif
+#if PLATFORM(X86_64)
+ ScalePtr = TimesEight
+#endif
+ };
+
+ MacroAssembler()
+ {
+ }
+
+ size_t size() { return m_assembler.size(); }
+ void* copyCode(ExecutablePool* allocator)
+ {
+ return m_assembler.executableCopy(allocator);
+ }
+
+
+ // Address:
+ //
+ // Describes a simple base-offset address.
+ struct Address {
+ explicit Address(RegisterID base, int32_t offset = 0)
+ : base(base)
+ , offset(offset)
+ {
+ }
+
+ RegisterID base;
+ int32_t offset;
+ };
+
+ // ImplicitAddress:
+ //
+ // This class is used for explicit 'load' and 'store' operations
+ // (as opposed to situations in which a memory operand is provided
+ // to a generic operation, such as an integer arithmetic instruction).
+ //
+ // In the case of a load (or store) operation we want to permit
+ // addresses to be implicitly constructed, e.g. the two calls:
+ //
+ // load32(Address(addrReg), destReg);
+ // load32(addrReg, destReg);
+ //
+ // Are equivalent, and the explicit wrapping of the Address in the former
+ // is unnecessary.
+ struct ImplicitAddress {
+ ImplicitAddress(RegisterID base)
+ : base(base)
+ , offset(0)
+ {
+ }
+
+ ImplicitAddress(Address address)
+ : base(address.base)
+ , offset(address.offset)
+ {
+ }
+
+ RegisterID base;
+ int32_t offset;
+ };
+
+ // BaseIndex:
+ //
+ // Describes a complex addressing mode.
+ struct BaseIndex {
+ BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
+ : base(base)
+ , index(index)
+ , scale(scale)
+ , offset(offset)
+ {
+ }
+
+ RegisterID base;
+ RegisterID index;
+ Scale scale;
+ int32_t offset;
+ };
+
+ // AbsoluteAddress:
+ //
+ // Describes an memory operand given by a pointer. For regular load & store
+ // operations an unwrapped void* will be used, rather than using this.
+ struct AbsoluteAddress {
+ explicit AbsoluteAddress(void* ptr)
+ : m_ptr(ptr)
+ {
+ }
+
+ void* m_ptr;
+ };
+
+
+ class Jump;
+ class PatchBuffer;
+
+ // DataLabelPtr:
+ //
+ // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
+ // patched after the code has been generated.
+ class DataLabelPtr {
+ friend class MacroAssembler;
+ friend class PatchBuffer;
+
+ public:
+ DataLabelPtr()
+ {
+ }
+
+ DataLabelPtr(MacroAssembler* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ static void patch(void* address, void* value)
+ {
+ X86Assembler::patchPointer(reinterpret_cast<intptr_t>(address), reinterpret_cast<intptr_t>(value));
+ }
+
+ private:
+ X86Assembler::JmpDst m_label;
+ };
+
+ // DataLabel32:
+ //
+ // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
+ // patched after the code has been generated.
+ class DataLabel32 {
+ friend class MacroAssembler;
+ friend class PatchBuffer;
+
+ public:
+ DataLabel32()
+ {
+ }
+
+ DataLabel32(MacroAssembler* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ static void patch(void* address, int32_t value)
+ {
+ X86Assembler::patchImmediate(reinterpret_cast<intptr_t>(address), value);
+ }
+
+ private:
+ X86Assembler::JmpDst m_label;
+ };
+
+ // Label:
+ //
+ // A Label records a point in the generated instruction stream, typically such that
+ // it may be used as a destination for a jump.
+ class Label {
+ friend class Jump;
+ friend class MacroAssembler;
+ friend class PatchBuffer;
+
+ public:
+ Label()
+ {
+ }
+
+ Label(MacroAssembler* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ // FIXME: transitionary method, while we replace JmpSrces with Jumps.
+ operator X86Assembler::JmpDst()
+ {
+ return m_label;
+ }
+
+ private:
+ X86Assembler::JmpDst m_label;
+ };
+
+
+ // Jump:
+ //
+ // A jump object is a reference to a jump instruction that has been planted
+ // into the code buffer - it is typically used to link the jump, setting the
+ // relative offset such that when executed it will jump to the desired
+ // destination.
+ //
+ // Jump objects retain a pointer to the assembler for syntactic purposes -
+ // to allow the jump object to be able to link itself, e.g.:
+ //
+ // Jump forwardsBranch = jne32(Imm32(0), reg1);
+ // // ...
+ // forwardsBranch.link();
+ //
+ // Jumps may also be linked to a Label.
+ class Jump {
+ friend class PatchBuffer;
+ friend class MacroAssembler;
+
+ public:
+ Jump()
+ {
+ }
+
+ // FIXME: transitionary method, while we replace JmpSrces with Jumps.
+ Jump(X86Assembler::JmpSrc jmp)
+ : m_jmp(jmp)
+ {
+ }
+
+ void link(MacroAssembler* masm)
+ {
+ masm->m_assembler.link(m_jmp, masm->m_assembler.label());
+ }
+
+ void linkTo(Label label, MacroAssembler* masm)
+ {
+ masm->m_assembler.link(m_jmp, label.m_label);
+ }
+
+ // FIXME: transitionary method, while we replace JmpSrces with Jumps.
+ operator X86Assembler::JmpSrc()
+ {
+ return m_jmp;
+ }
+
+ static void patch(void* address, void* destination)
+ {
+ X86Assembler::patchBranchOffset(reinterpret_cast<intptr_t>(address), destination);
+ }
+
+ private:
+ X86Assembler::JmpSrc m_jmp;
+ };
+
+ // JumpList:
+ //
+ // A JumpList is a set of Jump objects.
+ // All jumps in the set will be linked to the same destination.
+ class JumpList {
+ friend class PatchBuffer;
+
+ public:
+ void link(MacroAssembler* masm)
+ {
+ size_t size = m_jumps.size();
+ for (size_t i = 0; i < size; ++i)
+ m_jumps[i].link(masm);
+ m_jumps.clear();
+ }
+
+ void linkTo(Label label, MacroAssembler* masm)
+ {
+ size_t size = m_jumps.size();
+ for (size_t i = 0; i < size; ++i)
+ m_jumps[i].linkTo(label, masm);
+ m_jumps.clear();
+ }
+
+ void append(Jump jump)
+ {
+ m_jumps.append(jump);
+ }
+
+ void append(JumpList& other)
+ {
+ m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
+ }
+
+ bool empty()
+ {
+ return !m_jumps.size();
+ }
+
+ private:
+ Vector<Jump, 16> m_jumps;
+ };
+
+
+ // PatchBuffer:
+ //
+ // This class assists in linking code generated by the macro assembler, once code generation
+ // has been completed, and the code has been copied to is final location in memory. At this
+ // time pointers to labels within the code may be resolved, and relative offsets to external
+ // addresses may be fixed.
+ //
+ // Specifically:
+ // * Jump objects may be linked to external targets,
+ // * The address of Jump objects may taken, such that it can later be relinked.
+ // * The return address of a Jump object representing a call may be acquired.
+ // * The address of a Label pointing into the code may be resolved.
+ // * The value referenced by a DataLabel may be fixed.
+ //
+ // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
+ // address of calls, as opposed to a point that can be used to later relink a Jump -
+ // possibly wrap the later up in an object that can do just that).
+ class PatchBuffer {
+ public:
+ PatchBuffer(void* code)
+ : m_code(code)
+ {
+ }
+
+ void link(Jump jump, void* target)
+ {
+ X86Assembler::link(m_code, jump.m_jmp, target);
+ }
+
+ void link(JumpList list, void* target)
+ {
+ for (unsigned i = 0; i < list.m_jumps.size(); ++i)
+ X86Assembler::link(m_code, list.m_jumps[i], target);
+ }
+
+ void* addressOf(Jump jump)
+ {
+ return X86Assembler::getRelocatedAddress(m_code, jump.m_jmp);
+ }
+
+ void* addressOf(Label label)
+ {
+ return X86Assembler::getRelocatedAddress(m_code, label.m_label);
+ }
+
+ void* addressOf(DataLabelPtr label)
+ {
+ return X86Assembler::getRelocatedAddress(m_code, label.m_label);
+ }
+
+ void* addressOf(DataLabel32 label)
+ {
+ return X86Assembler::getRelocatedAddress(m_code, label.m_label);
+ }
+
+ void setPtr(DataLabelPtr label, void* value)
+ {
+ X86Assembler::patchAddress(m_code, label.m_label, value);
+ }
+
+ private:
+ void* m_code;
+ };
+
+
+ // ImmPtr:
+ //
+ // A pointer sized immediate operand to an instruction - this is wrapped
+ // in a class requiring explicit construction in order to differentiate
+ // from pointers used as absolute addresses to memory operations
+ struct ImmPtr {
+ explicit ImmPtr(void* value)
+ : m_value(value)
+ {
+ }
+
+ intptr_t asIntptr()
+ {
+ return reinterpret_cast<intptr_t>(m_value);
+ }
+
+ void* m_value;
+ };
+
+
+ // Imm32:
+ //
+ // A 32bit immediate operand to an instruction - this is wrapped in a
+ // class requiring explicit construction in order to prevent RegisterIDs
+ // (which are implemented as an enum) from accidentally being passed as
+ // immediate values.
+ struct Imm32 {
+ explicit Imm32(int32_t value)
+ : m_value(value)
+ {
+ }
+
+#if PLATFORM(X86)
+ explicit Imm32(ImmPtr ptr)
+ : m_value(ptr.asIntptr())
+ {
+ }
+#endif
+
+ int32_t m_value;
+ };
+
+ // Integer arithmetic operations:
+ //
+ // Operations are typically two operand - operation(source, srcDst)
+ // For many operations the source may be an Imm32, the srcDst operand
+ // may often be a memory location (explictly described using an Address
+ // object).
+
+ void addPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.addq_rr(src, dest);
+#else
+ add32(src, dest);
+#endif
+ }
+
+ void addPtr(Imm32 imm, RegisterID srcDest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.addq_ir(imm.m_value, srcDest);
+#else
+ add32(imm, srcDest);
+#endif
+ }
+
+ void addPtr(ImmPtr imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ m_assembler.addq_rr(scratchRegister, dest);
+#else
+ add32(Imm32(imm), dest);
+#endif
+ }
+
+ void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ m_assembler.leal_mr(imm.m_value, src, dest);
+ }
+
+ void add32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.addl_rr(src, dest);
+ }
+
+ void add32(Imm32 imm, Address address)
+ {
+ m_assembler.addl_im(imm.m_value, address.offset, address.base);
+ }
+
+ void add32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.addl_ir(imm.m_value, dest);
+ }
+
+ void add32(Imm32 imm, AbsoluteAddress address)
+ {
+#if PLATFORM(X86_64)
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ add32(imm, Address(scratchRegister));
+#else
+ m_assembler.addl_im(imm.m_value, address.m_ptr);
+#endif
+ }
+
+ void add32(Address src, RegisterID dest)
+ {
+ m_assembler.addl_mr(src.offset, src.base, dest);
+ }
+
+ void andPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.andq_rr(src, dest);
+#else
+ and32(src, dest);
+#endif
+ }
+
+ void andPtr(Imm32 imm, RegisterID srcDest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.andq_ir(imm.m_value, srcDest);
+#else
+ and32(imm, srcDest);
+#endif
+ }
+
+ void and32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.andl_rr(src, dest);
+ }
+
+ void and32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.andl_ir(imm.m_value, dest);
+ }
+
+ void lshift32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.shll_i8r(imm.m_value, dest);
+ }
+
+ void lshift32(RegisterID shift_amount, RegisterID dest)
+ {
+ // On x86 we can only shift by ecx; if asked to shift by another register we'll
+ // need rejig the shift amount into ecx first, and restore the registers afterwards.
+ if (shift_amount != X86::ecx) {
+ swap(shift_amount, X86::ecx);
+
+ // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
+ if (dest == shift_amount)
+ m_assembler.shll_CLr(X86::ecx);
+ // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
+ else if (dest == X86::ecx)
+ m_assembler.shll_CLr(shift_amount);
+ // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
+ else
+ m_assembler.shll_CLr(dest);
+
+ swap(shift_amount, X86::ecx);
+ } else
+ m_assembler.shll_CLr(dest);
+ }
+
+ // Take the value from dividend, divide it by divisor, and put the remainder in remainder.
+ // For now, this operation has specific register requirements, and the three register must
+ // be unique. It is unfortunate to expose this in the MacroAssembler interface, however
+ // given the complexity to fix, the fact that it is not uncommmon for processors to have
+ // specific register requirements on this operation (e.g. Mips result in 'hi'), or to not
+ // support a hardware divide at all, it may not be
+ void mod32(RegisterID divisor, RegisterID dividend, RegisterID remainder)
+ {
+#ifdef NDEBUG
+#pragma unused(dividend,remainder)
+#else
+ ASSERT((dividend == X86::eax) && (remainder == X86::edx));
+ ASSERT((dividend != divisor) && (remainder != divisor));
+#endif
+
+ m_assembler.cdq();
+ m_assembler.idivl_r(divisor);
+ }
+
+ void mul32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.imull_rr(src, dest);
+ }
+
+ void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ m_assembler.imull_i32r(src, imm.m_value, dest);
+ }
+
+ void not32(RegisterID srcDest)
+ {
+ m_assembler.notl_r(srcDest);
+ }
+
+ void orPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.orq_rr(src, dest);
+#else
+ or32(src, dest);
+#endif
+ }
+
+ void orPtr(ImmPtr imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ m_assembler.orq_rr(scratchRegister, dest);
+#else
+ or32(Imm32(imm), dest);
+#endif
+ }
+
+ void orPtr(Imm32 imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.orq_ir(imm.m_value, dest);
+#else
+ or32(imm, dest);
+#endif
+ }
+
+ void or32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.orl_rr(src, dest);
+ }
+
+ void or32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.orl_ir(imm.m_value, dest);
+ }
+
+ void rshiftPtr(RegisterID shift_amount, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ // On x86 we can only shift by ecx; if asked to shift by another register we'll
+ // need rejig the shift amount into ecx first, and restore the registers afterwards.
+ if (shift_amount != X86::ecx) {
+ swap(shift_amount, X86::ecx);
+
+ // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
+ if (dest == shift_amount)
+ m_assembler.sarq_CLr(X86::ecx);
+ // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
+ else if (dest == X86::ecx)
+ m_assembler.sarq_CLr(shift_amount);
+ // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
+ else
+ m_assembler.sarq_CLr(dest);
+
+ swap(shift_amount, X86::ecx);
+ } else
+ m_assembler.sarq_CLr(dest);
+#else
+ rshift32(shift_amount, dest);
+#endif
+ }
+
+ void rshiftPtr(Imm32 imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.sarq_i8r(imm.m_value, dest);
+#else
+ rshift32(imm, dest);
+#endif
+ }
+
+ void rshift32(RegisterID shift_amount, RegisterID dest)
+ {
+ // On x86 we can only shift by ecx; if asked to shift by another register we'll
+ // need rejig the shift amount into ecx first, and restore the registers afterwards.
+ if (shift_amount != X86::ecx) {
+ swap(shift_amount, X86::ecx);
+
+ // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
+ if (dest == shift_amount)
+ m_assembler.sarl_CLr(X86::ecx);
+ // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
+ else if (dest == X86::ecx)
+ m_assembler.sarl_CLr(shift_amount);
+ // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
+ else
+ m_assembler.sarl_CLr(dest);
+
+ swap(shift_amount, X86::ecx);
+ } else
+ m_assembler.sarl_CLr(dest);
+ }
+
+ void rshift32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.sarl_i8r(imm.m_value, dest);
+ }
+
+ void subPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.subq_rr(src, dest);
+#else
+ sub32(src, dest);
+#endif
+ }
+
+ void subPtr(Imm32 imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.subq_ir(imm.m_value, dest);
+#else
+ sub32(imm, dest);
+#endif
+ }
+
+ void subPtr(ImmPtr imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ m_assembler.subq_rr(scratchRegister, dest);
+#else
+ sub32(Imm32(imm), dest);
+#endif
+ }
+
+ void sub32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.subl_rr(src, dest);
+ }
+
+ void sub32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.subl_ir(imm.m_value, dest);
+ }
+
+ void sub32(Imm32 imm, Address address)
+ {
+ m_assembler.subl_im(imm.m_value, address.offset, address.base);
+ }
+
+ void sub32(Imm32 imm, AbsoluteAddress address)
+ {
+#if PLATFORM(X86_64)
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ sub32(imm, Address(scratchRegister));
+#else
+ m_assembler.subl_im(imm.m_value, address.m_ptr);
+#endif
+ }
+
+ void sub32(Address src, RegisterID dest)
+ {
+ m_assembler.subl_mr(src.offset, src.base, dest);
+ }
+
+ void xorPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.xorq_rr(src, dest);
+#else
+ xor32(src, dest);
+#endif
+ }
+
+ void xorPtr(Imm32 imm, RegisterID srcDest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.xorq_ir(imm.m_value, srcDest);
+#else
+ xor32(imm, srcDest);
+#endif
+ }
+
+ void xor32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.xorl_rr(src, dest);
+ }
+
+ void xor32(Imm32 imm, RegisterID srcDest)
+ {
+ m_assembler.xorl_ir(imm.m_value, srcDest);
+ }
+
+
+ // Memory access operations:
+ //
+ // Loads are of the form load(address, destination) and stores of the form
+ // store(source, address). The source for a store may be an Imm32. Address
+ // operand objects to loads and store will be implicitly constructed if a
+ // register is passed.
+
+ void loadPtr(ImplicitAddress address, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_mr(address.offset, address.base, dest);
+#else
+ load32(address, dest);
+#endif
+ }
+
+ DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_mr_disp32(address.offset, address.base, dest);
+ return DataLabel32(this);
+#else
+ m_assembler.movl_mr_disp32(address.offset, address.base, dest);
+ return DataLabel32(this);
+#endif
+ }
+
+ void loadPtr(BaseIndex address, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest);
+#else
+ load32(address, dest);
+#endif
+ }
+
+ void loadPtr(void* address, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ if (dest == X86::eax)
+ m_assembler.movq_mEAX(address);
+ else {
+ move(X86::eax, dest);
+ m_assembler.movq_mEAX(address);
+ swap(X86::eax, dest);
+ }
+#else
+ load32(address, dest);
+#endif
+ }
+
+ void load32(ImplicitAddress address, RegisterID dest)
+ {
+ m_assembler.movl_mr(address.offset, address.base, dest);
+ }
+
+ void load32(BaseIndex address, RegisterID dest)
+ {
+ m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
+ }
+
+ void load32(void* address, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ if (dest == X86::eax)
+ m_assembler.movl_mEAX(address);
+ else {
+ move(X86::eax, dest);
+ m_assembler.movl_mEAX(address);
+ swap(X86::eax, dest);
+ }
+#else
+ m_assembler.movl_mr(address, dest);
+#endif
+ }
+
+ void load16(BaseIndex address, RegisterID dest)
+ {
+ m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
+ }
+
+ void storePtr(RegisterID src, ImplicitAddress address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_rm(src, address.offset, address.base);
+#else
+ store32(src, address);
+#endif
+ }
+
+ DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_rm_disp32(src, address.offset, address.base);
+ return DataLabel32(this);
+#else
+ m_assembler.movl_rm_disp32(src, address.offset, address.base);
+ return DataLabel32(this);
+#endif
+ }
+
+ void storePtr(RegisterID src, BaseIndex address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_rm(src, address.offset, address.base, address.index, address.scale);
+#else
+ store32(src, address);
+#endif
+ }
+
+ void storePtr(ImmPtr imm, ImplicitAddress address)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ storePtr(scratchRegister, address);
+#else
+ m_assembler.movl_i32m(imm.asIntptr(), address.offset, address.base);
+#endif
+ }
+
+#if !PLATFORM(X86_64)
+ void storePtr(ImmPtr imm, void* address)
+ {
+ store32(Imm32(imm), address);
+ }
+#endif
+
+ DataLabelPtr storePtrWithPatch(Address address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_i64r(0, scratchRegister);
+ DataLabelPtr label(this);
+ storePtr(scratchRegister, address);
+ return label;
+#else
+ m_assembler.movl_i32m(0, address.offset, address.base);
+ return DataLabelPtr(this);
+#endif
+ }
+
+ void store32(RegisterID src, ImplicitAddress address)
+ {
+ m_assembler.movl_rm(src, address.offset, address.base);
+ }
+
+ void store32(RegisterID src, BaseIndex address)
+ {
+ m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
+ }
+
+ void store32(Imm32 imm, ImplicitAddress address)
+ {
+ m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
+ }
+
+ void store32(Imm32 imm, void* address)
+ {
+#if PLATFORM(X86_64)
+ move(X86::eax, scratchRegister);
+ move(imm, X86::eax);
+ m_assembler.movl_EAXm(address);
+ move(scratchRegister, X86::eax);
+#else
+ m_assembler.movl_i32m(imm.m_value, address);
+#endif
+ }
+
+
+ // Stack manipulation operations:
+ //
+ // The ABI is assumed to provide a stack abstraction to memory,
+ // containing machine word sized units of data. Push and pop
+ // operations add and remove a single register sized unit of data
+ // to or from the stack. Peek and poke operations read or write
+ // values on the stack, without moving the current stack position.
+
+ void pop(RegisterID dest)
+ {
+ m_assembler.pop_r(dest);
+ }
+
+ void push(RegisterID src)
+ {
+ m_assembler.push_r(src);
+ }
+
+ void push(Address address)
+ {
+ m_assembler.push_m(address.offset, address.base);
+ }
+
+ void push(Imm32 imm)
+ {
+ m_assembler.push_i32(imm.m_value);
+ }
+
+ void pop()
+ {
+ addPtr(Imm32(sizeof(void*)), X86::esp);
+ }
+
+ void peek(RegisterID dest, int index = 0)
+ {
+ loadPtr(Address(X86::esp, (index * sizeof(void *))), dest);
+ }
+
+ void poke(RegisterID src, int index = 0)
+ {
+ storePtr(src, Address(X86::esp, (index * sizeof(void *))));
+ }
+
+ void poke(Imm32 value, int index = 0)
+ {
+ store32(value, Address(X86::esp, (index * sizeof(void *))));
+ }
+
+ void poke(ImmPtr imm, int index = 0)
+ {
+ storePtr(imm, Address(X86::esp, (index * sizeof(void *))));
+ }
+
+ // Register move operations:
+ //
+ // Move values in registers.
+
+ void move(Imm32 imm, RegisterID dest)
+ {
+ // Note: on 64-bit the Imm32 value is zero extended into the register, it
+ // may be useful to have a separate version that sign extends the value?
+ if (!imm.m_value)
+ m_assembler.xorl_rr(dest, dest);
+ else
+ m_assembler.movl_i32r(imm.m_value, dest);
+ }
+
+ void move(RegisterID src, RegisterID dest)
+ {
+ // Note: on 64-bit this is is a full register move; perhaps it would be
+ // useful to have separate move32 & movePtr, with move32 zero extending?
+#if PLATFORM(X86_64)
+ m_assembler.movq_rr(src, dest);
+#else
+ m_assembler.movl_rr(src, dest);
+#endif
+ }
+
+ void move(ImmPtr imm, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ if (CAN_SIGN_EXTEND_U32_64(imm.asIntptr()))
+ m_assembler.movl_i32r(static_cast<int32_t>(imm.asIntptr()), dest);
+ else
+ m_assembler.movq_i64r(imm.asIntptr(), dest);
+#else
+ m_assembler.movl_i32r(imm.asIntptr(), dest);
+#endif
+ }
+
+ void swap(RegisterID reg1, RegisterID reg2)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.xchgq_rr(reg1, reg2);
+#else
+ m_assembler.xchgl_rr(reg1, reg2);
+#endif
+ }
+
+ void signExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movsxd_rr(src, dest);
+#else
+ if (src != dest)
+ move(src, dest);
+#endif
+ }
+
+ void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movl_rr(src, dest);
+#else
+ if (src != dest)
+ move(src, dest);
+#endif
+ }
+
+
+ // Forwards / external control flow operations:
+ //
+ // This set of jump and conditional branch operations return a Jump
+ // object which may linked at a later point, allow forwards jump,
+ // or jumps that will require external linkage (after the code has been
+ // relocated).
+ //
+ // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
+ // respecitvely, for unsigned comparisons the names b, a, be, and ae are
+ // used (representing the names 'below' and 'above').
+ //
+ // Operands to the comparision are provided in the expected order, e.g.
+ // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
+ // treated as a signed 32bit value, is less than or equal to 5.
+ //
+ // jz and jnz test whether the first operand is equal to zero, and take
+ // an optional second operand of a mask under which to perform the test.
+
+private:
+ void compareImm32ForBranch(RegisterID left, int32_t right)
+ {
+ m_assembler.cmpl_ir(right, left);
+ }
+
+ void compareImm32ForBranchEquality(RegisterID reg, int32_t imm)
+ {
+ if (!imm)
+ m_assembler.testl_rr(reg, reg);
+ else
+ m_assembler.cmpl_ir(imm, reg);
+ }
+
+ void compareImm32ForBranchEquality(Address address, int32_t imm)
+ {
+ m_assembler.cmpl_im(imm, address.offset, address.base);
+ }
+
+ void testImm32(RegisterID reg, Imm32 mask)
+ {
+ // if we are only interested in the low seven bits, this can be tested with a testb
+ if (mask.m_value == -1)
+ m_assembler.testl_rr(reg, reg);
+ else if ((mask.m_value & ~0x7f) == 0)
+ m_assembler.testb_i8r(mask.m_value, reg);
+ else
+ m_assembler.testl_i32r(mask.m_value, reg);
+ }
+
+ void testImm32(Address address, Imm32 mask)
+ {
+ if (mask.m_value == -1)
+ m_assembler.cmpl_im(0, address.offset, address.base);
+ else
+ m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
+ }
+
+ void testImm32(BaseIndex address, Imm32 mask)
+ {
+ if (mask.m_value == -1)
+ m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
+ else
+ m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
+ }
+
+#if PLATFORM(X86_64)
+ void compareImm64ForBranch(RegisterID left, int32_t right)
+ {
+ m_assembler.cmpq_ir(right, left);
+ }
+
+ void compareImm64ForBranchEquality(RegisterID reg, int32_t imm)
+ {
+ if (!imm)
+ m_assembler.testq_rr(reg, reg);
+ else
+ m_assembler.cmpq_ir(imm, reg);
+ }
+
+ void testImm64(RegisterID reg, Imm32 mask)
+ {
+ // if we are only interested in the low seven bits, this can be tested with a testb
+ if (mask.m_value == -1)
+ m_assembler.testq_rr(reg, reg);
+ else if ((mask.m_value & ~0x7f) == 0)
+ m_assembler.testb_i8r(mask.m_value, reg);
+ else
+ m_assembler.testq_i32r(mask.m_value, reg);
+ }
+
+ void testImm64(Address address, Imm32 mask)
+ {
+ if (mask.m_value == -1)
+ m_assembler.cmpq_im(0, address.offset, address.base);
+ else
+ m_assembler.testq_i32m(mask.m_value, address.offset, address.base);
+ }
+
+ void testImm64(BaseIndex address, Imm32 mask)
+ {
+ if (mask.m_value == -1)
+ m_assembler.cmpq_im(0, address.offset, address.base, address.index, address.scale);
+ else
+ m_assembler.testq_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
+ }
+#endif
+
+public:
+ Jump ja32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.ja());
+ }
+
+ Jump jaePtr(RegisterID left, RegisterID right)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jae());
+#else
+ return jae32(left, right);
+#endif
+ }
+
+ Jump jaePtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranch(reg, imm);
+ return Jump(m_assembler.jae());
+ } else {
+ move(ptr, scratchRegister);
+ return jaePtr(reg, scratchRegister);
+ }
+#else
+ return jae32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jae32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jae());
+ }
+
+ Jump jae32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.jae());
+ }
+
+ Jump jae32(RegisterID left, Address right)
+ {
+ m_assembler.cmpl_mr(right.offset, right.base, left);
+ return Jump(m_assembler.jae());
+ }
+
+ Jump jae32(Address left, RegisterID right)
+ {
+ m_assembler.cmpl_rm(right, left.offset, left.base);
+ return Jump(m_assembler.jae());
+ }
+
+ Jump jbPtr(RegisterID left, RegisterID right)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jb());
+#else
+ return jb32(left, right);
+#endif
+ }
+
+ Jump jbPtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranch(reg, imm);
+ return Jump(m_assembler.jb());
+ } else {
+ move(ptr, scratchRegister);
+ return jbPtr(reg, scratchRegister);
+ }
+#else
+ return jb32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jb32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jb());
+ }
+
+ Jump jb32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.jb());
+ }
+
+ Jump jb32(RegisterID left, Address right)
+ {
+ m_assembler.cmpl_mr(right.offset, right.base, left);
+ return Jump(m_assembler.jb());
+ }
+
+ Jump jePtr(RegisterID op1, RegisterID op2)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(op1, op2);
+ return Jump(m_assembler.je());
+#else
+ return je32(op1, op2);
+#endif
+ }
+
+ Jump jePtr(RegisterID reg, Address address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rm(reg, address.offset, address.base);
+#else
+ m_assembler.cmpl_rm(reg, address.offset, address.base);
+#endif
+ return Jump(m_assembler.je());
+ }
+
+ Jump jePtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranchEquality(reg, imm);
+ return Jump(m_assembler.je());
+ } else {
+ move(ptr, scratchRegister);
+ return jePtr(scratchRegister, reg);
+ }
+#else
+ return je32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jePtr(Address address, ImmPtr imm)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ return jePtr(scratchRegister, address);
+#else
+ return je32(address, Imm32(imm));
+#endif
+ }
+
+ Jump je32(RegisterID op1, RegisterID op2)
+ {
+ m_assembler.cmpl_rr(op1, op2);
+ return Jump(m_assembler.je());
+ }
+
+ Jump je32(Address op1, RegisterID op2)
+ {
+ m_assembler.cmpl_mr(op1.offset, op1.base, op2);
+ return Jump(m_assembler.je());
+ }
+
+ Jump je32(RegisterID reg, Imm32 imm)
+ {
+ compareImm32ForBranchEquality(reg, imm.m_value);
+ return Jump(m_assembler.je());
+ }
+
+ Jump je32(Address address, Imm32 imm)
+ {
+ compareImm32ForBranchEquality(address, imm.m_value);
+ return Jump(m_assembler.je());
+ }
+
+ Jump je16(RegisterID op1, BaseIndex op2)
+ {
+ m_assembler.cmpw_rm(op1, op2.offset, op2.base, op2.index, op2.scale);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jg32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jg());
+ }
+
+ Jump jg32(RegisterID reg, Address address)
+ {
+ m_assembler.cmpl_mr(address.offset, address.base, reg);
+ return Jump(m_assembler.jg());
+ }
+
+ Jump jgePtr(RegisterID left, RegisterID right)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jge());
+#else
+ return jge32(left, right);
+#endif
+ }
+
+ Jump jgePtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranch(reg, imm);
+ return Jump(m_assembler.jge());
+ } else {
+ move(ptr, scratchRegister);
+ return jgePtr(reg, scratchRegister);
+ }
+#else
+ return jge32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jge32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jge());
+ }
+
+ Jump jge32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.jge());
+ }
+
+ Jump jlPtr(RegisterID left, RegisterID right)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jl());
+#else
+ return jl32(left, right);
+#endif
+ }
+
+ Jump jlPtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranch(reg, imm);
+ return Jump(m_assembler.jl());
+ } else {
+ move(ptr, scratchRegister);
+ return jlPtr(reg, scratchRegister);
+ }
+#else
+ return jl32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jl32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jl());
+ }
+
+ Jump jl32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.jl());
+ }
+
+ Jump jlePtr(RegisterID left, RegisterID right)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jle());
+#else
+ return jle32(left, right);
+#endif
+ }
+
+ Jump jlePtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranch(reg, imm);
+ return Jump(m_assembler.jle());
+ } else {
+ move(ptr, scratchRegister);
+ return jlePtr(reg, scratchRegister);
+ }
+#else
+ return jle32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jle32(RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jle());
+ }
+
+ Jump jle32(RegisterID left, Imm32 right)
+ {
+ compareImm32ForBranch(left, right.m_value);
+ return Jump(m_assembler.jle());
+ }
+
+ Jump jnePtr(RegisterID op1, RegisterID op2)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rr(op1, op2);
+ return Jump(m_assembler.jne());
+#else
+ return jne32(op1, op2);
+#endif
+ }
+
+ Jump jnePtr(RegisterID reg, Address address)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.cmpq_rm(reg, address.offset, address.base);
+#else
+ m_assembler.cmpl_rm(reg, address.offset, address.base);
+#endif
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jnePtr(RegisterID reg, AbsoluteAddress address)
+ {
+#if PLATFORM(X86_64)
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ return jnePtr(reg, Address(scratchRegister));
+#else
+ m_assembler.cmpl_rm(reg, address.m_ptr);
+ return Jump(m_assembler.jne());
+#endif
+ }
+
+ Jump jnePtr(RegisterID reg, ImmPtr ptr)
+ {
+#if PLATFORM(X86_64)
+ intptr_t imm = ptr.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ compareImm64ForBranchEquality(reg, imm);
+ return Jump(m_assembler.jne());
+ } else {
+ move(ptr, scratchRegister);
+ return jnePtr(scratchRegister, reg);
+ }
+#else
+ return jne32(reg, Imm32(ptr));
+#endif
+ }
+
+ Jump jnePtr(Address address, ImmPtr imm)
+ {
+#if PLATFORM(X86_64)
+ move(imm, scratchRegister);
+ return jnePtr(scratchRegister, address);
+#else
+ return jne32(address, Imm32(imm));
+#endif
+ }
+
+#if !PLATFORM(X86_64)
+ Jump jnePtr(AbsoluteAddress address, ImmPtr imm)
+ {
+ m_assembler.cmpl_im(imm.asIntptr(), address.m_ptr);
+ return Jump(m_assembler.jne());
+ }
+#endif
+
+ Jump jnePtrWithPatch(RegisterID reg, DataLabelPtr& dataLabel, ImmPtr initialValue = ImmPtr(0))
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister);
+ dataLabel = DataLabelPtr(this);
+ return jnePtr(scratchRegister, reg);
+#else
+ m_assembler.cmpl_ir_force32(initialValue.asIntptr(), reg);
+ dataLabel = DataLabelPtr(this);
+ return Jump(m_assembler.jne());
+#endif
+ }
+
+ Jump jnePtrWithPatch(Address address, DataLabelPtr& dataLabel, ImmPtr initialValue = ImmPtr(0))
+ {
+#if PLATFORM(X86_64)
+ m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister);
+ dataLabel = DataLabelPtr(this);
+ return jnePtr(scratchRegister, address);
+#else
+ m_assembler.cmpl_im_force32(initialValue.asIntptr(), address.offset, address.base);
+ dataLabel = DataLabelPtr(this);
+ return Jump(m_assembler.jne());
+#endif
+ }
+
+ Jump jne32(RegisterID op1, RegisterID op2)
+ {
+ m_assembler.cmpl_rr(op1, op2);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jne32(RegisterID reg, Imm32 imm)
+ {
+ compareImm32ForBranchEquality(reg, imm.m_value);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jne32(Address address, Imm32 imm)
+ {
+ compareImm32ForBranchEquality(address, imm.m_value);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jne32(Address address, RegisterID reg)
+ {
+ m_assembler.cmpl_rm(reg, address.offset, address.base);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jnzPtr(RegisterID reg, RegisterID mask)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.testq_rr(reg, mask);
+ return Jump(m_assembler.jne());
+#else
+ return jnz32(reg, mask);
+#endif
+ }
+
+ Jump jnzPtr(RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+#if PLATFORM(X86_64)
+ testImm64(reg, mask);
+ return Jump(m_assembler.jne());
+#else
+ return jnz32(reg, mask);
+#endif
+ }
+
+ Jump jnzPtr(RegisterID reg, ImmPtr mask)
+ {
+#if PLATFORM(X86_64)
+ move(mask, scratchRegister);
+ m_assembler.testq_rr(scratchRegister, reg);
+ return Jump(m_assembler.jne());
+#else
+ return jnz32(reg, Imm32(mask));
+#endif
+ }
+
+ Jump jnzPtr(Address address, Imm32 mask = Imm32(-1))
+ {
+#if PLATFORM(X86_64)
+ testImm64(address, mask);
+ return Jump(m_assembler.jne());
+#else
+ return jnz32(address, mask);
+#endif
+ }
+
+ Jump jnz32(RegisterID reg, RegisterID mask)
+ {
+ m_assembler.testl_rr(reg, mask);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jnz32(RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+ testImm32(reg, mask);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jnz32(Address address, Imm32 mask = Imm32(-1))
+ {
+ testImm32(address, mask);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jzPtr(RegisterID reg, RegisterID mask)
+ {
+#if PLATFORM(X86_64)
+ m_assembler.testq_rr(reg, mask);
+ return Jump(m_assembler.je());
+#else
+ return jz32(reg, mask);
+#endif
+ }
+
+ Jump jzPtr(RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+#if PLATFORM(X86_64)
+ testImm64(reg, mask);
+ return Jump(m_assembler.je());
+#else
+ return jz32(reg, mask);
+#endif
+ }
+
+ Jump jzPtr(RegisterID reg, ImmPtr mask)
+ {
+#if PLATFORM(X86_64)
+ move(mask, scratchRegister);
+ m_assembler.testq_rr(scratchRegister, reg);
+ return Jump(m_assembler.je());
+#else
+ return jz32(reg, Imm32(mask));
+#endif
+ }
+
+ Jump jzPtr(Address address, Imm32 mask = Imm32(-1))
+ {
+#if PLATFORM(X86_64)
+ testImm64(address, mask);
+ return Jump(m_assembler.je());
+#else
+ return jz32(address, mask);
+#endif
+ }
+
+ Jump jzPtr(BaseIndex address, Imm32 mask = Imm32(-1))
+ {
+#if PLATFORM(X86_64)
+ testImm64(address, mask);
+ return Jump(m_assembler.je());
+#else
+ return jz32(address, mask);
+#endif
+ }
+
+ Jump jz32(RegisterID reg, RegisterID mask)
+ {
+ m_assembler.testl_rr(reg, mask);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jz32(RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+ testImm32(reg, mask);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jz32(Address address, Imm32 mask = Imm32(-1))
+ {
+ testImm32(address, mask);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jz32(BaseIndex address, Imm32 mask = Imm32(-1))
+ {
+ testImm32(address, mask);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jump()
+ {
+ return Jump(m_assembler.jmp());
+ }
+
+
+ // Backwards, local control flow operations:
+ //
+ // These operations provide a shorter notation for local
+ // backwards branches, which may be both more convenient
+ // for the user, and for the programmer, and for the
+ // assembler (allowing shorter values to be used in
+ // relative offsets).
+ //
+ // The code sequence:
+ //
+ // Label topOfLoop(this);
+ // // ...
+ // jne32(reg1, reg2, topOfLoop);
+ //
+ // Is equivalent to the longer, potentially less efficient form:
+ //
+ // Label topOfLoop(this);
+ // // ...
+ // jne32(reg1, reg2).linkTo(topOfLoop);
+
+ void jae32(RegisterID left, Address right, Label target)
+ {
+ jae32(left, right).linkTo(target, this);
+ }
+
+ void je32(RegisterID op1, Imm32 imm, Label target)
+ {
+ je32(op1, imm).linkTo(target, this);
+ }
+
+ void je16(RegisterID op1, BaseIndex op2, Label target)
+ {
+ je16(op1, op2).linkTo(target, this);
+ }
+
+ void jl32(RegisterID left, Imm32 right, Label target)
+ {
+ jl32(left, right).linkTo(target, this);
+ }
+
+ void jle32(RegisterID left, RegisterID right, Label target)
+ {
+ jle32(left, right).linkTo(target, this);
+ }
+
+ void jnePtr(RegisterID op1, ImmPtr imm, Label target)
+ {
+ jnePtr(op1, imm).linkTo(target, this);
+ }
+
+ void jne32(RegisterID op1, RegisterID op2, Label target)
+ {
+ jne32(op1, op2).linkTo(target, this);
+ }
+
+ void jne32(RegisterID op1, Imm32 imm, Label target)
+ {
+ jne32(op1, imm).linkTo(target, this);
+ }
+
+ void jzPtr(RegisterID reg, Label target)
+ {
+ jzPtr(reg).linkTo(target, this);
+ }
+
+ void jump(Label target)
+ {
+ m_assembler.link(m_assembler.jmp(), target.m_label);
+ }
+
+ void jump(RegisterID target)
+ {
+ m_assembler.jmp_r(target);
+ }
+
+ // Address is a memory location containing the address to jump to
+ void jump(Address address)
+ {
+ m_assembler.jmp_m(address.offset, address.base);
+ }
+
+
+ // Arithmetic control flow operations:
+ //
+ // This set of conditional branch operations branch based
+ // on the result of an arithmetic operation. The operation
+ // is performed as normal, storing the result.
+ //
+ // * jz operations branch if the result is zero.
+ // * jo operations branch if the (signed) arithmetic
+ // operation caused an overflow to occur.
+
+ Jump jnzSubPtr(Imm32 imm, RegisterID dest)
+ {
+ subPtr(imm, dest);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump jnzSub32(Imm32 imm, RegisterID dest)
+ {
+ sub32(imm, dest);
+ return Jump(m_assembler.jne());
+ }
+
+ Jump joAddPtr(RegisterID src, RegisterID dest)
+ {
+ addPtr(src, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joAdd32(RegisterID src, RegisterID dest)
+ {
+ add32(src, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joAdd32(Imm32 imm, RegisterID dest)
+ {
+ add32(imm, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joMul32(RegisterID src, RegisterID dest)
+ {
+ mul32(src, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joMul32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ mul32(imm, src, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joSub32(RegisterID src, RegisterID dest)
+ {
+ sub32(src, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump joSub32(Imm32 imm, RegisterID dest)
+ {
+ sub32(imm, dest);
+ return Jump(m_assembler.jo());
+ }
+
+ Jump jzSubPtr(Imm32 imm, RegisterID dest)
+ {
+ subPtr(imm, dest);
+ return Jump(m_assembler.je());
+ }
+
+ Jump jzSub32(Imm32 imm, RegisterID dest)
+ {
+ sub32(imm, dest);
+ return Jump(m_assembler.je());
+ }
+
+
+ // Miscellaneous operations:
+
+ void breakpoint()
+ {
+ m_assembler.int3();
+ }
+
+ Jump call()
+ {
+ return Jump(m_assembler.call());
+ }
+
+ // FIXME: why does this return a Jump object? - it can't be linked.
+ // This may be to get a reference to the return address of the call.
+ //
+ // This should probably be handled by a separate label type to a regular
+ // jump. Todo: add a CallLabel type, for the regular call - can be linked
+ // like a jump (possibly a subclass of jump?, or possibly casts to a Jump).
+ // Also add a CallReturnLabel type for this to return (just a more JmpDsty
+ // form of label, can get the void* after the code has been linked, but can't
+ // try to link it like a Jump object), and let the CallLabel be cast into a
+ // CallReturnLabel.
+ Jump call(RegisterID target)
+ {
+ return Jump(m_assembler.call(target));
+ }
+
+ Label label()
+ {
+ return Label(this);
+ }
+
+ Label align()
+ {
+ m_assembler.align(16);
+ return Label(this);
+ }
+
+ ptrdiff_t differenceBetween(Label from, Jump to)
+ {
+ return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+ ptrdiff_t differenceBetween(Label from, Label to)
+ {
+ return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
+ {
+ return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(Label from, DataLabel32 to)
+ {
+ return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
+ {
+ return X86Assembler::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+ void ret()
+ {
+ m_assembler.ret();
+ }
+
+ void sete32(RegisterID src, RegisterID srcDest)
+ {
+ m_assembler.cmpl_rr(srcDest, src);
+ m_assembler.sete_r(srcDest);
+ m_assembler.movzbl_rr(srcDest, srcDest);
+ }
+
+ void sete32(Imm32 imm, RegisterID srcDest)
+ {
+ compareImm32ForBranchEquality(srcDest, imm.m_value);
+ m_assembler.sete_r(srcDest);
+ m_assembler.movzbl_rr(srcDest, srcDest);
+ }
+
+ void setne32(RegisterID src, RegisterID srcDest)
+ {
+ m_assembler.cmpl_rr(srcDest, src);
+ m_assembler.setne_r(srcDest);
+ m_assembler.movzbl_rr(srcDest, srcDest);
+ }
+
+ void setne32(Imm32 imm, RegisterID srcDest)
+ {
+ compareImm32ForBranchEquality(srcDest, imm.m_value);
+ m_assembler.setne_r(srcDest);
+ m_assembler.movzbl_rr(srcDest, srcDest);
+ }
+
+ // FIXME:
+ // The mask should be optional... paerhaps the argument order should be
+ // dest-src, operations always have a dest? ... possibly not true, considering
+ // asm ops like test, or pseudo ops like pop().
+ void setnz32(Address address, Imm32 mask, RegisterID dest)
+ {
+ testImm32(address, mask);
+ m_assembler.setnz_r(dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+
+ void setz32(Address address, Imm32 mask, RegisterID dest)
+ {
+ testImm32(address, mask);
+ m_assembler.setz_r(dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssembler_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef X86Assembler_h
+#define X86Assembler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64))
+
+#include "AssemblerBuffer.h"
+#include <stdint.h>
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
+#if PLATFORM(X86_64)
+inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; }
+inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; }
+#endif
+
+namespace X86 {
+ typedef enum {
+ eax,
+ ecx,
+ edx,
+ ebx,
+ esp,
+ ebp,
+ esi,
+ edi,
+
+#if PLATFORM(X86_64)
+ r8,
+ r9,
+ r10,
+ r11,
+ r12,
+ r13,
+ r14,
+ r15,
+#endif
+ } RegisterID;
+
+ typedef enum {
+ xmm0,
+ xmm1,
+ xmm2,
+ xmm3,
+ xmm4,
+ xmm5,
+ xmm6,
+ xmm7,
+ } XMMRegisterID;
+}
+
+class X86Assembler {
+public:
+ typedef X86::RegisterID RegisterID;
+ typedef X86::XMMRegisterID XMMRegisterID;
+
+ typedef enum {
+ OP_ADD_EvGv = 0x01,
+ OP_ADD_GvEv = 0x03,
+ OP_OR_EvGv = 0x09,
+ OP_OR_GvEv = 0x0B,
+ OP_2BYTE_ESCAPE = 0x0F,
+ OP_AND_EvGv = 0x21,
+ OP_SUB_EvGv = 0x29,
+ OP_SUB_GvEv = 0x2B,
+ PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
+ OP_XOR_EvGv = 0x31,
+ OP_CMP_EvGv = 0x39,
+ OP_CMP_GvEv = 0x3B,
+#if PLATFORM(X86_64)
+ PRE_REX = 0x40,
+#endif
+ OP_PUSH_EAX = 0x50,
+ OP_POP_EAX = 0x58,
+#if PLATFORM(X86_64)
+ OP_MOVSXD_GvEv = 0x63,
+#endif
+ PRE_OPERAND_SIZE = 0x66,
+ PRE_SSE_66 = 0x66,
+ OP_PUSH_Iz = 0x68,
+ OP_IMUL_GvEvIz = 0x69,
+ OP_GROUP1_EvIz = 0x81,
+ OP_GROUP1_EvIb = 0x83,
+ OP_TEST_EvGv = 0x85,
+ OP_XCHG_EvGv = 0x87,
+ OP_MOV_EvGv = 0x89,
+ OP_MOV_GvEv = 0x8B,
+ OP_LEA = 0x8D,
+ OP_GROUP1A_Ev = 0x8F,
+ OP_CDQ = 0x99,
+ OP_MOV_EAXOv = 0xA1,
+ OP_MOV_OvEAX = 0xA3,
+ OP_MOV_EAXIv = 0xB8,
+ OP_GROUP2_EvIb = 0xC1,
+ OP_RET = 0xC3,
+ OP_GROUP11_EvIz = 0xC7,
+ OP_INT3 = 0xCC,
+ OP_GROUP2_Ev1 = 0xD1,
+ OP_GROUP2_EvCL = 0xD3,
+ OP_CALL_rel32 = 0xE8,
+ OP_JMP_rel32 = 0xE9,
+ PRE_SSE_F2 = 0xF2,
+ OP_HLT = 0xF4,
+ OP_GROUP3_EbIb = 0xF6,
+ OP_GROUP3_Ev = 0xF7,
+ OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
+ OP_GROUP5_Ev = 0xFF,
+ } OneByteOpcodeID;
+
+ typedef enum {
+ OP2_MOVSD_VsdWsd = 0x10,
+ OP2_MOVSD_WsdVsd = 0x11,
+ OP2_CVTSI2SD_VsdEd = 0x2A,
+ OP2_CVTTSD2SI_GdWsd = 0x2C,
+ OP2_UCOMISD_VsdWsd = 0x2E,
+ OP2_ADDSD_VsdWsd = 0x58,
+ OP2_MULSD_VsdWsd = 0x59,
+ OP2_SUBSD_VsdWsd = 0x5C,
+ OP2_MOVD_VdEd = 0x6E,
+ OP2_MOVD_EdVd = 0x7E,
+ OP2_JO_rel32 = 0x80,
+ OP2_JB_rel32 = 0x82,
+ OP2_JAE_rel32 = 0x83,
+ OP2_JE_rel32 = 0x84,
+ OP2_JNE_rel32 = 0x85,
+ OP2_JBE_rel32 = 0x86,
+ OP2_JA_rel32 = 0x87,
+ OP2_JS_rel32 = 0x88,
+ OP2_JP_rel32 = 0x8A,
+ OP2_JL_rel32 = 0x8C,
+ OP2_JGE_rel32 = 0x8D,
+ OP2_JLE_rel32 = 0x8E,
+ OP2_JG_rel32 = 0x8F,
+ OP_SETE = 0x94,
+ OP_SETNE = 0x95,
+ OP2_IMUL_GvEv = 0xAF,
+ OP2_MOVZX_GvEb = 0xB6,
+ OP2_MOVZX_GvEw = 0xB7,
+ OP2_PEXTRW_GdUdIb = 0xC5,
+ } TwoByteOpcodeID;
+
+ typedef enum {
+ GROUP1_OP_ADD = 0,
+ GROUP1_OP_OR = 1,
+ GROUP1_OP_AND = 4,
+ GROUP1_OP_SUB = 5,
+ GROUP1_OP_XOR = 6,
+ GROUP1_OP_CMP = 7,
+
+ GROUP1A_OP_POP = 0,
+
+ GROUP2_OP_SHL = 4,
+ GROUP2_OP_SAR = 7,
+
+ GROUP3_OP_TEST = 0,
+ GROUP3_OP_NOT = 2,
+ GROUP3_OP_IDIV = 7,
+
+ GROUP5_OP_CALLN = 2,
+ GROUP5_OP_JMPN = 4,
+ GROUP5_OP_PUSH = 6,
+
+ GROUP11_MOV = 0,
+ } GroupOpcodeID;
+
+ // Opaque label types
+
+private:
+ class X86InstructionFormatter;
+public:
+
+ class JmpSrc {
+ friend class X86Assembler;
+ friend class X86InstructionFormatter;
+ public:
+ JmpSrc()
+ : m_offset(-1)
+ {
+ }
+
+ private:
+ JmpSrc(int offset)
+ : m_offset(offset)
+ {
+ }
+
+ int m_offset;
+ };
+
+ class JmpDst {
+ friend class X86Assembler;
+ friend class X86InstructionFormatter;
+ public:
+ JmpDst()
+ : m_offset(-1)
+ {
+ }
+
+ private:
+ JmpDst(int offset)
+ : m_offset(offset)
+ {
+ }
+
+ int m_offset;
+ };
+
+ X86Assembler()
+ {
+ }
+
+ size_t size() const { return m_formatter.size(); }
+
+ // Stack operations:
+
+ void push_r(RegisterID reg)
+ {
+ m_formatter.oneByteOp(OP_PUSH_EAX, reg);
+ }
+
+ void pop_r(RegisterID reg)
+ {
+ m_formatter.oneByteOp(OP_POP_EAX, reg);
+ }
+
+ void push_i32(int imm)
+ {
+ m_formatter.oneByteOp(OP_PUSH_Iz);
+ m_formatter.immediate32(imm);
+ }
+
+ void push_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset);
+ }
+
+ void pop_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset);
+ }
+
+ // Arithmetic operations:
+
+ void addl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
+ }
+
+ void addl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
+ }
+
+ void addl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void addl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+#if PLATFORM(X86_64)
+ void addq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
+ }
+
+ void addq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+#else
+ void addl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void andl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
+ }
+
+ void andl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+#if PLATFORM(X86_64)
+ void andq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
+ }
+
+ void andq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void notl_r(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
+ }
+
+ void orl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
+ }
+
+ void orl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
+ }
+
+ void orl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+#if PLATFORM(X86_64)
+ void orq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
+ }
+
+ void orq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void subl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_SUB_EvGv, src, dst);
+ }
+
+ void subl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
+ }
+
+ void subl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void subl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+#if PLATFORM(X86_64)
+ void subq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
+ }
+
+ void subq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+#else
+ void subl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void xorl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
+ }
+
+ void xorl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+#if PLATFORM(X86_64)
+ void xorq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
+ }
+
+ void xorq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void sarl_i8r(int imm, RegisterID dst)
+ {
+ if (imm == 1)
+ m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+ else {
+ m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+
+ void sarl_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
+ }
+
+ void shll_i8r(int imm, RegisterID dst)
+ {
+ if (imm == 1)
+ m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
+ else {
+ m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+
+ void shll_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
+ }
+
+#if PLATFORM(X86_64)
+ void sarq_CLr(RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
+ }
+
+ void sarq_i8r(int imm, RegisterID dst)
+ {
+ if (imm == 1)
+ m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+ else {
+ m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+ m_formatter.immediate8(imm);
+ }
+ }
+#endif
+
+ void imull_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
+ }
+
+ void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
+ m_formatter.immediate32(value);
+ }
+
+ void idivl_r(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);
+ }
+
+ // Comparisons:
+
+ void cmpl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
+ }
+
+ void cmpl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
+ }
+
+ void cmpl_mr(int offset, RegisterID base, RegisterID src)
+ {
+ m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
+ }
+
+ void cmpl_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void cmpl_ir_force32(int imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+ m_formatter.immediate32(imm);
+ }
+
+ void cmpl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void cmpl_im_force32(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
+ m_formatter.immediate32(imm);
+ }
+
+#if PLATFORM(X86_64)
+ void cmpq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
+ }
+
+ void cmpq_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset);
+ }
+
+ void cmpq_ir(int imm, RegisterID dst)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void cmpq_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+#else
+ void cmpl_rm(RegisterID reg, void* addr)
+ {
+ m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
+ }
+
+ void cmpl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
+ void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
+ }
+
+ void testl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
+ }
+
+ void testl_i32r(int imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
+ m_formatter.immediate32(imm);
+ }
+
+ void testl_i32m(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
+ m_formatter.immediate32(imm);
+ }
+
+ void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
+ m_formatter.immediate32(imm);
+ }
+
+#if PLATFORM(X86_64)
+ void testq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
+ }
+
+ void testq_i32r(int imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
+ m_formatter.immediate32(imm);
+ }
+
+ void testq_i32m(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
+ m_formatter.immediate32(imm);
+ }
+
+ void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
+ m_formatter.immediate32(imm);
+ }
+#endif
+
+ void testb_i8r(int imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
+ m_formatter.immediate8(imm);
+ }
+
+ void sete_r(RegisterID dst)
+ {
+ m_formatter.twoByteOp8(OP_SETE, (GroupOpcodeID)0, dst);
+ }
+
+ void setz_r(RegisterID dst)
+ {
+ sete_r(dst);
+ }
+
+ void setne_r(RegisterID dst)
+ {
+ m_formatter.twoByteOp8(OP_SETNE, (GroupOpcodeID)0, dst);
+ }
+
+ void setnz_r(RegisterID dst)
+ {
+ setne_r(dst);
+ }
+
+ // Various move ops:
+
+ void cdq()
+ {
+ m_formatter.oneByteOp(OP_CDQ);
+ }
+
+ void xchgl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
+ }
+
+#if PLATFORM(X86_64)
+ void xchgq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
+ }
+#endif
+
+ void movl_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_MOV_EvGv, src, dst);
+ }
+
+ void movl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
+ }
+
+ void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
+ }
+
+ void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
+ }
+
+ void movl_mEAX(void* addr)
+ {
+ m_formatter.oneByteOp(OP_MOV_EAXOv);
+#if PLATFORM(X86_64)
+ m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
+#else
+ m_formatter.immediate32(reinterpret_cast<int>(addr));
+#endif
+ }
+
+ void movl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
+ }
+
+ void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
+ }
+
+ void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
+ }
+
+ void movl_i32r(int imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_MOV_EAXIv, dst);
+ m_formatter.immediate32(imm);
+ }
+
+ void movl_i32m(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
+ m_formatter.immediate32(imm);
+ }
+
+ void movl_EAXm(void* addr)
+ {
+ m_formatter.oneByteOp(OP_MOV_OvEAX);
+#if PLATFORM(X86_64)
+ m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
+#else
+ m_formatter.immediate32(reinterpret_cast<int>(addr));
+#endif
+ }
+
+#if PLATFORM(X86_64)
+ void movq_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
+ }
+
+ void movq_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset);
+ }
+
+ void movq_rm_disp32(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset);
+ }
+
+ void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
+ }
+
+ void movq_mEAX(void* addr)
+ {
+ m_formatter.oneByteOp64(OP_MOV_EAXOv);
+ m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
+ }
+
+ void movq_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
+ }
+
+ void movq_mr_disp32(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset);
+ }
+
+ void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
+ }
+
+ void movq_i64r(int64_t imm, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
+ m_formatter.immediate64(imm);
+ }
+
+ void movsxd_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
+ }
+
+
+#else
+ void movl_mr(void* addr, RegisterID dst)
+ {
+ if (dst == X86::eax)
+ movl_mEAX(addr);
+ else
+ m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
+ }
+
+ void movl_i32m(int imm, void* addr)
+ {
+ m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
+ m_formatter.immediate32(imm);
+ }
+#endif
+
+ void movzwl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
+ }
+
+ void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+ {
+ m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
+ }
+
+ void movzbl_rr(RegisterID src, RegisterID dst)
+ {
+ // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
+ // is in the range ESP-EDI, and the src would not have required a REX). Unneeded
+ // REX prefixes are defined to be silently ignored by the processor.
+ m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src);
+ }
+
+ void leal_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_LEA, dst, base, offset);
+ }
+
+ // Flow control:
+
+ JmpSrc call()
+ {
+ m_formatter.oneByteOp(OP_CALL_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc call(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
+ return JmpSrc(m_formatter.size());
+ }
+
+ JmpSrc jmp()
+ {
+ m_formatter.oneByteOp(OP_JMP_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ void jmp_r(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
+ }
+
+ void jmp_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
+ }
+
+ JmpSrc jne()
+ {
+ m_formatter.twoByteOp(OP2_JNE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jnz()
+ {
+ return jne();
+ }
+
+ JmpSrc je()
+ {
+ m_formatter.twoByteOp(OP2_JE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jl()
+ {
+ m_formatter.twoByteOp(OP2_JL_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jb()
+ {
+ m_formatter.twoByteOp(OP2_JB_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jle()
+ {
+ m_formatter.twoByteOp(OP2_JLE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jbe()
+ {
+ m_formatter.twoByteOp(OP2_JBE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jge()
+ {
+ m_formatter.twoByteOp(OP2_JGE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jg()
+ {
+ m_formatter.twoByteOp(OP2_JG_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc ja()
+ {
+ m_formatter.twoByteOp(OP2_JA_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jae()
+ {
+ m_formatter.twoByteOp(OP2_JAE_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jo()
+ {
+ m_formatter.twoByteOp(OP2_JO_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jp()
+ {
+ m_formatter.twoByteOp(OP2_JP_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc js()
+ {
+ m_formatter.twoByteOp(OP2_JS_rel32);
+ return m_formatter.immediateRel32();
+ }
+
+ // SSE operations:
+
+ void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+ }
+
+ void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
+ }
+
+ void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
+ }
+
+ void movd_rr(XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
+ }
+
+#if PLATFORM(X86_64)
+ void movq_rr(XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp64(OP2_MOVD_EdVd, (RegisterID)src, dst);
+ }
+
+ void movq_rr(RegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp64(OP2_MOVD_VdEd, (RegisterID)dst, src);
+ }
+#endif
+
+ void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
+ }
+
+ void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+ }
+
+ void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src);
+ m_formatter.immediate8(whichWord);
+ }
+
+ void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+ }
+
+ void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+ }
+
+ // Misc instructions:
+
+ void int3()
+ {
+ m_formatter.oneByteOp(OP_INT3);
+ }
+
+ void ret()
+ {
+ m_formatter.oneByteOp(OP_RET);
+ }
+
+ void predictNotTaken()
+ {
+ m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN);
+ }
+
+ // Assembler admin methods:
+
+ JmpDst label()
+ {
+ return JmpDst(m_formatter.size());
+ }
+
+ JmpDst align(int alignment)
+ {
+ while (!m_formatter.isAligned(alignment))
+ m_formatter.oneByteOp(OP_HLT);
+
+ return label();
+ }
+
+ // Linking & patching:
+
+ void link(JmpSrc from, JmpDst to)
+ {
+ ASSERT(to.m_offset != -1);
+ ASSERT(from.m_offset != -1);
+
+ reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_formatter.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
+ }
+
+ static void patchAddress(void* code, JmpDst position, void* value)
+ {
+ ASSERT(position.m_offset != -1);
+
+ reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value;
+ }
+
+ static void link(void* code, JmpSrc from, void* to)
+ {
+ ASSERT(from.m_offset != -1);
+
+ reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset);
+ }
+
+ static void* getRelocatedAddress(void* code, JmpSrc jump)
+ {
+ return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
+ }
+
+ static void* getRelocatedAddress(void* code, JmpDst destination)
+ {
+ ASSERT(destination.m_offset != -1);
+
+ return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
+ }
+
+ static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
+ {
+ return dst.m_offset - src.m_offset;
+ }
+
+ static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
+ {
+ return dst.m_offset - src.m_offset;
+ }
+
+ static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
+ {
+ return dst.m_offset - src.m_offset;
+ }
+
+ static void patchImmediate(intptr_t where, int32_t value)
+ {
+ reinterpret_cast<int32_t*>(where)[-1] = value;
+ }
+
+ static void patchPointer(intptr_t where, intptr_t value)
+ {
+ reinterpret_cast<intptr_t*>(where)[-1] = value;
+ }
+
+ static void patchBranchOffset(intptr_t where, void* destination)
+ {
+ intptr_t offset = reinterpret_cast<intptr_t>(destination) - where;
+ ASSERT(offset == static_cast<int32_t>(offset));
+ reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset);
+ }
+
+ void* executableCopy(ExecutablePool* allocator)
+ {
+ void* copy = m_formatter.executableCopy(allocator);
+ ASSERT(copy);
+ return copy;
+ }
+
+private:
+
+ class X86InstructionFormatter {
+
+ static const int maxInstructionSize = 16;
+
+ public:
+
+ // Legacy prefix bytes:
+ //
+ // These are emmitted prior to the instruction.
+
+ void prefix(OneByteOpcodeID pre)
+ {
+ m_buffer.putByte(pre);
+ }
+
+ // Word-sized operands / no operand instruction formatters.
+ //
+ // In addition to the opcode, the following operand permutations are supported:
+ // * None - instruction takes no operands.
+ // * One register - the low three bits of the RegisterID are added into the opcode.
+ // * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place).
+ // * Three argument ModRM - a register, and a register and an offset describing a memory operand.
+ // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
+ //
+ // For 32-bit x86 targets, the address operand may also be provided as a void*.
+ // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
+ //
+ // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
+
+ void oneByteOp(OneByteOpcodeID opcode)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ m_buffer.putByteUnchecked(opcode);
+ }
+
+ void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(0, 0, reg);
+ m_buffer.putByteUnchecked(opcode + (reg & 7));
+ }
+
+ void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, 0, rm);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(reg, rm);
+ }
+
+ void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, 0, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, offset);
+ }
+
+ void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, 0, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM_disp32(reg, base, offset);
+ }
+
+ void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, index, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, index, scale, offset);
+ }
+
+#if !PLATFORM(X86_64)
+ void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, address);
+ }
+#endif
+
+ void twoByteOp(TwoByteOpcodeID opcode)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ }
+
+ void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, 0, rm);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(reg, rm);
+ }
+
+ void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, 0, base);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, offset);
+ }
+
+ void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIfNeeded(reg, index, base);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, index, scale, offset);
+ }
+
+#if PLATFORM(X86_64)
+ // Quad-word-sized operands:
+ //
+ // Used to format 64-bit operantions, planting a REX.w prefix.
+ // When planting d64 or f64 instructions, not requiring a REX.w prefix,
+ // the normal (non-'64'-postfixed) formatters should be used.
+
+ void oneByteOp64(OneByteOpcodeID opcode)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(0, 0, 0);
+ m_buffer.putByteUnchecked(opcode);
+ }
+
+ void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(0, 0, reg);
+ m_buffer.putByteUnchecked(opcode + (reg & 7));
+ }
+
+ void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(reg, 0, rm);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(reg, rm);
+ }
+
+ void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(reg, 0, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, offset);
+ }
+
+ void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(reg, 0, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM_disp32(reg, base, offset);
+ }
+
+ void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(reg, index, base);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, base, index, scale, offset);
+ }
+
+ void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexW(reg, 0, rm);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(reg, rm);
+ }
+#endif
+
+ // Byte-operands:
+ //
+ // These methods format byte operations. Byte operations differ from the normal
+ // formatters in the circumstances under which they will decide to emit REX prefixes.
+ // These should be used where any register operand signifies a byte register.
+ //
+ // The disctinction is due to the handling of register numbers in the range 4..7 on
+ // x86-64. These register numbers may either represent the second byte of the first
+ // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
+ //
+ // Since ah..bh cannot be used in all permutations of operands (specifically cannot
+ // be accessed where a REX prefix is present), these are likely best treated as
+ // deprecated. In order to ensure the correct registers spl..dil are selected a
+ // REX prefix will be emitted for any byte register operand in the range 4..15.
+ //
+ // These formatters may be used in instructions where a mix of operand sizes, in which
+ // case an unnecessary REX will be emitted, for example:
+ // movzbl %al, %edi
+ // In this case a REX will be planted since edi is 7 (and were this a byte operand
+ // a REX would be required to specify dil instead of bh). Unneeded REX prefixes will
+ // be silently ignored by the processor.
+ //
+ // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
+ // is provided to check byte register operands.
+
+ void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(groupOp, rm);
+ }
+
+ void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(reg, rm);
+ }
+
+ void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ registerModRM(groupOp, rm);
+ }
+
+ // Immediates:
+ //
+ // An immedaite should be appended where appropriate after an op has been emitted.
+ // The writes are unchecked since the opcode formatters above will have ensured space.
+
+ void immediate8(int imm)
+ {
+ m_buffer.putByteUnchecked(imm);
+ }
+
+ void immediate32(int imm)
+ {
+ m_buffer.putIntUnchecked(imm);
+ }
+
+ void immediate64(int64_t imm)
+ {
+ m_buffer.putInt64Unchecked(imm);
+ }
+
+ JmpSrc immediateRel32()
+ {
+ m_buffer.putIntUnchecked(0);
+ return JmpSrc(m_buffer.size());
+ }
+
+ // Administrative methods:
+
+ size_t size() const { return m_buffer.size(); }
+ bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
+ void* data() const { return m_buffer.data(); }
+ void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
+
+ private:
+
+ // Internals; ModRm and REX formatters.
+
+ static const RegisterID noBase = X86::ebp;
+ static const RegisterID hasSib = X86::esp;
+ static const RegisterID noIndex = X86::esp;
+#if PLATFORM(X86_64)
+ static const RegisterID noBase2 = X86::r13;
+ static const RegisterID hasSib2 = X86::r12;
+
+ // Registers r8 & above require a REX prefixe.
+ inline bool regRequiresRex(int reg)
+ {
+ return (reg >= X86::r8);
+ }
+
+ // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
+ inline bool byteRegRequiresRex(int reg)
+ {
+ return (reg >= X86::esp);
+ }
+
+ // Format a REX prefix byte.
+ inline void emitRex(bool w, int r, int x, int b)
+ {
+ m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
+ }
+
+ // Used to plant a REX byte with REX.w set (for 64-bit operations).
+ inline void emitRexW(int r, int x, int b)
+ {
+ emitRex(true, r, x, b);
+ }
+
+ // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
+ // regRequiresRex() to check other registers (i.e. address base & index).
+ inline void emitRexIf(bool condition, int r, int x, int b)
+ {
+ if (condition) emitRex(false, r, x, b);
+ }
+
+ // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
+ inline void emitRexIfNeeded(int r, int x, int b)
+ {
+ emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);
+ }
+#else
+ // No REX prefix bytes on 32-bit x86.
+ inline bool regRequiresRex(int) { return false; }
+ inline bool byteRegRequiresRex(int) { return false; }
+ inline void emitRexIf(bool, int, int, int) {}
+ inline void emitRexIfNeeded(int, int, int) {}
+#endif
+
+ enum ModRmMode {
+ ModRmMemoryNoDisp,
+ ModRmMemoryDisp8,
+ ModRmMemoryDisp32,
+ ModRmRegister,
+ };
+
+ void putModRm(ModRmMode mode, int reg, RegisterID rm)
+ {
+ m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
+ }
+
+ void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
+ {
+ ASSERT(mode != ModRmRegister);
+
+ // Encode sacle of (1,2,4,8) -> (0,1,2,3)
+ int shift = 0;
+ while (scale >>= 1)
+ shift++;
+
+ putModRm(mode, reg, hasSib);
+ m_buffer.putByteUnchecked((shift << 6) | ((index & 7) << 3) | (base & 7));
+ }
+
+ void registerModRM(int reg, RegisterID rm)
+ {
+ putModRm(ModRmRegister, reg, rm);
+ }
+
+ void memoryModRM(int reg, RegisterID base, int offset)
+ {
+ // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
+#if PLATFORM(X86_64)
+ if ((base == hasSib) || (base == hasSib2)) {
+#else
+ if (base == hasSib) {
+#endif
+ if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
+ putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);
+ else if (CAN_SIGN_EXTEND_8_32(offset)) {
+ putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
+ m_buffer.putByteUnchecked(offset);
+ } else {
+ putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
+ m_buffer.putIntUnchecked(offset);
+ }
+ } else {
+#if PLATFORM(X86_64)
+ if (!offset && (base != noBase) && (base != noBase2))
+#else
+ if (!offset && (base != noBase))
+#endif
+ putModRm(ModRmMemoryNoDisp, reg, base);
+ else if (CAN_SIGN_EXTEND_8_32(offset)) {
+ putModRm(ModRmMemoryDisp8, reg, base);
+ m_buffer.putByteUnchecked(offset);
+ } else {
+ putModRm(ModRmMemoryDisp32, reg, base);
+ m_buffer.putIntUnchecked(offset);
+ }
+ }
+ }
+
+ void memoryModRM_disp32(int reg, RegisterID base, int offset)
+ {
+ // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
+#if PLATFORM(X86_64)
+ if ((base == hasSib) || (base == hasSib2)) {
+#else
+ if (base == hasSib) {
+#endif
+ putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
+ m_buffer.putIntUnchecked(offset);
+ } else {
+ putModRm(ModRmMemoryDisp32, reg, base);
+ m_buffer.putIntUnchecked(offset);
+ }
+ }
+
+ void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
+ {
+ ASSERT(index != noIndex);
+
+#if PLATFORM(X86_64)
+ if (!offset && (base != noBase) && (base != noBase2))
+#else
+ if (!offset && (base != noBase))
+#endif
+ putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);
+ else if (CAN_SIGN_EXTEND_8_32(offset)) {
+ putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);
+ m_buffer.putByteUnchecked(offset);
+ } else {
+ putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);
+ m_buffer.putIntUnchecked(offset);
+ }
+ }
+
+#if !PLATFORM(X86_64)
+ void memoryModRM(int reg, void* address)
+ {
+ // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
+ putModRm(ModRmMemoryNoDisp, reg, noBase);
+ m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
+ }
+#endif
+
+ AssemblerBuffer m_buffer;
+ } m_formatter;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
+
+#endif // X86Assembler_h
+++ /dev/null
-/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "NP_jsobject.h"
-
-#include "JSGlobalObject.h"
-#include "PropertyNameArray.h"
-#include "SourceCode.h"
-#include "c_utility.h"
-#include "interpreter.h"
-#include "npruntime_impl.h"
-#include "npruntime_priv.h"
-#include "object.h"
-#include "runtime_root.h"
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, List& aList)
-{
- for (unsigned i = 0; i < argCount; i++)
- aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
-}
-
-static NPObject* jsAllocate(NPP, NPClass*)
-{
- return (NPObject*)malloc(sizeof(JavaScriptObject));
-}
-
-static void jsDeallocate(NPObject* npObj)
-{
- JavaScriptObject* obj = (JavaScriptObject*)npObj;
-
- if (obj->rootObject && obj->rootObject->isValid())
- obj->rootObject->gcUnprotect(obj->imp);
-
- if (obj->rootObject)
- obj->rootObject->deref();
-
- free(obj);
-}
-
-static NPClass javascriptClass = { 1, jsAllocate, jsDeallocate, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-NPClass* NPScriptObjectClass = &javascriptClass;
-static NPClass* NPNoScriptObjectClass = &noScriptClass;
-
-NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
-{
- JavaScriptObject* obj = (JavaScriptObject*)_NPN_CreateObject(npp, NPScriptObjectClass);
-
- obj->rootObject = rootObject.releaseRef();
-
- if (obj->rootObject)
- obj->rootObject->gcProtect(imp);
- obj->imp = imp;
-
- return (NPObject*)obj;
-}
-
-NPObject *_NPN_CreateNoScriptObject(void)
-{
- return _NPN_CreateObject(0, NPNoScriptObjectClass);
-}
-
-bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- VOID_TO_NPVARIANT(*result);
-
- // Lookup the function object.
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
-
- // Call the function object.
- JSObject *funcImp = static_cast<JSObject*>(obj->imp);
- if (!funcImp->implementsCall())
- return false;
-
- List argList;
- getListFromVariantArgs(exec, args, argCount, rootObject, argList);
- rootObject->globalObject()->startTimeoutCheck();
- JSValue *resultV = funcImp->call (exec, funcImp, argList);
- rootObject->globalObject()->stopTimeoutCheck();
-
- // Convert and return the result of the function call.
- convertValueToNPVariant(exec, resultV, result);
- return true;
- }
-
- if (o->_class->invokeDefault)
- return o->_class->invokeDefault(o, args, argCount, result);
- VOID_TO_NPVARIANT(*result);
- return true;
-}
-
-bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- PrivateIdentifier* i = (PrivateIdentifier*)methodName;
- if (!i->isString)
- return false;
-
- // Special case the "eval" method.
- if (methodName == _NPN_GetStringIdentifier("eval")) {
- if (argCount != 1)
- return false;
- if (args[0].type != NPVariantType_String)
- return false;
- return _NPN_Evaluate(npp, o, (NPString *)&args[0].value.stringValue, result);
- }
-
- // Lookup the function object.
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
- if (func->isNull()) {
- NULL_TO_NPVARIANT(*result);
- return false;
- }
- if (func->isUndefined()) {
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- // Call the function object.
- JSObject *funcImp = static_cast<JSObject*>(func);
- JSObject *thisObj = const_cast<JSObject*>(obj->imp);
- List argList;
- getListFromVariantArgs(exec, args, argCount, rootObject, argList);
- rootObject->globalObject()->startTimeoutCheck();
- JSValue *resultV = funcImp->call (exec, thisObj, argList);
- rootObject->globalObject()->stopTimeoutCheck();
-
- // Convert and return the result of the function call.
- convertValueToNPVariant(exec, resultV, result);
- return true;
- }
-
- if (o->_class->invoke)
- return o->_class->invoke(o, methodName, args, argCount, result);
-
- VOID_TO_NPVARIANT(*result);
- return true;
-}
-
-bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
-
- JSLock lock;
- NPUTF16* scriptString;
- unsigned int UTF16Length;
- convertNPStringToUTF16(s, &scriptString, &UTF16Length); // requires free() of returned memory
- rootObject->globalObject()->startTimeoutCheck();
-
- SourceCode source = makeSource(UString(reinterpret_cast<const UChar*>(scriptString), UTF16Length), UString());
- Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), source);
- rootObject->globalObject()->stopTimeoutCheck();
- ComplType type = completion.complType();
-
- JSValue* result;
- if (type == Normal) {
- result = completion.value();
- if (!result)
- result = jsUndefined();
- } else
- result = jsUndefined();
-
- free(scriptString);
-
- convertValueToNPVariant(exec, result, variant);
-
- return true;
- }
-
- VOID_TO_NPVARIANT(*variant);
- return false;
-}
-
-bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
-
- JSLock lock;
- JSValue *result;
- if (i->isString)
- result = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
- else
- result = obj->imp->get(exec, i->value.number);
-
- convertValueToNPVariant(exec, result, variant);
- return true;
- }
-
- if (o->_class->hasProperty && o->_class->getProperty) {
- if (o->_class->hasProperty(o, propertyName))
- return o->_class->getProperty(o, propertyName, variant);
- return false;
- }
-
- VOID_TO_NPVARIANT(*variant);
- return false;
-}
-
-bool _NPN_SetProperty(NPP, NPObject* o, NPIdentifier propertyName, const NPVariant* variant)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
- if (i->isString)
- obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject));
- else
- obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
- return true;
- }
-
- if (o->_class->setProperty)
- return o->_class->setProperty(o, propertyName, variant);
-
- return false;
-}
-
-bool _NPN_RemoveProperty(NPP, NPObject* o, NPIdentifier propertyName)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
- if (i->isString) {
- if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string)))
- return false;
- } else {
- if (!obj->imp->hasProperty(exec, i->value.number))
- return false;
- }
-
- JSLock lock;
- if (i->isString)
- obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
- else
- obj->imp->deleteProperty(exec, i->value.number);
-
- return true;
- }
- return false;
-}
-
-bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
- JSLock lock;
- if (i->isString)
- return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
- return obj->imp->hasProperty(exec, i->value.number);
- }
-
- if (o->_class->hasProperty)
- return o->_class->hasProperty(o, propertyName);
-
- return false;
-}
-
-bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- PrivateIdentifier* i = (PrivateIdentifier*)methodName;
- if (!i->isString)
- return false;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
- return !func->isUndefined();
- }
-
- if (o->_class->hasMethod)
- return o->_class->hasMethod(o, methodName);
-
- return false;
-}
-
-void _NPN_SetException(NPObject* o, const NPUTF8* message)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- throwError(exec, GeneralError, message);
- }
-}
-
-bool _NPN_Enumerate(NPP, NPObject *o, NPIdentifier **identifier, uint32_t *count)
-{
- if (o->_class == NPScriptObjectClass) {
- JavaScriptObject* obj = (JavaScriptObject*)o;
-
- RootObject* rootObject = obj->rootObject;
- if (!rootObject || !rootObject->isValid())
- return false;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- PropertyNameArray propertyNames;
-
- obj->imp->getPropertyNames(exec, propertyNames);
- unsigned size = static_cast<unsigned>(propertyNames.size());
- // FIXME: This should really call NPN_MemAlloc but that's in WebKit
- NPIdentifier *identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
-
- for (unsigned i = 0; i < size; i++)
- identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());
-
- *identifier = identifiers;
- *count = size;
-
- return true;
- }
-
- if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
- return o->_class->enumerate(o, identifier, count);
-
- return false;
-}
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef NP_JSOBJECT_H
-#define NP_JSOBJECT_H
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-#include <wtf/Forward.h>
-
-namespace KJS {
- class JSObject;
- namespace Bindings {
- class RootObject;
- }
-}
-
-extern NPClass* NPScriptObjectClass;
-
-struct JavaScriptObject
-{
- NPObject object;
- KJS::JSObject* imp;
- KJS::Bindings::RootObject* rootObject;
-};
-
-NPObject* _NPN_CreateScriptObject(NPP npp, KJS::JSObject*, PassRefPtr<KJS::Bindings::RootObject> rootObject);
-NPObject* _NPN_CreateNoScriptObject(void);
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "c_class.h"
-
-#include "c_instance.h"
-#include "c_runtime.h"
-#include "identifier.h"
-#include "npruntime_impl.h"
-
-namespace KJS { namespace Bindings {
-
-CClass::CClass(NPClass* aClass)
-{
- _isa = aClass;
-}
-
-CClass::~CClass()
-{
- JSLock lock;
-
- deleteAllValues(_methods);
- _methods.clear();
-
- deleteAllValues(_fields);
- _fields.clear();
-}
-
-typedef HashMap<NPClass*, CClass*> ClassesByIsAMap;
-static ClassesByIsAMap* classesByIsA = 0;
-
-CClass* CClass::classForIsA(NPClass* isa)
-{
- if (!classesByIsA)
- classesByIsA = new ClassesByIsAMap;
-
- CClass* aClass = classesByIsA->get(isa);
- if (!aClass) {
- aClass = new CClass(isa);
- classesByIsA->set(isa, aClass);
- }
-
- return aClass;
-}
-
-const char* CClass::name() const
-{
- return "";
-}
-
-MethodList CClass::methodsNamed(const Identifier& identifier, Instance* instance) const
-{
- MethodList methodList;
-
- Method* method = _methods.get(identifier.ustring().rep());
- if (method) {
- methodList.append(method);
- return methodList;
- }
-
- NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
- const CInstance* inst = static_cast<const CInstance*>(instance);
- NPObject* obj = inst->getObject();
- if (_isa->hasMethod && _isa->hasMethod(obj, ident)){
- Method* aMethod = new CMethod(ident); // deleted in the CClass destructor
- {
- JSLock lock;
- _methods.set(identifier.ustring().rep(), aMethod);
- }
- methodList.append(aMethod);
- }
-
- return methodList;
-}
-
-Field* CClass::fieldNamed(const Identifier& identifier, Instance* instance) const
-{
- Field* aField = _fields.get(identifier.ustring().rep());
- if (aField)
- return aField;
-
- NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
- const CInstance* inst = static_cast<const CInstance*>(instance);
- NPObject* obj = inst->getObject();
- if (_isa->hasProperty && _isa->hasProperty(obj, ident)){
- aField = new CField(ident); // deleted in the CClass destructor
- {
- JSLock lock;
- _fields.set(identifier.ustring().rep(), aField);
- }
- }
- return aField;
-}
-
-} } // namespace KJS::Bindings
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BINDINGS_C_CLASS_H_
-#define BINDINGS_C_CLASS_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-#include "runtime.h"
-#include <wtf/HashMap.h>
-
-namespace KJS {
-namespace Bindings {
-
-class CClass : public Class {
-protected:
- CClass(NPClass*); // Use classForIsA to create a CClass.
-
-public:
- static CClass* classForIsA(NPClass*);
- virtual ~CClass();
-
- virtual const char* name() const;
- virtual MethodList methodsNamed(const Identifier&, Instance*) const;
- virtual Field* fieldNamed(const Identifier&, Instance*) const;
-
-private:
- NPClass* _isa;
- mutable MethodMap _methods;
- mutable FieldMap _fields;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "c_instance.h"
-
-#include "c_class.h"
-#include "c_runtime.h"
-#include "c_utility.h"
-#include "list.h"
-#include "npruntime_impl.h"
-#include "PropertyNameArray.h"
-#include "runtime_root.h"
-#include <wtf/Assertions.h>
-#include <wtf/StringExtras.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-namespace Bindings {
-
-CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
- : Instance(rootObject)
-{
- _object = _NPN_RetainObject(o);
- _class = 0;
-}
-
-CInstance::~CInstance()
-{
- _NPN_ReleaseObject(_object);
-}
-
-Class *CInstance::getClass() const
-{
- if (!_class)
- _class = CClass::classForIsA(_object->_class);
- return _class;
-}
-
-void CInstance::begin()
-{
- // Do nothing.
-}
-
-void CInstance::end()
-{
- // Do nothing.
-}
-
-bool CInstance::implementsCall() const
-{
- return (_object->_class->invokeDefault != 0);
-}
-
-JSValue* CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const List& args)
-{
- // Overloading methods are not allowed by NPObjects. Should only be one
- // name match for a particular method.
- ASSERT(methodList.size() == 1);
-
- CMethod* method = static_cast<CMethod*>(methodList[0]);
-
- NPIdentifier ident = _NPN_GetStringIdentifier(method->name());
- if (!_object->_class->hasMethod(_object, ident))
- return jsUndefined();
-
- unsigned count = args.size();
- Vector<NPVariant, 128> cArgs(count);
-
- unsigned i;
- for (i = 0; i < count; i++)
- convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
-
- // Invoke the 'C' method.
- NPVariant resultVariant;
- VOID_TO_NPVARIANT(resultVariant);
-
- {
- JSLock::DropAllLocks dropAllLocks;
- _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
- }
-
- for (i = 0; i < count; i++)
- _NPN_ReleaseVariantValue(&cArgs[i]);
-
- JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
- _NPN_ReleaseVariantValue(&resultVariant);
- return resultValue;
-}
-
-
-JSValue* CInstance::invokeDefaultMethod(ExecState* exec, const List& args)
-{
- if (!_object->_class->invokeDefault)
- return jsUndefined();
-
- unsigned count = args.size();
- Vector<NPVariant, 128> cArgs(count);
-
- unsigned i;
- for (i = 0; i < count; i++)
- convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
-
- // Invoke the 'C' method.
- NPVariant resultVariant;
- VOID_TO_NPVARIANT(resultVariant);
- {
- JSLock::DropAllLocks dropAllLocks;
- _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
- }
-
- for (i = 0; i < count; i++)
- _NPN_ReleaseVariantValue(&cArgs[i]);
-
- JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
- _NPN_ReleaseVariantValue(&resultVariant);
- return resultValue;
-}
-
-
-JSValue* CInstance::defaultValue(JSType hint) const
-{
- if (hint == StringType)
- return stringValue();
- if (hint == NumberType)
- return numberValue();
- if (hint == BooleanType)
- return booleanValue();
- return valueOf();
-}
-
-JSValue* CInstance::stringValue() const
-{
- char buf[1024];
- snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
- return jsString(buf);
-}
-
-JSValue* CInstance::numberValue() const
-{
- // FIXME: Implement something sensible.
- return jsNumber(0);
-}
-
-JSValue* CInstance::booleanValue() const
-{
- // FIXME: Implement something sensible.
- return jsBoolean(false);
-}
-
-JSValue* CInstance::valueOf() const
-{
- return stringValue();
-}
-
-void CInstance::getPropertyNames(ExecState*, PropertyNameArray& nameArray)
-{
- if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) ||
- !_object->_class->enumerate)
- return;
-
- unsigned count;
- NPIdentifier* identifiers;
-
- {
- JSLock::DropAllLocks dropAllLocks;
- if (!_object->_class->enumerate(_object, &identifiers, &count))
- return;
- }
-
- for (unsigned i = 0; i < count; i++) {
- PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(identifiers[i]);
-
- if (identifier->isString)
- nameArray.add(identifierFromNPIdentifier(identifier->value.string));
- else
- nameArray.add(Identifier::from(identifier->value.number));
- }
-
- // FIXME: This should really call NPN_MemFree but that's in WebKit
- free(identifiers);
-}
-
-}
-}
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BINDINGS_C_INSTANCE_H_
-#define BINDINGS_C_INSTANCE_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "runtime.h"
-#include <wtf/Noncopyable.h>
-
-typedef struct NPObject NPObject;
-
-namespace KJS {
-
-namespace Bindings {
-
-class CClass;
-
-class CInstance : public Instance {
-public:
- CInstance (NPObject*, PassRefPtr<RootObject>);
- ~CInstance ();
-
- virtual Class *getClass() const;
-
- virtual void begin();
- virtual void end();
-
- virtual JSValue *valueOf() const;
- virtual JSValue *defaultValue (JSType hint) const;
-
- virtual bool implementsCall() const;
-
- virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
- virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- JSValue *stringValue() const;
- JSValue *numberValue() const;
- JSValue *booleanValue() const;
-
- NPObject *getObject() const { return _object; }
-
- virtual BindingLanguage getBindingLanguage() const { return CLanguage; }
-
-private:
- mutable CClass *_class;
- NPObject *_object;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "c_runtime.h"
-
-#include "c_instance.h"
-#include "c_utility.h"
-#include "npruntime_impl.h"
-
-namespace KJS {
-namespace Bindings {
-
-// ---------------------- CMethod ----------------------
-
-const char* CMethod::name() const
-{
- PrivateIdentifier *i = (PrivateIdentifier *)_methodIdentifier;
- return i->isString ? i->value.string : 0;
-}
-
-// ---------------------- CField ----------------------
-
-const char* CField::name() const
-{
- PrivateIdentifier *i = (PrivateIdentifier *)_fieldIdentifier;
- return i->isString ? i->value.string : 0;
-}
-
-JSValue* CField::valueFromInstance(ExecState* exec, const Instance* inst) const
-{
- const CInstance* instance = static_cast<const CInstance*>(inst);
- NPObject* obj = instance->getObject();
- if (obj->_class->getProperty) {
- NPVariant property;
- VOID_TO_NPVARIANT(property);
-
- bool result;
- {
- JSLock::DropAllLocks dropAllLocks;
- result = obj->_class->getProperty(obj, _fieldIdentifier, &property);
- }
- if (result) {
- JSValue* result = convertNPVariantToValue(exec, &property, instance->rootObject());
- _NPN_ReleaseVariantValue(&property);
- return result;
- }
- }
- return jsUndefined();
-}
-
-void CField::setValueToInstance(ExecState *exec, const Instance *inst, JSValue *aValue) const
-{
- const CInstance* instance = static_cast<const CInstance*>(inst);
- NPObject* obj = instance->getObject();
- if (obj->_class->setProperty) {
- NPVariant variant;
- convertValueToNPVariant(exec, aValue, &variant);
-
- {
- JSLock::DropAllLocks dropAllLocks;
- obj->_class->setProperty(obj, _fieldIdentifier, &variant);
- }
-
- _NPN_ReleaseVariantValue(&variant);
- }
-}
-
-} }
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BINDINGS_C_RUNTIME_H_
-#define BINDINGS_C_RUNTIME_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-#include "runtime.h"
-
-namespace KJS {
-namespace Bindings {
-
-class CField : public Field {
-public:
- CField(NPIdentifier ident) : _fieldIdentifier(ident) { }
-
- virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
- virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
- virtual const char* name() const;
-
-private:
- NPIdentifier _fieldIdentifier;
-};
-
-
-class CMethod : public Method
-{
-public:
- CMethod(NPIdentifier ident) : _methodIdentifier(ident) { }
-
- virtual const char* name() const;
- virtual int numParameters() const { return 0; }
-
-private:
- NPIdentifier _methodIdentifier;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "c_utility.h"
-
-#include "NP_jsobject.h"
-#include "c_instance.h"
-#include "JSGlobalObject.h"
-#include "npruntime_impl.h"
-#include "npruntime_priv.h"
-#include "runtime_object.h"
-#include "runtime_root.h"
-#include "Platform.h"
-#include <wtf/Assertions.h>
-#include <wtf/unicode/UTF8.h>
-
-using namespace WTF::Unicode;
-
-namespace KJS { namespace Bindings {
-
-// Requires free() of returned UTF16Chars.
-static void convertUTF8ToUTF16WithLatin1Fallback(const NPUTF8* UTF8Chars, int UTF8Length, NPUTF16** UTF16Chars, unsigned int* UTF16Length)
-{
- ASSERT(UTF8Chars || UTF8Length == 0);
- ASSERT(UTF16Chars);
-
- if (UTF8Length == -1)
- UTF8Length = static_cast<int>(strlen(UTF8Chars));
-
- *UTF16Length = UTF8Length;
- *UTF16Chars = static_cast<NPUTF16*>(malloc(sizeof(NPUTF16) * (*UTF16Length)));
-
- const char* sourcestart = UTF8Chars;
- const char* sourceend = sourcestart + UTF8Length;
-
- ::UChar* targetstart = reinterpret_cast< ::UChar*>(*UTF16Chars);
- ::UChar* targetend = targetstart + UTF8Length;
-
- ConversionResult result = convertUTF8ToUTF16(&sourcestart, sourceend, &targetstart, targetend);
-
- *UTF16Length = targetstart - reinterpret_cast< ::UChar*>(*UTF16Chars);
-
- // Check to see if the conversion was successful
- // Some plugins return invalid UTF-8 in NPVariantType_String, see <http://bugs.webkit.org/show_bug.cgi?id=5163>
- // There is no "bad data" for latin1. It is unlikely that the plugin was really sending text in this encoding,
- // but it should have used UTF-8, and now we are simply avoiding a crash.
- if (result != conversionOK) {
- *UTF16Length = UTF8Length;
-
- if (!*UTF16Chars) // If the memory wasn't allocated, allocate it.
- *UTF16Chars = (NPUTF16*)malloc(sizeof(NPUTF16) * (*UTF16Length));
-
- for (unsigned i = 0; i < *UTF16Length; i++)
- (*UTF16Chars)[i] = UTF8Chars[i] & 0xFF;
- }
-}
-
-// Variant value must be released with NPReleaseVariantValue()
-void convertValueToNPVariant(ExecState *exec, JSValue *value, NPVariant *result)
-{
- JSLock lock;
-
- JSType type = value->type();
-
- VOID_TO_NPVARIANT(*result);
-
- if (type == StringType) {
- UString ustring = value->toString(exec);
- CString cstring = ustring.UTF8String();
- NPString string = { (const NPUTF8 *)cstring.c_str(), static_cast<uint32_t>(cstring.size()) };
- NPN_InitializeVariantWithStringCopy(result, &string);
- } else if (type == NumberType) {
- DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result);
- } else if (type == BooleanType) {
- BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result);
- } else if (type == UnspecifiedType) {
- VOID_TO_NPVARIANT(*result);
- } else if (type == NullType) {
- NULL_TO_NPVARIANT(*result);
- } else if (type == ObjectType) {
- JSObject* object = static_cast<JSObject*>(value);
- if (object->classInfo() == &RuntimeObjectImp::info) {
- RuntimeObjectImp* imp = static_cast<RuntimeObjectImp *>(value);
- CInstance* instance = static_cast<CInstance*>(imp->getInternalInstance());
- if (instance) {
- NPObject* obj = instance->getObject();
- _NPN_RetainObject(obj);
- OBJECT_TO_NPVARIANT(obj, *result);
- }
- } else {
- JSGlobalObject* globalObject = exec->dynamicGlobalObject();
-
- RootObject* rootObject = findRootObject(globalObject);
- if (rootObject) {
- NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject);
- OBJECT_TO_NPVARIANT(npObject, *result);
- }
- }
- }
-}
-
-JSValue *convertNPVariantToValue(ExecState*, const NPVariant* variant, RootObject* rootObject)
-{
- JSLock lock;
-
- NPVariantType type = variant->type;
-
- if (type == NPVariantType_Bool)
- return jsBoolean(NPVARIANT_TO_BOOLEAN(*variant));
- if (type == NPVariantType_Null)
- return jsNull();
- if (type == NPVariantType_Void)
- return jsUndefined();
- if (type == NPVariantType_Int32)
- return jsNumber(NPVARIANT_TO_INT32(*variant));
- if (type == NPVariantType_Double)
- return jsNumber(NPVARIANT_TO_DOUBLE(*variant));
- if (type == NPVariantType_String) {
- NPUTF16 *stringValue;
- unsigned int UTF16Length;
- convertNPStringToUTF16(&variant->value.stringValue, &stringValue, &UTF16Length); // requires free() of returned memory
- UString resultString((const UChar *)stringValue,UTF16Length);
- free(stringValue);
- return jsString(resultString);
- }
- if (type == NPVariantType_Object) {
- NPObject *obj = variant->value.objectValue;
-
- if (obj->_class == NPScriptObjectClass)
- // Get JSObject from NP_JavaScriptObject.
- return ((JavaScriptObject *)obj)->imp;
-
- // Wrap NPObject in a CInstance.
- return Instance::createRuntimeObject(Instance::CLanguage, obj, rootObject);
- }
-
- return jsUndefined();
-}
-
-// Requires free() of returned UTF16Chars.
-void convertNPStringToUTF16(const NPString *string, NPUTF16 **UTF16Chars, unsigned int *UTF16Length)
-{
- convertUTF8ToUTF16WithLatin1Fallback(string->UTF8Characters, string->UTF8Length, UTF16Chars, UTF16Length);
-}
-
-Identifier identifierFromNPIdentifier(const NPUTF8* name)
-{
- NPUTF16 *methodName;
- unsigned UTF16Length;
- convertUTF8ToUTF16WithLatin1Fallback(name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
- Identifier identifier((const KJS::UChar*)methodName, UTF16Length);
- free(methodName);
- return identifier;
-}
-
-} }
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef C_UTILITY_H_
-#define C_UTILITY_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-
-namespace KJS {
-
-class ExecState;
-class Identifier;
-class JSValue;
-
-namespace Bindings {
-
-class RootObject;
-
-typedef uint16_t NPUTF16;
-
-enum NP_ValueType {
- NP_NumberValueType,
- NP_StringValueType,
- NP_BooleanValueType,
- NP_NullValueType,
- NP_UndefinedValueType,
- NP_ObjectValueType,
- NP_InvalidValueType
-};
-
-void convertNPStringToUTF16(const NPString*, NPUTF16** UTF16Chars, unsigned int* UTF16Length);
-void convertValueToNPVariant(ExecState*, JSValue*, NPVariant* result);
-JSValue* convertNPVariantToValue(ExecState*, const NPVariant*, RootObject*);
-Identifier identifierFromNPIdentifier(const NPUTF8* name);
-
-struct PrivateIdentifier {
- union {
- const NPUTF8* string;
- int32_t number;
- } value;
- bool isString;
-};
-
-} }
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include <jni_class.h>
-
-#include "identifier.h"
-#include <jni_utility.h>
-#include <jni_runtime.h>
-
-using namespace KJS::Bindings;
-
-JavaClass::JavaClass(jobject anInstance)
-{
- jobject aClass = callJNIObjectMethod(anInstance, "getClass", "()Ljava/lang/Class;");
-
- if (!aClass) {
- fprintf(stderr, "%s: unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance);
- return;
- }
-
- jstring className = (jstring)callJNIObjectMethod(aClass, "getName", "()Ljava/lang/String;");
- const char *classNameC = getCharactersFromJString(className);
- _name = strdup(classNameC);
- releaseCharactersForJString(className, classNameC);
-
- int i;
- JNIEnv *env = getJNIEnv();
-
- // Get the fields
- jarray fields = (jarray)callJNIObjectMethod(aClass, "getFields", "()[Ljava/lang/reflect/Field;");
- int numFields = env->GetArrayLength(fields);
- for (i = 0; i < numFields; i++) {
- jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i);
- Field *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
- {
- JSLock lock;
- _fields.set(Identifier(aField->name()).ustring().rep(), aField);
- }
- env->DeleteLocalRef(aJField);
- }
-
- // Get the methods
- jarray methods = (jarray)callJNIObjectMethod(aClass, "getMethods", "()[Ljava/lang/reflect/Method;");
- int numMethods = env->GetArrayLength(methods);
- for (i = 0; i < numMethods; i++) {
- jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i);
- Method *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
- MethodList* methodList;
- {
- JSLock lock;
-
- methodList = _methods.get(Identifier(aMethod->name()).ustring().rep());
- if (!methodList) {
- methodList = new MethodList();
- _methods.set(Identifier(aMethod->name()).ustring().rep(), methodList);
- }
- }
- methodList->append(aMethod);
- env->DeleteLocalRef(aJMethod);
- }
-}
-
-JavaClass::~JavaClass() {
- free((void *)_name);
-
- JSLock lock;
-
- deleteAllValues(_fields);
- _fields.clear();
-
- MethodListMap::const_iterator end = _methods.end();
- for (MethodListMap::const_iterator it = _methods.begin(); it != end; ++it) {
- const MethodList* methodList = it->second;
- deleteAllValues(*methodList);
- delete methodList;
- }
- _methods.clear();
-}
-
-MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const
-{
- MethodList *methodList = _methods.get(identifier.ustring().rep());
-
- if (methodList)
- return *methodList;
- return MethodList();
-}
-
-Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const
-{
- return _fields.get(identifier.ustring().rep());
-}
-
-bool JavaClass::isNumberClass() const
-{
- return ((strcmp(_name, "java.lang.Byte") == 0 ||
- strcmp(_name, "java.lang.Short") == 0 ||
- strcmp(_name, "java.lang.Integer") == 0 ||
- strcmp(_name, "java.lang.Long") == 0 ||
- strcmp(_name, "java.lang.Float") == 0 ||
- strcmp(_name, "java.lang.Double") == 0) );
-}
-
-bool JavaClass::isBooleanClass() const
-{
- return strcmp(_name, "java.lang.Boolean") == 0;
-}
-
-bool JavaClass::isStringClass() const
-{
- return strcmp(_name, "java.lang.String") == 0;
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JNI_CLASS_H_
-#define JNI_CLASS_H_
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include <jni_runtime.h>
-#include <wtf/HashMap.h>
-
-namespace KJS {
-
-namespace Bindings {
-
-class JavaClass : public Class {
-public:
- JavaClass (jobject anInstance);
- ~JavaClass ();
-
- virtual const char *name() const { return _name; };
-
- virtual MethodList methodsNamed(const Identifier&, Instance* instance) const;
- virtual Field *fieldNamed(const Identifier&, Instance* instance) const;
-
- bool isNumberClass() const;
- bool isBooleanClass() const;
- bool isStringClass() const;
-
-private:
- JavaClass (); // prevent default construction
-
- const char *_name;
- FieldMap _fields;
- MethodListMap _methods;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // ENABLE(JAVA_BINDINGS)
-
-#endif // JNI_CLASS_H_
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include "jni_class.h"
-#include "jni_instance.h"
-#include "jni_runtime.h"
-#include "jni_utility.h"
-#include "runtime_object.h"
-#include "runtime_root.h"
-
-#ifdef NDEBUG
-#define JS_LOG(formatAndArgs...) ((void)0)
-#else
-#define JS_LOG(formatAndArgs...) { \
- fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
- fprintf(stderr, formatAndArgs); \
-}
-#endif
-
-using namespace KJS::Bindings;
-using namespace KJS;
-
-JavaInstance::JavaInstance (jobject instance, PassRefPtr<RootObject> rootObject)
- : Instance(rootObject)
-{
- _instance = new JObjectWrapper (instance);
- _class = 0;
-}
-
-JavaInstance::~JavaInstance ()
-{
- delete _class;
-}
-
-#define NUM_LOCAL_REFS 64
-
-void JavaInstance::begin()
-{
- getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS);
-}
-
-void JavaInstance::end()
-{
- getJNIEnv()->PopLocalFrame (NULL);
-}
-
-Class *JavaInstance::getClass() const
-{
- if (_class == 0)
- _class = new JavaClass (_instance->_instance);
- return _class;
-}
-
-JSValue *JavaInstance::stringValue() const
-{
- JSLock lock;
-
- jstring stringValue = (jstring)callJNIObjectMethod (_instance->_instance, "toString", "()Ljava/lang/String;");
- JNIEnv *env = getJNIEnv();
- const jchar *c = getUCharactersFromJStringInEnv(env, stringValue);
- UString u((const UChar *)c, (int)env->GetStringLength(stringValue));
- releaseUCharactersForJStringInEnv(env, stringValue, c);
- return jsString(u);
-}
-
-JSValue *JavaInstance::numberValue() const
-{
- jdouble doubleValue = callJNIDoubleMethod (_instance->_instance, "doubleValue", "()D");
- return jsNumber(doubleValue);
-}
-
-JSValue *JavaInstance::booleanValue() const
-{
- jboolean booleanValue = callJNIBooleanMethod (_instance->_instance, "booleanValue", "()Z");
- return jsBoolean(booleanValue);
-}
-
-JSValue *JavaInstance::invokeMethod (ExecState *exec, const MethodList &methodList, const List &args)
-{
- int i, count = args.size();
- jvalue *jArgs;
- JSValue *resultValue;
- Method *method = 0;
- size_t numMethods = methodList.size();
-
- // Try to find a good match for the overloaded method. The
- // fundamental problem is that JavaScript doesn have the
- // notion of method overloading and Java does. We could
- // get a bit more sophisticated and attempt to does some
- // type checking as we as checking the number of parameters.
- Method *aMethod;
- for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
- aMethod = methodList[methodIndex];
- if (aMethod->numParameters() == count) {
- method = aMethod;
- break;
- }
- }
- if (method == 0) {
- JS_LOG ("unable to find an appropiate method\n");
- return jsUndefined();
- }
-
- const JavaMethod *jMethod = static_cast<const JavaMethod*>(method);
- JS_LOG ("call %s %s on %p\n", method->name(), jMethod->signature(), _instance->_instance);
-
- if (count > 0) {
- jArgs = (jvalue *)malloc (count * sizeof(jvalue));
- }
- else
- jArgs = 0;
-
- for (i = 0; i < count; i++) {
- JavaParameter* aParameter = jMethod->parameterAt(i);
- jArgs[i] = convertValueToJValue (exec, args.at(i), aParameter->getJNIType(), aParameter->type());
- JS_LOG("arg[%d] = %s\n", i, args.at(i)->toString(exec).ascii());
- }
-
- jvalue result;
-
- // Try to use the JNI abstraction first, otherwise fall back to
- // nornmal JNI. The JNI dispatch abstraction allows the Java plugin
- // to dispatch the call on the appropriate internal VM thread.
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return jsUndefined();
-
- bool handled = false;
- if (rootObject->nativeHandle()) {
- jobject obj = _instance->_instance;
- JSValue *exceptionDescription = NULL;
- const char *callingURL = 0; // FIXME, need to propagate calling URL to Java
- handled = dispatchJNICall(rootObject->nativeHandle(), obj, jMethod->isStatic(), jMethod->JNIReturnType(), jMethod->methodID(obj), jArgs, result, callingURL, exceptionDescription);
- if (exceptionDescription) {
- throwError(exec, GeneralError, exceptionDescription->toString(exec));
- free (jArgs);
- return jsUndefined();
- }
- }
-
- // The following code can be conditionally removed once we have a Tiger update that
- // contains the new Java plugin. It is needed for builds prior to Tiger.
- if (!handled) {
- jobject obj = _instance->_instance;
- switch (jMethod->JNIReturnType()){
- case void_type: {
- callJNIVoidMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case object_type: {
- result.l = callJNIObjectMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case boolean_type: {
- result.z = callJNIBooleanMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case byte_type: {
- result.b = callJNIByteMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case char_type: {
- result.c = callJNICharMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case short_type: {
- result.s = callJNIShortMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case int_type: {
- result.i = callJNIIntMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case long_type: {
- result.j = callJNILongMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case float_type: {
- result.f = callJNIFloatMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case double_type: {
- result.d = callJNIDoubleMethodIDA (obj, jMethod->methodID(obj), jArgs);
- }
- break;
-
- case invalid_type:
- default: {
- }
- break;
- }
- }
-
- switch (jMethod->JNIReturnType()){
- case void_type: {
- resultValue = jsUndefined();
- }
- break;
-
- case object_type: {
- if (result.l != 0) {
- const char *arrayType = jMethod->returnType();
- if (arrayType[0] == '[') {
- resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject);
- }
- else {
- resultValue = Instance::createRuntimeObject(Instance::JavaLanguage, result.l, rootObject);
- }
- }
- else {
- resultValue = jsUndefined();
- }
- }
- break;
-
- case boolean_type: {
- resultValue = jsBoolean(result.z);
- }
- break;
-
- case byte_type: {
- resultValue = jsNumber(result.b);
- }
- break;
-
- case char_type: {
- resultValue = jsNumber(result.c);
- }
- break;
-
- case short_type: {
- resultValue = jsNumber(result.s);
- }
- break;
-
- case int_type: {
- resultValue = jsNumber(result.i);
- }
- break;
-
- case long_type: {
- resultValue = jsNumber(result.j);
- }
- break;
-
- case float_type: {
- resultValue = jsNumber(result.f);
- }
- break;
-
- case double_type: {
- resultValue = jsNumber(result.d);
- }
- break;
-
- case invalid_type:
- default: {
- resultValue = jsUndefined();
- }
- break;
- }
-
- free (jArgs);
-
- return resultValue;
-}
-
-JSValue *JavaInstance::defaultValue (JSType hint) const
-{
- if (hint == StringType) {
- return stringValue();
- }
- else if (hint == NumberType) {
- return numberValue();
- }
- else if (hint == BooleanType) {
- return booleanValue();
- }
- else if (hint == UnspecifiedType) {
- JavaClass *aClass = static_cast<JavaClass*>(getClass());
- if (aClass->isStringClass()) {
- return stringValue();
- }
- else if (aClass->isNumberClass()) {
- return numberValue();
- }
- else if (aClass->isBooleanClass()) {
- return booleanValue();
- }
- }
-
- return valueOf();
-}
-
-JSValue *JavaInstance::valueOf() const
-{
- return stringValue();
-}
-
-JObjectWrapper::JObjectWrapper(jobject instance)
-: _refCount(0)
-{
- assert (instance != 0);
-
- // Cache the JNIEnv used to get the global ref for this java instanace.
- // It'll be used to delete the reference.
- _env = getJNIEnv();
-
- _instance = _env->NewGlobalRef (instance);
-
- JS_LOG ("new global ref %p for %p\n", _instance, instance);
-
- if (_instance == NULL) {
- fprintf (stderr, "%s: could not get GlobalRef for %p\n", __PRETTY_FUNCTION__, instance);
- }
-}
-
-JObjectWrapper::~JObjectWrapper() {
- JS_LOG ("deleting global ref %p\n", _instance);
- _env->DeleteGlobalRef (_instance);
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _JNI_INSTANCE_H_
-#define _JNI_INSTANCE_H_
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include "runtime.h"
-
-#include <JavaVM/jni.h>
-
-
-namespace KJS {
-
-namespace Bindings {
-
-class JavaClass;
-
-class JObjectWrapper
-{
-friend class RefPtr<JObjectWrapper>;
-friend class JavaArray;
-friend class JavaField;
-friend class JavaInstance;
-friend class JavaMethod;
-
-protected:
- JObjectWrapper(jobject instance);
- ~JObjectWrapper();
-
- void ref() { _refCount++; }
- void deref()
- {
- if (--_refCount == 0)
- delete this;
- }
-
- jobject _instance;
-
-private:
- JNIEnv *_env;
- unsigned int _refCount;
-};
-
-class JavaInstance : public Instance
-{
-public:
- JavaInstance(jobject instance, PassRefPtr<RootObject>);
- ~JavaInstance();
-
- virtual Class *getClass() const;
-
- virtual void begin();
- virtual void end();
-
- virtual JSValue *valueOf() const;
- virtual JSValue *defaultValue (JSType hint) const;
-
- virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
-
- jobject javaInstance() const { return _instance->_instance; }
-
- JSValue *stringValue() const;
- JSValue *numberValue() const;
- JSValue *booleanValue() const;
-
- virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
-
-private:
- RefPtr<JObjectWrapper> _instance;
- mutable JavaClass *_class;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // ENABLE(JAVA_BINDINGS)
-
-#endif // _JNI_INSTANCE_H_
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include "SourceCode.h"
-#include "identifier.h"
-#include "internal.h"
-#include "interpreter.h"
-#include "jni_jsobject.h"
-#include "jni_runtime.h"
-#include "jni_utility.h"
-#include "JSGlobalObject.h"
-#include "list.h"
-#include "runtime_object.h"
-#include "runtime_root.h"
-#include <CoreFoundation/CoreFoundation.h>
-#include <wtf/Assertions.h>
-
-using namespace KJS::Bindings;
-using namespace KJS;
-
-#ifdef NDEBUG
-#define JS_LOG(formatAndArgs...) ((void)0)
-#else
-#define JS_LOG(formatAndArgs...) { \
- fprintf (stderr, "%s(%p,%p): ", __PRETTY_FUNCTION__, RootObject::runLoop(), CFRunLoopGetCurrent()); \
- fprintf(stderr, formatAndArgs); \
-}
-#endif
-
-#define UndefinedHandle 1
-
-static bool isJavaScriptThread()
-{
- return (RootObject::runLoop() == CFRunLoopGetCurrent());
-}
-
-jvalue JavaJSObject::invoke (JSObjectCallContext *context)
-{
- jvalue result;
-
- bzero ((void *)&result, sizeof(jvalue));
-
- if (!isJavaScriptThread()) {
- // Send the call context to the thread that is allowed to
- // call JavaScript.
- RootObject::dispatchToJavaScriptThread(context);
- result = context->result;
- }
- else {
- jlong nativeHandle = context->nativeHandle;
- if (nativeHandle == UndefinedHandle || nativeHandle == 0) {
- return result;
- }
-
- if (context->type == CreateNative) {
- result.j = JavaJSObject::createNative(nativeHandle);
- }
- else {
- JSObject *imp = jlong_to_impptr(nativeHandle);
- if (!findProtectingRootObject(imp)) {
- fprintf (stderr, "%s:%d: Attempt to access JavaScript from destroyed applet, type %d.\n", __FILE__, __LINE__, context->type);
- return result;
- }
-
- switch (context->type){
- case Call: {
- result.l = JavaJSObject(nativeHandle).call(context->string, context->args);
- break;
- }
-
- case Eval: {
- result.l = JavaJSObject(nativeHandle).eval(context->string);
- break;
- }
-
- case GetMember: {
- result.l = JavaJSObject(nativeHandle).getMember(context->string);
- break;
- }
-
- case SetMember: {
- JavaJSObject(nativeHandle).setMember(context->string, context->value);
- break;
- }
-
- case RemoveMember: {
- JavaJSObject(nativeHandle).removeMember(context->string);
- break;
- }
-
- case GetSlot: {
- result.l = JavaJSObject(nativeHandle).getSlot(context->index);
- break;
- }
-
- case SetSlot: {
- JavaJSObject(nativeHandle).setSlot(context->index, context->value);
- break;
- }
-
- case ToString: {
- result.l = (jobject) JavaJSObject(nativeHandle).toString();
- break;
- }
-
- case Finalize: {
- JavaJSObject(nativeHandle).finalize();
- break;
- }
-
- default: {
- fprintf (stderr, "%s: invalid JavaScript call\n", __PRETTY_FUNCTION__);
- }
- }
- }
- context->result = result;
- }
-
- return result;
-}
-
-
-JavaJSObject::JavaJSObject(jlong nativeJSObject)
-{
- _imp = jlong_to_impptr(nativeJSObject);
-
- ASSERT(_imp);
- _rootObject = findProtectingRootObject(_imp);
- ASSERT(_rootObject);
-}
-
-RootObject* JavaJSObject::rootObject() const
-{
- return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
-}
-
-jobject JavaJSObject::call(jstring methodName, jobjectArray args) const
-{
- JS_LOG ("methodName = %s\n", JavaString(methodName).UTF8String());
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- // Lookup the function object.
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
-
- Identifier identifier(JavaString(methodName).ustring());
- JSValue *func = _imp->get (exec, identifier);
- if (func->isUndefinedOrNull())
- return 0;
-
- // Call the function object.
- JSObject *funcImp = static_cast<JSObject*>(func);
- JSObject *thisObj = const_cast<JSObject*>(_imp);
- List argList;
- getListFromJArray(args, argList);
- rootObject->globalObject()->startTimeoutCheck();
- JSValue *result = funcImp->call(exec, thisObj, argList);
- rootObject->globalObject()->stopTimeoutCheck();
-
- return convertValueToJObject(result);
-}
-
-jobject JavaJSObject::eval(jstring script) const
-{
- JS_LOG ("script = %s\n", JavaString(script).UTF8String());
-
- JSObject *thisObj = const_cast<JSObject*>(_imp);
- JSValue *result;
-
- JSLock lock;
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- rootObject->globalObject()->startTimeoutCheck();
-
- SourceCode source = makeSource(JavaString(script).ustring(), UString());
- Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), source, thisObj);
-
- rootObject->globalObject()->stopTimeoutCheck();
- ComplType type = completion.complType();
-
- if (type == Normal) {
- result = completion.value();
- if (!result)
- result = jsUndefined();
- } else
- result = jsUndefined();
-
- return convertValueToJObject (result);
-}
-
-jobject JavaJSObject::getMember(jstring memberName) const
-{
- JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String());
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
-
- JSLock lock;
- JSValue *result = _imp->get (exec, Identifier (JavaString(memberName).ustring()));
-
- return convertValueToJObject(result);
-}
-
-void JavaJSObject::setMember(jstring memberName, jobject value) const
-{
- JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value);
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- _imp->put(exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value));
-}
-
-
-void JavaJSObject::removeMember(jstring memberName) const
-{
- JS_LOG ("memberName = %s\n", JavaString(memberName).UTF8String());
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- _imp->deleteProperty(exec, Identifier (JavaString(memberName).ustring()));
-}
-
-
-jobject JavaJSObject::getSlot(jint index) const
-{
-#ifdef __LP64__
- JS_LOG ("index = %d\n", index);
-#else
- JS_LOG ("index = %ld\n", index);
-#endif
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
-
- JSLock lock;
- JSValue *result = _imp->get (exec, (unsigned)index);
-
- return convertValueToJObject(result);
-}
-
-
-void JavaJSObject::setSlot(jint index, jobject value) const
-{
-#ifdef __LP64__
- JS_LOG ("index = %d, value = %p\n", index, value);
-#else
- JS_LOG ("index = %ld, value = %p\n", index, value);
-#endif
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JSLock lock;
- _imp->put(exec, (unsigned)index, convertJObjectToValue(value));
-}
-
-
-jstring JavaJSObject::toString() const
-{
- JS_LOG ("\n");
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- JSLock lock;
- JSObject *thisObj = const_cast<JSObject*>(_imp);
- ExecState* exec = rootObject->globalObject()->globalExec();
-
- return (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l;
-}
-
-void JavaJSObject::finalize() const
-{
- if (RootObject* rootObject = this->rootObject())
- rootObject->gcUnprotect(_imp);
-}
-
-// We're either creating a 'Root' object (via a call to JavaJSObject.getWindow()), or
-// another JavaJSObject.
-jlong JavaJSObject::createNative(jlong nativeHandle)
-{
- JS_LOG ("nativeHandle = %d\n", (int)nativeHandle);
-
- if (nativeHandle == UndefinedHandle)
- return nativeHandle;
-
- if (findProtectingRootObject(jlong_to_impptr(nativeHandle)))
- return nativeHandle;
-
- CreateRootObjectFunction createRootObject = RootObject::createRootObject();
- if (!createRootObject)
- return ptr_to_jlong(0);
-
- RefPtr<RootObject> rootObject = createRootObject(jlong_to_ptr(nativeHandle));
-
- // If rootObject is !NULL We must have been called via netscape.javascript.JavaJSObject.getWindow(),
- // otherwise we are being called after creating a JavaJSObject in
- // JavaJSObject::convertValueToJObject().
- if (rootObject) {
- JSObject* globalObject = rootObject->globalObject();
- // We call gcProtect here to get the object into the root object's "protect set" which
- // is used to test if a native handle is valid as well as getting the root object given the handle.
- rootObject->gcProtect(globalObject);
- return ptr_to_jlong(globalObject);
- }
-
- return nativeHandle;
-}
-
-jobject JavaJSObject::convertValueToJObject (JSValue *value) const
-{
- JSLock lock;
-
- RootObject* rootObject = this->rootObject();
- if (!rootObject)
- return 0;
-
- ExecState* exec = rootObject->globalObject()->globalExec();
- JNIEnv *env = getJNIEnv();
- jobject result = 0;
-
- // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition',
- // figure 22-5.
- // number -> java.lang.Double
- // string -> java.lang.String
- // boolean -> java.lang.Boolean
- // Java instance -> Java instance
- // Everything else -> JavaJSObject
-
- JSType type = value->type();
- if (type == NumberType) {
- jclass JSObjectClass = env->FindClass ("java/lang/Double");
- jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V");
- if (constructorID != NULL) {
- result = env->NewObject (JSObjectClass, constructorID, (jdouble)value->toNumber(exec));
- }
- }
- else if (type == StringType) {
- UString stringValue = value->toString(exec);
- JNIEnv *env = getJNIEnv();
- result = env->NewString ((const jchar *)stringValue.data(), stringValue.size());
- }
- else if (type == BooleanType) {
- jclass JSObjectClass = env->FindClass ("java/lang/Boolean");
- jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(Z)V");
- if (constructorID != NULL) {
- result = env->NewObject (JSObjectClass, constructorID, (jboolean)value->toBoolean(exec));
- }
- }
- else {
- // Create a JavaJSObject.
- jlong nativeHandle;
-
- if (type == ObjectType){
- JSObject *imp = static_cast<JSObject*>(value);
-
- // We either have a wrapper around a Java instance or a JavaScript
- // object. If we have a wrapper around a Java instance, return that
- // instance, otherwise create a new Java JavaJSObject with the JSObject*
- // as it's nativeHandle.
- if (imp->classInfo() && strcmp(imp->classInfo()->className, "RuntimeObject") == 0) {
- RuntimeObjectImp *runtimeImp = static_cast<RuntimeObjectImp*>(value);
- JavaInstance *runtimeInstance = static_cast<JavaInstance *>(runtimeImp->getInternalInstance());
- if (!runtimeInstance)
- return 0;
-
- return runtimeInstance->javaInstance();
- }
- else {
- nativeHandle = ptr_to_jlong(imp);
- rootObject->gcProtect(imp);
- }
- }
- // All other types will result in an undefined object.
- else {
- nativeHandle = UndefinedHandle;
- }
-
- // Now create the Java JavaJSObject. Look for the JavaJSObject in it's new (Tiger)
- // location and in the original Java 1.4.2 location.
- jclass JSObjectClass;
-
- JSObjectClass = env->FindClass ("sun/plugin/javascript/webkit/JSObject");
- if (!JSObjectClass) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- JSObjectClass = env->FindClass ("apple/applet/JSObject");
- }
-
- jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(J)V");
- if (constructorID != NULL) {
- result = env->NewObject (JSObjectClass, constructorID, nativeHandle);
- }
- }
-
- return result;
-}
-
-JSValue *JavaJSObject::convertJObjectToValue (jobject theObject) const
-{
- // Instances of netscape.javascript.JSObject get converted back to
- // JavaScript objects. All other objects are wrapped. It's not
- // possible to pass primitive types from the Java to JavaScript.
- // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition',
- // figure 22-4.
- jobject classOfInstance = callJNIObjectMethod(theObject, "getClass", "()Ljava/lang/Class;");
- jstring className = (jstring)callJNIObjectMethod(classOfInstance, "getName", "()Ljava/lang/String;");
-
- // Only the sun.plugin.javascript.webkit.JSObject has a member called nativeJSObject. This class is
- // created above to wrap internal browser objects. The constructor of this class takes the native
- // pointer and stores it in this object, so that it can be retrieved below.
- if (strcmp(JavaString(className).UTF8String(), "sun.plugin.javascript.webkit.JSObject") == 0) {
- // Pull the nativeJSObject value from the Java instance. This is a
- // pointer to the JSObject.
- JNIEnv *env = getJNIEnv();
- jfieldID fieldID = env->GetFieldID((jclass)classOfInstance, "nativeJSObject", "J");
- if (fieldID == NULL) {
- return jsUndefined();
- }
- jlong nativeHandle = env->GetLongField(theObject, fieldID);
- if (nativeHandle == UndefinedHandle) {
- return jsUndefined();
- }
- JSObject *imp = static_cast<JSObject*>(jlong_to_impptr(nativeHandle));
- return imp;
- }
-
- JSLock lock;
- JavaInstance* javaInstance = new JavaInstance(theObject, _rootObject);
- return KJS::Bindings::Instance::createRuntimeObject(javaInstance);
-}
-
-void JavaJSObject::getListFromJArray(jobjectArray jArray, List& list) const
-{
- JNIEnv *env = getJNIEnv();
- int i, numObjects = jArray ? env->GetArrayLength (jArray) : 0;
-
- for (i = 0; i < numObjects; i++) {
- jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i);
- if (anObject) {
- list.append(convertJObjectToValue(anObject));
- env->DeleteLocalRef (anObject);
- }
- else {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- }
-}
-
-extern "C" {
-
-jlong KJS_JSCreateNativeJSObject (JNIEnv*, jclass, jstring, jlong nativeHandle, jboolean)
-{
- JSObjectCallContext context;
- context.type = CreateNative;
- context.nativeHandle = nativeHandle;
- return JavaJSObject::invoke (&context).j;
-}
-
-void KJS_JSObject_JSFinalize (JNIEnv*, jclass, jlong nativeHandle)
-{
- JSObjectCallContext context;
- context.type = Finalize;
- context.nativeHandle = nativeHandle;
- JavaJSObject::invoke (&context);
-}
-
-jobject KJS_JSObject_JSObjectCall (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring methodName, jobjectArray args, jboolean)
-{
- JSObjectCallContext context;
- context.type = Call;
- context.nativeHandle = nativeHandle;
- context.string = methodName;
- context.args = args;
- return JavaJSObject::invoke (&context).l;
-}
-
-jobject KJS_JSObject_JSObjectEval (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jscript, jboolean)
-{
- JSObjectCallContext context;
- context.type = Eval;
- context.nativeHandle = nativeHandle;
- context.string = jscript;
- return JavaJSObject::invoke (&context).l;
-}
-
-jobject KJS_JSObject_JSObjectGetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
-{
- JSObjectCallContext context;
- context.type = GetMember;
- context.nativeHandle = nativeHandle;
- context.string = jname;
- return JavaJSObject::invoke (&context).l;
-}
-
-void KJS_JSObject_JSObjectSetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jobject value, jboolean)
-{
- JSObjectCallContext context;
- context.type = SetMember;
- context.nativeHandle = nativeHandle;
- context.string = jname;
- context.value = value;
- JavaJSObject::invoke (&context);
-}
-
-void KJS_JSObject_JSObjectRemoveMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
-{
- JSObjectCallContext context;
- context.type = RemoveMember;
- context.nativeHandle = nativeHandle;
- context.string = jname;
- JavaJSObject::invoke (&context);
-}
-
-jobject KJS_JSObject_JSObjectGetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jboolean)
-{
- JSObjectCallContext context;
- context.type = GetSlot;
- context.nativeHandle = nativeHandle;
- context.index = jindex;
- return JavaJSObject::invoke (&context).l;
-}
-
-void KJS_JSObject_JSObjectSetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jobject value, jboolean)
-{
- JSObjectCallContext context;
- context.type = SetSlot;
- context.nativeHandle = nativeHandle;
- context.index = jindex;
- context.value = value;
- JavaJSObject::invoke (&context);
-}
-
-jstring KJS_JSObject_JSObjectToString (JNIEnv*, jclass, jlong nativeHandle)
-{
- JSObjectCallContext context;
- context.type = ToString;
- context.nativeHandle = nativeHandle;
- return (jstring)JavaJSObject::invoke (&context).l;
-}
-
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
-#define JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
-
-#if ENABLE(JAVA_BINDINGS)
-
-#if PLATFORM(MAC)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-#include <JavaVM/jni.h>
-#include <wtf/RefPtr.h>
-
-#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))
-#define jlong_to_impptr(a) (static_cast<KJS::JSObject*>(((void*)(uintptr_t)(a))))
-#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
-
-namespace KJS {
-
-class List;
-class JSObject;
-class JSValue;
-
-namespace Bindings {
-
-class RootObject;
-
-enum JSObjectCallType {
- CreateNative,
- Call,
- Eval,
- GetMember,
- SetMember,
- RemoveMember,
- GetSlot,
- SetSlot,
- ToString,
- Finalize
-};
-
-struct JSObjectCallContext
-{
- JSObjectCallType type;
- jlong nativeHandle;
- jstring string;
- jobjectArray args;
- jint index;
- jobject value;
- CFRunLoopRef originatingLoop;
- jvalue result;
-};
-
-class JavaJSObject
-{
-public:
- JavaJSObject(jlong nativeHandle);
-
- static jlong createNative(jlong nativeHandle);
- jobject call(jstring methodName, jobjectArray args) const;
- jobject eval(jstring script) const;
- jobject getMember(jstring memberName) const;
- void setMember(jstring memberName, jobject value) const;
- void removeMember(jstring memberName) const;
- jobject getSlot(jint index) const;
- void setSlot(jint index, jobject value) const;
- jstring toString() const;
- void finalize() const;
-
- static jvalue invoke(JSObjectCallContext*);
-
- jobject convertValueToJObject(JSValue*) const;
- JSValue* convertJObjectToValue(jobject) const;
- void getListFromJArray(jobjectArray, List&) const;
-
- RootObject* rootObject() const;
-
-private:
- RefPtr<RootObject> _rootObject;
- JSObject* _imp;
-};
-
-
-} // namespace Bindings
-
-} // namespace KJS
-
-extern "C" {
-
-// The Java VM calls these functions to handle calls to methods in Java's JSObject class.
-jlong KJS_JSCreateNativeJSObject(JNIEnv*, jclass, jstring jurl, jlong nativeHandle, jboolean ctx);
-void KJS_JSObject_JSFinalize(JNIEnv*, jclass, jlong nativeJSObject);
-jobject KJS_JSObject_JSObjectCall(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring methodName, jobjectArray args, jboolean ctx);
-jobject KJS_JSObject_JSObjectEval(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jscript, jboolean ctx);
-jobject KJS_JSObject_JSObjectGetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
-void KJS_JSObject_JSObjectSetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jobject value, jboolean ctx);
-void KJS_JSObject_JSObjectRemoveMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
-jobject KJS_JSObject_JSObjectGetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jboolean ctx);
-void KJS_JSObject_JSObjectSetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jobject value, jboolean ctx);
-jstring KJS_JSObject_JSObjectToString(JNIEnv*, jclass, jlong nativeJSObject);
-
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
-
-#endif // JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#import <Foundation/Foundation.h>
-#import <JavaScriptCore/jni_utility.h>
-#import <JavaScriptCore/objc_utility.h>
-
-using namespace KJS::Bindings;
-
-@interface NSObject (WebScriptingPrivate)
-- (jvalue)webPlugInCallJava:(jobject)object method:(jmethodID)method returnType:(JNIType)returnType arguments:(jvalue*)args;
-- (jvalue)webPlugInCallJava:(jobject)object
- isStatic:(BOOL)isStatic
- returnType:(JNIType)returnType
- method:(jmethodID)method
- arguments:(jvalue*)args
- callingURL:(NSURL *)url
- exceptionDescription:(NSString **)exceptionString;
-@end
-
-bool KJS::Bindings::dispatchJNICall (const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char*, JSValue *&exceptionDescription)
-{
- id view = (id)targetAppletView;
-
- // As array_type is not known by the Mac JVM, change it to a compatible type.
- if (returnType == array_type)
- returnType = object_type;
-
- if ([view respondsToSelector:@selector(webPlugInCallJava:isStatic:returnType:method:arguments:callingURL:exceptionDescription:)]) {
- NSString *_exceptionDescription = 0;
-
- // Passing nil as the calling URL will cause the Java plugin to use the URL
- // of the page that contains the applet. The execution restrictions
- // implemented in WebCore will guarantee that only appropriate JavaScript
- // can reference the applet.
- {
- JSLock::DropAllLocks dropAllLocks;
- result = [view webPlugInCallJava:obj isStatic:isStatic returnType:returnType method:methodID arguments:args callingURL:nil exceptionDescription:&_exceptionDescription];
- }
-
- if (_exceptionDescription != 0) {
- exceptionDescription = convertNSStringToString(_exceptionDescription);
- }
- return true;
- }
- else if ([view respondsToSelector:@selector(webPlugInCallJava:method:returnType:arguments:)]) {
- JSLock::DropAllLocks dropAllLocks;
- result = [view webPlugInCallJava:obj method:methodID returnType:returnType arguments:args];
- return true;
- }
-
- bzero (&result, sizeof(jvalue));
- return false;
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include <internal.h>
-#include <ustring.h>
-#include <value.h>
-
-#include <jni_utility.h>
-#include <jni_runtime.h>
-
-#include <runtime_array.h>
-#include <runtime_object.h>
-#include <runtime_root.h>
-
-#ifdef NDEBUG
-#define JS_LOG(formatAndArgs...) ((void)0)
-#else
-#define JS_LOG(formatAndArgs...) { \
- fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
- fprintf(stderr, formatAndArgs); \
-}
-#endif
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-
-JavaParameter::JavaParameter (JNIEnv *env, jstring type)
-{
- _type = JavaString (env, type);
- _JNIType = JNITypeFromClassName (_type.UTF8String());
-}
-
-JavaField::JavaField (JNIEnv *env, jobject aField)
-{
- // Get field type
- jobject fieldType = callJNIObjectMethod (aField, "getType", "()Ljava/lang/Class;");
- jstring fieldTypeName = (jstring)callJNIObjectMethod (fieldType, "getName", "()Ljava/lang/String;");
- _type = JavaString(env, fieldTypeName);
- _JNIType = JNITypeFromClassName (_type.UTF8String());
-
- // Get field name
- jstring fieldName = (jstring)callJNIObjectMethod (aField, "getName", "()Ljava/lang/String;");
- _name = JavaString(env, fieldName);
-
- _field = new JObjectWrapper(aField);
-}
-
-JSValue* JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
-{
- if (type[0] != '[')
- return jsUndefined();
-
- return new RuntimeArray(exec, new JavaArray((jobject)anObject, type, rootObject));
-}
-
-jvalue JavaField::dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const
-{
- jobject jinstance = instance->javaInstance();
- jobject fieldJInstance = _field->_instance;
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- jclass cls = env->GetObjectClass(fieldJInstance);
- if ( cls != NULL ) {
- jmethodID mid = env->GetMethodID(cls, name, sig);
- if ( mid != NULL )
- {
- RootObject* rootObject = instance->rootObject();
- if (rootObject && rootObject->nativeHandle()) {
- JSValue *exceptionDescription = NULL;
- jvalue args[1];
-
- args[0].l = jinstance;
- dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
- if (exceptionDescription)
- throwError(exec, GeneralError, exceptionDescription->toString(exec));
- }
- }
- }
- return result;
-}
-
-JSValue *JavaField::valueFromInstance(ExecState *exec, const Instance *i) const
-{
- const JavaInstance *instance = static_cast<const JavaInstance *>(i);
-
- JSValue *jsresult = jsUndefined();
-
- switch (_JNIType) {
- case array_type:
- case object_type: {
- jvalue result = dispatchValueFromInstance (exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
- jobject anObject = result.l;
-
- const char *arrayType = type();
- if (arrayType[0] == '[') {
- jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
- }
- else if (anObject != 0){
- jsresult = Instance::createRuntimeObject(Instance::JavaLanguage, anObject, instance->rootObject());
- }
- }
- break;
-
- case boolean_type:
- jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type).z);
- break;
-
- case byte_type:
- case char_type:
- case short_type:
-
- case int_type: {
- jint value;
- jvalue result = dispatchValueFromInstance (exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
- value = result.i;
- jsresult = jsNumber((int)value);
- }
- break;
-
- case long_type:
- case float_type:
- case double_type: {
- jdouble value;
- jvalue result = dispatchValueFromInstance (exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
- value = result.i;
- jsresult = jsNumber((double)value);
- }
- break;
- default:
- break;
- }
-
- JS_LOG ("getting %s = %s\n", name(), jsresult->toString(exec).ascii());
-
- return jsresult;
-}
-
-void JavaField::dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const
-{
- jobject jinstance = instance->javaInstance();
- jobject fieldJInstance = _field->_instance;
- JNIEnv *env = getJNIEnv();
-
- jclass cls = env->GetObjectClass(fieldJInstance);
- if ( cls != NULL ) {
- jmethodID mid = env->GetMethodID(cls, name, sig);
- if ( mid != NULL )
- {
- RootObject* rootObject = instance->rootObject();
- if (rootObject && rootObject->nativeHandle()) {
- JSValue *exceptionDescription = NULL;
- jvalue args[2];
- jvalue result;
-
- args[0].l = jinstance;
- args[1] = javaValue;
- dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
- if (exceptionDescription)
- throwError(exec, GeneralError, exceptionDescription->toString(exec));
- }
- }
- }
-}
-
-void JavaField::setValueToInstance(ExecState *exec, const Instance *i, JSValue *aValue) const
-{
- const JavaInstance *instance = static_cast<const JavaInstance *>(i);
- jvalue javaValue = convertValueToJValue (exec, aValue, _JNIType, type());
-
- JS_LOG ("setting value %s to %s\n", name(), aValue->toString(exec).ascii());
-
- switch (_JNIType) {
- case array_type:
- case object_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
- }
- break;
-
- case boolean_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
- }
- break;
-
- case byte_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
- }
- break;
-
- case char_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
- }
- break;
-
- case short_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
- }
- break;
-
- case int_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
- }
- break;
-
- case long_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
- }
- break;
-
- case float_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
- }
- break;
-
- case double_type: {
- dispatchSetValueToInstance (exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
- }
- break;
- default:
- break;
- }
-}
-
-JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod)
-{
- // Get return type
- jobject returnType = callJNIObjectMethod (aMethod, "getReturnType", "()Ljava/lang/Class;");
- jstring returnTypeName = (jstring)callJNIObjectMethod (returnType, "getName", "()Ljava/lang/String;");
- _returnType =JavaString (env, returnTypeName);
- _JNIReturnType = JNITypeFromClassName (_returnType.UTF8String());
- env->DeleteLocalRef (returnType);
- env->DeleteLocalRef (returnTypeName);
-
- // Get method name
- jstring methodName = (jstring)callJNIObjectMethod (aMethod, "getName", "()Ljava/lang/String;");
- _name = JavaString (env, methodName);
- env->DeleteLocalRef (methodName);
-
- // Get parameters
- jarray jparameters = (jarray)callJNIObjectMethod (aMethod, "getParameterTypes", "()[Ljava/lang/Class;");
- _numParameters = env->GetArrayLength (jparameters);
- _parameters = new JavaParameter[_numParameters];
-
- int i;
- for (i = 0; i < _numParameters; i++) {
- jobject aParameter = env->GetObjectArrayElement ((jobjectArray)jparameters, i);
- jstring parameterName = (jstring)callJNIObjectMethod (aParameter, "getName", "()Ljava/lang/String;");
- _parameters[i] = JavaParameter(env, parameterName);
- env->DeleteLocalRef (aParameter);
- env->DeleteLocalRef (parameterName);
- }
- env->DeleteLocalRef (jparameters);
-
- // Created lazily.
- _signature = 0;
- _methodID = 0;
-
- jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
- int modifiers = callJNIIntMethod (aMethod, "getModifiers", "()I");
- _isStatic = (bool)callJNIStaticBooleanMethod (modifierClass, "isStatic", "(I)Z", modifiers);
-}
-
-JavaMethod::~JavaMethod()
-{
- if (_signature)
- free(_signature);
- delete [] _parameters;
-};
-
-// JNI method signatures use '/' between components of a class name, but
-// we get '.' between components from the reflection API.
-static void appendClassName(UString& aString, const char* className)
-{
- ASSERT(JSLock::lockCount() > 0);
-
- char *result, *cp = strdup(className);
-
- result = cp;
- while (*cp) {
- if (*cp == '.')
- *cp = '/';
- cp++;
- }
-
- aString.append(result);
-
- free (result);
-}
-
-const char *JavaMethod::signature() const
-{
- if (!_signature) {
- JSLock lock;
-
- UString signatureBuilder("(");
- for (int i = 0; i < _numParameters; i++) {
- JavaParameter* aParameter = parameterAt(i);
- JNIType _JNIType = aParameter->getJNIType();
- if (_JNIType == array_type)
- appendClassName(signatureBuilder, aParameter->type());
- else {
- signatureBuilder.append(signatureFromPrimitiveType(_JNIType));
- if (_JNIType == object_type) {
- appendClassName(signatureBuilder, aParameter->type());
- signatureBuilder.append(";");
- }
- }
- }
- signatureBuilder.append(")");
-
- const char *returnType = _returnType.UTF8String();
- if (_JNIReturnType == array_type) {
- appendClassName(signatureBuilder, returnType);
- } else {
- signatureBuilder.append(signatureFromPrimitiveType(_JNIReturnType));
- if (_JNIReturnType == object_type) {
- appendClassName(signatureBuilder, returnType);
- signatureBuilder.append(";");
- }
- }
-
- _signature = strdup(signatureBuilder.ascii());
- }
-
- return _signature;
-}
-
-JNIType JavaMethod::JNIReturnType() const
-{
- return _JNIReturnType;
-}
-
-jmethodID JavaMethod::methodID (jobject obj) const
-{
- if (_methodID == 0) {
- _methodID = getMethodID (obj, name(), signature());
- }
- return _methodID;
-}
-
-
-JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
- : Array(rootObject)
-{
- _array = new JObjectWrapper(array);
- // Java array are fixed length, so we can cache length.
- JNIEnv *env = getJNIEnv();
- _length = env->GetArrayLength((jarray)_array->_instance);
- _type = strdup(type);
- _rootObject = rootObject;
-}
-
-JavaArray::~JavaArray ()
-{
- free ((void *)_type);
-}
-
-RootObject* JavaArray::rootObject() const
-{
- return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
-}
-
-void JavaArray::setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const
-{
- JNIEnv *env = getJNIEnv();
- char *javaClassName = 0;
-
- JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
- if (_type[1] == 'L'){
- // The type of the array will be something like:
- // "[Ljava.lang.string;". This is guaranteed, so no need
- // for extra sanity checks.
- javaClassName = strdup(&_type[2]);
- javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
- }
- jvalue aJValue = convertValueToJValue (exec, aValue, arrayType, javaClassName);
-
- switch (arrayType) {
- case object_type: {
- env->SetObjectArrayElement((jobjectArray)javaArray(), index, aJValue.l);
- break;
- }
-
- case boolean_type: {
- env->SetBooleanArrayRegion((jbooleanArray)javaArray(), index, 1, &aJValue.z);
- break;
- }
-
- case byte_type: {
- env->SetByteArrayRegion((jbyteArray)javaArray(), index, 1, &aJValue.b);
- break;
- }
-
- case char_type: {
- env->SetCharArrayRegion((jcharArray)javaArray(), index, 1, &aJValue.c);
- break;
- }
-
- case short_type: {
- env->SetShortArrayRegion((jshortArray)javaArray(), index, 1, &aJValue.s);
- break;
- }
-
- case int_type: {
- env->SetIntArrayRegion((jintArray)javaArray(), index, 1, &aJValue.i);
- break;
- }
-
- case long_type: {
- env->SetLongArrayRegion((jlongArray)javaArray(), index, 1, &aJValue.j);
- }
-
- case float_type: {
- env->SetFloatArrayRegion((jfloatArray)javaArray(), index, 1, &aJValue.f);
- break;
- }
-
- case double_type: {
- env->SetDoubleArrayRegion((jdoubleArray)javaArray(), index, 1, &aJValue.d);
- break;
- }
- default:
- break;
- }
-
- if (javaClassName)
- free ((void *)javaClassName);
-}
-
-
-JSValue *JavaArray::valueAt(ExecState *exec, unsigned int index) const
-{
- JNIEnv *env = getJNIEnv();
- JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
- switch (arrayType) {
- case object_type: {
- jobjectArray objectArray = (jobjectArray)javaArray();
- jobject anObject;
- anObject = env->GetObjectArrayElement(objectArray, index);
-
- // No object?
- if (!anObject) {
- return jsNull();
- }
-
- // Nested array?
- if (_type[1] == '[') {
- return JavaArray::convertJObjectToArray(exec, anObject, _type+1, rootObject());
- }
- // or array of other object type?
- return Instance::createRuntimeObject(Instance::JavaLanguage, anObject, rootObject());
- }
-
- case boolean_type: {
- jbooleanArray booleanArray = (jbooleanArray)javaArray();
- jboolean aBoolean;
- env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
- return jsBoolean(aBoolean);
- }
-
- case byte_type: {
- jbyteArray byteArray = (jbyteArray)javaArray();
- jbyte aByte;
- env->GetByteArrayRegion(byteArray, index, 1, &aByte);
- return jsNumber(aByte);
- }
-
- case char_type: {
- jcharArray charArray = (jcharArray)javaArray();
- jchar aChar;
- env->GetCharArrayRegion(charArray, index, 1, &aChar);
- return jsNumber(aChar);
- break;
- }
-
- case short_type: {
- jshortArray shortArray = (jshortArray)javaArray();
- jshort aShort;
- env->GetShortArrayRegion(shortArray, index, 1, &aShort);
- return jsNumber(aShort);
- }
-
- case int_type: {
- jintArray intArray = (jintArray)javaArray();
- jint anInt;
- env->GetIntArrayRegion(intArray, index, 1, &anInt);
- return jsNumber(anInt);
- }
-
- case long_type: {
- jlongArray longArray = (jlongArray)javaArray();
- jlong aLong;
- env->GetLongArrayRegion(longArray, index, 1, &aLong);
- return jsNumber(aLong);
- }
-
- case float_type: {
- jfloatArray floatArray = (jfloatArray)javaArray();
- jfloat aFloat;
- env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
- return jsNumber(aFloat);
- }
-
- case double_type: {
- jdoubleArray doubleArray = (jdoubleArray)javaArray();
- jdouble aDouble;
- env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
- return jsNumber(aDouble);
- }
- default:
- break;
- }
- return jsUndefined();
-}
-
-unsigned int JavaArray::getLength() const
-{
- return _length;
-}
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _JNI_RUNTIME_H_
-#define _JNI_RUNTIME_H_
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include <jni_utility.h>
-#include <jni_instance.h>
-
-
-namespace KJS
-{
-
-namespace Bindings
-{
-
-typedef const char* RuntimeType;
-
-class JavaString
-{
-public:
- JavaString()
- {
- JSLock lock;
- _rep = UString().rep();
- }
-
- void _commonInit (JNIEnv *e, jstring s)
- {
- int _size = e->GetStringLength (s);
- const jchar *uc = getUCharactersFromJStringInEnv (e, s);
- {
- JSLock lock;
- _rep = UString((UChar *)uc,_size).rep();
- }
- releaseUCharactersForJStringInEnv (e, s, uc);
- }
-
- JavaString (JNIEnv *e, jstring s) {
- _commonInit (e, s);
- }
-
- JavaString (jstring s) {
- _commonInit (getJNIEnv(), s);
- }
-
- ~JavaString()
- {
- JSLock lock;
- _rep = 0;
- }
-
- const char *UTF8String() const {
- if (_utf8String.c_str() == 0) {
- JSLock lock;
- _utf8String = UString(_rep).UTF8String();
- }
- return _utf8String.c_str();
- }
- const jchar *uchars() const { return (const jchar *)_rep->data(); }
- int length() const { return _rep->size(); }
- UString ustring() const { return UString(_rep); }
-
-private:
- RefPtr<UString::Rep> _rep;
- mutable CString _utf8String;
-};
-
-class JavaParameter
-{
-public:
- JavaParameter () : _JNIType(invalid_type) {};
- JavaParameter (JNIEnv *env, jstring type);
- virtual ~JavaParameter() { }
-
- RuntimeType type() const { return _type.UTF8String(); }
- JNIType getJNIType() const { return _JNIType; }
-
-private:
- JavaString _type;
- JNIType _JNIType;
-};
-
-
-class JavaField : public Field
-{
-public:
- JavaField (JNIEnv *env, jobject aField);
-
- virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
- virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
-
- virtual const char *name() const { return _name.UTF8String(); }
- virtual RuntimeType type() const { return _type.UTF8String(); }
-
- JNIType getJNIType() const { return _JNIType; }
-
-private:
- void dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const;
- jvalue dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const;
-
- JavaString _name;
- JavaString _type;
- JNIType _JNIType;
- RefPtr<JObjectWrapper> _field;
-};
-
-
-class JavaMethod : public Method
-{
-public:
- JavaMethod(JNIEnv* env, jobject aMethod);
- ~JavaMethod();
-
- virtual const char *name() const { return _name.UTF8String(); };
- RuntimeType returnType() const { return _returnType.UTF8String(); };
- JavaParameter* parameterAt(int i) const { return &_parameters[i]; };
- int numParameters() const { return _numParameters; };
-
- const char *signature() const;
- JNIType JNIReturnType() const;
-
- jmethodID methodID (jobject obj) const;
-
- bool isStatic() const { return _isStatic; }
-
-private:
- JavaParameter* _parameters;
- int _numParameters;
- JavaString _name;
- mutable char* _signature;
- JavaString _returnType;
- JNIType _JNIReturnType;
- mutable jmethodID _methodID;
- bool _isStatic;
-};
-
-class JavaArray : public Array
-{
-public:
- JavaArray(jobject array, const char* type, PassRefPtr<RootObject>);
- virtual ~JavaArray();
-
- RootObject* rootObject() const;
-
- virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const;
- virtual JSValue *valueAt(ExecState *exec, unsigned int index) const;
- virtual unsigned int getLength() const;
-
- jobject javaArray() const { return _array->_instance; }
-
- static JSValue* convertJObjectToArray (ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject>);
-
-private:
- RefPtr<JObjectWrapper> _array;
- unsigned int _length;
- const char *_type;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // ENABLE(JAVA_BINDINGS)
-
-#endif // _JNI_RUNTIME_H_
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include "jni_utility.h"
-
-#include "list.h"
-#include "jni_runtime.h"
-#include "runtime_array.h"
-#include "runtime_object.h"
-#include <dlfcn.h>
-
-namespace KJS {
-
-namespace Bindings {
-
-static jint KJS_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
-{
- static void* javaVMFramework = 0;
- if (!javaVMFramework)
- javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
- if (!javaVMFramework)
- return JNI_ERR;
-
- static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0;
- if (!functionPointer)
- functionPointer = (jint(*)(JavaVM**, jsize, jsize *))dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs");
- if (!functionPointer)
- return JNI_ERR;
- return functionPointer(vmBuf, bufLen, nVMs);
-}
-
-static JavaVM *jvm = 0;
-
-// Provide the ability for an outside component to specify the JavaVM to use
-// If the jvm value is set, the getJavaVM function below will just return.
-// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
-// attached, the result is a no-op.
-void setJavaVM(JavaVM *javaVM)
-{
- jvm = javaVM;
-}
-
-JavaVM *getJavaVM()
-{
- if (jvm)
- return jvm;
-
- JavaVM *jvmArray[1];
- jsize bufLen = 1;
- jsize nJVMs = 0;
- jint jniError = 0;
-
- // Assumes JVM is already running ..., one per process
- jniError = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
- if ( jniError == JNI_OK && nJVMs > 0 ) {
- jvm = jvmArray[0];
- }
- else
- fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
-
- return jvm;
-}
-
-JNIEnv* getJNIEnv()
-{
- union {
- JNIEnv* env;
- void* dummy;
- } u;
- jint jniError = 0;
-
- jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL);
- if (jniError == JNI_OK)
- return u.env;
- else
- fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
- return NULL;
-}
-
-static jvalue callJNIMethod (JNIType type, jobject obj, const char *name, const char *sig, va_list args)
-{
- JavaVM *jvm = getJavaVM();
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- if ( obj != NULL && jvm != NULL && env != NULL) {
- jclass cls = env->GetObjectClass(obj);
- if ( cls != NULL ) {
- jmethodID mid = env->GetMethodID(cls, name, sig);
- if ( mid != NULL )
- {
- switch (type) {
- case void_type:
- env->functions->CallVoidMethodV(env, obj, mid, args);
- break;
- case array_type:
- case object_type:
- result.l = env->functions->CallObjectMethodV(env, obj, mid, args);
- break;
- case boolean_type:
- result.z = env->functions->CallBooleanMethodV(env, obj, mid, args);
- break;
- case byte_type:
- result.b = env->functions->CallByteMethodV(env, obj, mid, args);
- break;
- case char_type:
- result.c = env->functions->CallCharMethodV(env, obj, mid, args);
- break;
- case short_type:
- result.s = env->functions->CallShortMethodV(env, obj, mid, args);
- break;
- case int_type:
- result.i = env->functions->CallIntMethodV(env, obj, mid, args);
- break;
- case long_type:
- result.j = env->functions->CallLongMethodV(env, obj, mid, args);
- break;
- case float_type:
- result.f = env->functions->CallFloatMethodV(env, obj, mid, args);
- break;
- case double_type:
- result.d = env->functions->CallDoubleMethodV(env, obj, mid, args);
- break;
- default:
- fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
- }
- }
- else
- {
- fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj);
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
-
- env->DeleteLocalRef(cls);
- }
- else {
- fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj);
- }
- }
-
- return result;
-}
-
-static jvalue callJNIStaticMethod (JNIType type, jclass cls, const char *name, const char *sig, va_list args)
-{
- JavaVM *jvm = getJavaVM();
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- if ( cls != NULL && jvm != NULL && env != NULL) {
- jmethodID mid = env->GetStaticMethodID(cls, name, sig);
- if ( mid != NULL )
- {
- switch (type) {
- case void_type:
- env->functions->CallStaticVoidMethodV(env, cls, mid, args);
- break;
- case array_type:
- case object_type:
- result.l = env->functions->CallStaticObjectMethodV(env, cls, mid, args);
- break;
- case boolean_type:
- result.z = env->functions->CallStaticBooleanMethodV(env, cls, mid, args);
- break;
- case byte_type:
- result.b = env->functions->CallStaticByteMethodV(env, cls, mid, args);
- break;
- case char_type:
- result.c = env->functions->CallStaticCharMethodV(env, cls, mid, args);
- break;
- case short_type:
- result.s = env->functions->CallStaticShortMethodV(env, cls, mid, args);
- break;
- case int_type:
- result.i = env->functions->CallStaticIntMethodV(env, cls, mid, args);
- break;
- case long_type:
- result.j = env->functions->CallStaticLongMethodV(env, cls, mid, args);
- break;
- case float_type:
- result.f = env->functions->CallStaticFloatMethodV(env, cls, mid, args);
- break;
- case double_type:
- result.d = env->functions->CallStaticDoubleMethodV(env, cls, mid, args);
- break;
- default:
- fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
- }
- }
- else
- {
- fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, cls);
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
- }
-
- return result;
-}
-
-static jvalue callJNIMethodIDA (JNIType type, jobject obj, jmethodID mid, jvalue *args)
-{
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- if ( obj != NULL && mid != NULL )
- {
- switch (type) {
- case void_type:
- env->functions->CallVoidMethodA(env, obj, mid, args);
- break;
- case array_type:
- case object_type:
- result.l = env->functions->CallObjectMethodA(env, obj, mid, args);
- break;
- case boolean_type:
- result.z = env->functions->CallBooleanMethodA(env, obj, mid, args);
- break;
- case byte_type:
- result.b = env->functions->CallByteMethodA(env, obj, mid, args);
- break;
- case char_type:
- result.c = env->functions->CallCharMethodA(env, obj, mid, args);
- break;
- case short_type:
- result.s = env->functions->CallShortMethodA(env, obj, mid, args);
- break;
- case int_type:
- result.i = env->functions->CallIntMethodA(env, obj, mid, args);
- break;
- case long_type:
- result.j = env->functions->CallLongMethodA(env, obj, mid, args);
- break;
- case float_type:
- result.f = env->functions->CallFloatMethodA(env, obj, mid, args);
- break;
- case double_type:
- result.d = env->functions->CallDoubleMethodA(env, obj, mid, args);
- break;
- default:
- fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
- }
- }
-
- return result;
-}
-
-static jvalue callJNIMethodA (JNIType type, jobject obj, const char *name, const char *sig, jvalue *args)
-{
- JavaVM *jvm = getJavaVM();
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- if ( obj != NULL && jvm != NULL && env != NULL) {
- jclass cls = env->GetObjectClass(obj);
- if ( cls != NULL ) {
- jmethodID mid = env->GetMethodID(cls, name, sig);
- if ( mid != NULL ) {
- result = callJNIMethodIDA (type, obj, mid, args);
- }
- else {
- fprintf(stderr, "%s: Could not find method: %s\n", __PRETTY_FUNCTION__, name);
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
-
- env->DeleteLocalRef(cls);
- }
- else {
- fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
- }
- }
-
- return result;
-}
-
-jmethodID getMethodID (jobject obj, const char *name, const char *sig)
-{
- JNIEnv *env = getJNIEnv();
- jmethodID mid = 0;
-
- if ( env != NULL) {
- jclass cls = env->GetObjectClass(obj);
- if ( cls != NULL ) {
- mid = env->GetMethodID(cls, name, sig);
- if (!mid) {
- env->ExceptionClear();
- mid = env->GetStaticMethodID(cls, name, sig);
- if (!mid) {
- env->ExceptionClear();
- }
- }
- }
- env->DeleteLocalRef(cls);
- }
- return mid;
-}
-
-
-#define CALL_JNI_METHOD(function_type,obj,name,sig) \
- va_list args;\
- va_start (args, sig);\
- \
- jvalue result = callJNIMethod(function_type, obj, name, sig, args);\
- \
- va_end (args);
-
-#define CALL_JNI_STATIC_METHOD(function_type,cls,name,sig) \
- va_list args;\
- va_start (args, sig);\
- \
- jvalue result = callJNIStaticMethod(function_type, cls, name, sig, args);\
- \
- va_end (args);
-
-void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (void_type, obj, name, sig);
-}
-
-jobject callJNIObjectMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (object_type, obj, name, sig);
- return result.l;
-}
-
-jboolean callJNIBooleanMethod( jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (boolean_type, obj, name, sig);
- return result.z;
-}
-
-jboolean callJNIStaticBooleanMethod (jclass cls, const char *name, const char *sig, ... )
-{
- CALL_JNI_STATIC_METHOD (boolean_type, cls, name, sig);
- return result.z;
-}
-
-jbyte callJNIByteMethod( jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (byte_type, obj, name, sig);
- return result.b;
-}
-
-jchar callJNICharMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (char_type, obj, name, sig);
- return result.c;
-}
-
-jshort callJNIShortMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (short_type, obj, name, sig);
- return result.s;
-}
-
-jint callJNIIntMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (int_type, obj, name, sig);
- return result.i;
-}
-
-jlong callJNILongMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (long_type, obj, name, sig);
- return result.j;
-}
-
-jfloat callJNIFloatMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (float_type, obj, name, sig);
- return result.f;
-}
-
-jdouble callJNIDoubleMethod (jobject obj, const char *name, const char *sig, ... )
-{
- CALL_JNI_METHOD (double_type, obj, name, sig);
- return result.d;
-}
-
-void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (void_type, obj, name, sig, args);
-}
-
-jobject callJNIObjectMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (object_type, obj, name, sig, args);
- return result.l;
-}
-
-jbyte callJNIByteMethodA ( jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (byte_type, obj, name, sig, args);
- return result.b;
-}
-
-jchar callJNICharMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (char_type, obj, name, sig, args);
- return result.c;
-}
-
-jshort callJNIShortMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (short_type, obj, name, sig, args);
- return result.s;
-}
-
-jint callJNIIntMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (int_type, obj, name, sig, args);
- return result.i;
-}
-
-jlong callJNILongMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (long_type, obj, name, sig, args);
- return result.j;
-}
-
-jfloat callJNIFloatMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (float_type, obj, name, sig, args);
- return result.f;
-}
-
-jdouble callJNIDoubleMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (double_type, obj, name, sig, args);
- return result.d;
-}
-
-jboolean callJNIBooleanMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
-{
- jvalue result = callJNIMethodA (boolean_type, obj, name, sig, args);
- return result.z;
-}
-
-void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (void_type, obj, methodID, args);
-}
-
-jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (object_type, obj, methodID, args);
- return result.l;
-}
-
-jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args);
- return result.b;
-}
-
-jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (char_type, obj, methodID, args);
- return result.c;
-}
-
-jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (short_type, obj, methodID, args);
- return result.s;
-}
-
-jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (int_type, obj, methodID, args);
- return result.i;
-}
-
-jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (long_type, obj, methodID, args);
- return result.j;
-}
-
-jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (float_type, obj, methodID, args);
- return result.f;
-}
-
-jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (double_type, obj, methodID, args);
- return result.d;
-}
-
-jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
-{
- jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args);
- return result.z;
-}
-
-const char *getCharactersFromJString (jstring aJString)
-{
- return getCharactersFromJStringInEnv (getJNIEnv(), aJString);
-}
-
-void releaseCharactersForJString (jstring aJString, const char *s)
-{
- releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s);
-}
-
-const char *getCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
-{
- jboolean isCopy;
- const char *s = env->GetStringUTFChars((jstring)aJString, &isCopy);
- if (!s) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
- return s;
-}
-
-void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s)
-{
- env->ReleaseStringUTFChars (aJString, s);
-}
-
-const jchar *getUCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
-{
- jboolean isCopy;
- const jchar *s = env->GetStringChars((jstring)aJString, &isCopy);
- if (!s) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
- return s;
-}
-
-void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s)
-{
- env->ReleaseStringChars (aJString, s);
-}
-
-JNIType JNITypeFromClassName(const char *name)
-{
- JNIType type;
-
- if (strcmp("byte",name) == 0)
- type = byte_type;
- else if (strcmp("short",name) == 0)
- type = short_type;
- else if (strcmp("int",name) == 0)
- type = int_type;
- else if (strcmp("long",name) == 0)
- type = long_type;
- else if (strcmp("float",name) == 0)
- type = float_type;
- else if (strcmp("double",name) == 0)
- type = double_type;
- else if (strcmp("char",name) == 0)
- type = char_type;
- else if (strcmp("boolean",name) == 0)
- type = boolean_type;
- else if (strcmp("void",name) == 0)
- type = void_type;
- else if ('[' == name[0])
- type = array_type;
- else
- type = object_type;
-
- return type;
-}
-
-const char *signatureFromPrimitiveType(JNIType type)
-{
- switch (type){
- case void_type:
- return "V";
-
- case array_type:
- return "[";
-
- case object_type:
- return "L";
-
- case boolean_type:
- return "Z";
-
- case byte_type:
- return "B";
-
- case char_type:
- return "C";
-
- case short_type:
- return "S";
-
- case int_type:
- return "I";
-
- case long_type:
- return "J";
-
- case float_type:
- return "F";
-
- case double_type:
- return "D";
-
- case invalid_type:
- default:
- break;
- }
- return "";
-}
-
-JNIType JNITypeFromPrimitiveType(char type)
-{
- switch (type){
- case 'V':
- return void_type;
-
- case 'L':
- return object_type;
-
- case '[':
- return array_type;
-
- case 'Z':
- return boolean_type;
-
- case 'B':
- return byte_type;
-
- case 'C':
- return char_type;
-
- case 'S':
- return short_type;
-
- case 'I':
- return int_type;
-
- case 'J':
- return long_type;
-
- case 'F':
- return float_type;
-
- case 'D':
- return double_type;
-
- default:
- break;
- }
- return invalid_type;
-}
-
-jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *signature)
-{
- JavaVM *jvm = getJavaVM();
- JNIEnv *env = getJNIEnv();
- jvalue result;
-
- bzero (&result, sizeof(jvalue));
- if ( obj != NULL && jvm != NULL && env != NULL) {
- jclass cls = env->GetObjectClass(obj);
- if ( cls != NULL ) {
- jfieldID field = env->GetFieldID(cls, name, signature);
- if ( field != NULL ) {
- switch (type) {
- case array_type:
- case object_type:
- result.l = env->functions->GetObjectField(env, obj, field);
- break;
- case boolean_type:
- result.z = env->functions->GetBooleanField(env, obj, field);
- break;
- case byte_type:
- result.b = env->functions->GetByteField(env, obj, field);
- break;
- case char_type:
- result.c = env->functions->GetCharField(env, obj, field);
- break;
- case short_type:
- result.s = env->functions->GetShortField(env, obj, field);
- break;
- case int_type:
- result.i = env->functions->GetIntField(env, obj, field);
- break;
- case long_type:
- result.j = env->functions->GetLongField(env, obj, field);
- break;
- case float_type:
- result.f = env->functions->GetFloatField(env, obj, field);
- break;
- case double_type:
- result.d = env->functions->GetDoubleField(env, obj, field);
- break;
- default:
- fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, (int)type);
- }
- }
- else
- {
- fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name);
- env->ExceptionDescribe();
- env->ExceptionClear();
- fprintf (stderr, "\n");
- }
-
- env->DeleteLocalRef(cls);
- }
- else {
- fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
- }
- }
-
- return result;
-}
-
-static jobject convertArrayInstanceToJavaArray(ExecState *exec, JSValue *value, const char *javaClassName) {
-
- ASSERT(JSLock::lockCount() > 0);
-
- JNIEnv *env = getJNIEnv();
- // As JS Arrays can contain a mixture of objects, assume we can convert to
- // the requested Java Array type requested, unless the array type is some object array
- // other than a string.
- ArrayInstance *jsArray = static_cast<ArrayInstance *>(value);
- unsigned length = jsArray->getLength();
- jobjectArray jarray = 0;
-
- // Build the correct array type
- switch (JNITypeFromPrimitiveType(javaClassName[1])) {
- case object_type: {
- // Only support string object types
- if (0 == strcmp("[Ljava.lang.String;", javaClassName)) {
- jarray = (jobjectArray)env->NewObjectArray(length,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- UString stringValue = item->toString(exec);
- env->SetObjectArrayElement(jarray,i,
- env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()));
- }
- }
- break;
- }
-
- case boolean_type: {
- jarray = (jobjectArray)env->NewBooleanArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jboolean value = (jboolean)item->toNumber(exec);
- env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case byte_type: {
- jarray = (jobjectArray)env->NewByteArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jbyte value = (jbyte)item->toNumber(exec);
- env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case char_type: {
- jarray = (jobjectArray)env->NewCharArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- UString stringValue = item->toString(exec);
- jchar value = 0;
- if (stringValue.size() > 0)
- value = ((const jchar*)stringValue.data())[0];
- env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case short_type: {
- jarray = (jobjectArray)env->NewShortArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jshort value = (jshort)item->toNumber(exec);
- env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case int_type: {
- jarray = (jobjectArray)env->NewIntArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jint value = (jint)item->toNumber(exec);
- env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case long_type: {
- jarray = (jobjectArray)env->NewLongArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jlong value = (jlong)item->toNumber(exec);
- env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case float_type: {
- jarray = (jobjectArray)env->NewFloatArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jfloat value = (jfloat)item->toNumber(exec);
- env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case double_type: {
- jarray = (jobjectArray)env->NewDoubleArray(length);
- for(unsigned i = 0; i < length; i++) {
- JSValue* item = jsArray->getItem(i);
- jdouble value = (jdouble)item->toNumber(exec);
- env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value);
- }
- break;
- }
-
- case array_type: // don't handle embedded arrays
- case void_type: // Don't expect arrays of void objects
- case invalid_type: // Array of unknown objects
- break;
- }
-
- // if it was not one of the cases handled, then null is returned
- return jarray;
-}
-
-
-jvalue convertValueToJValue (ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName)
-{
- JSLock lock;
-
- jvalue result;
-
- switch (_JNIType){
- case array_type:
- case object_type: {
- result.l = (jobject)0;
-
- // First see if we have a Java instance.
- if (value->isObject()){
- JSObject *objectImp = static_cast<JSObject*>(value);
- if (objectImp->classInfo() == &RuntimeObjectImp::info) {
- RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value);
- JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance());
- if (instance)
- result.l = instance->javaInstance();
- }
- else if (objectImp->classInfo() == &RuntimeArray::info) {
- // Input is a JavaScript Array that was originally created from a Java Array
- RuntimeArray *imp = static_cast<RuntimeArray *>(value);
- JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray());
- result.l = array->javaArray();
- }
- else if (objectImp->classInfo() == &ArrayInstance::info) {
- // Input is a Javascript Array. We need to create it to a Java Array.
- result.l = convertArrayInstanceToJavaArray(exec, value, javaClassName);
- }
- }
-
- // Now convert value to a string if the target type is a java.lang.string, and we're not
- // converting from a Null.
- if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) {
-#ifdef CONVERT_NULL_TO_EMPTY_STRING
- if (value->isNull()) {
- JNIEnv *env = getJNIEnv();
- jchar buf[2];
- jobject javaString = env->functions->NewString (env, buf, 0);
- result.l = javaString;
- }
- else
-#else
- if (!value->isNull())
-#endif
- {
- UString stringValue = value->toString(exec);
- JNIEnv *env = getJNIEnv();
- jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
- result.l = javaString;
- }
- } else if (result.l == 0)
- bzero (&result, sizeof(jvalue)); // Handle it the same as a void case
- }
- break;
-
- case boolean_type: {
- result.z = (jboolean)value->toNumber(exec);
- }
- break;
-
- case byte_type: {
- result.b = (jbyte)value->toNumber(exec);
- }
- break;
-
- case char_type: {
- result.c = (jchar)value->toNumber(exec);
- }
- break;
-
- case short_type: {
- result.s = (jshort)value->toNumber(exec);
- }
- break;
-
- case int_type: {
- result.i = (jint)value->toNumber(exec);
- }
- break;
-
- case long_type: {
- result.j = (jlong)value->toNumber(exec);
- }
- break;
-
- case float_type: {
- result.f = (jfloat)value->toNumber(exec);
- }
- break;
-
- case double_type: {
- result.d = (jdouble)value->toNumber(exec);
- }
- break;
-
- break;
-
- case invalid_type:
- default:
- case void_type: {
- bzero (&result, sizeof(jvalue));
- }
- break;
- }
- return result;
-}
-
-} // end of namespace Bindings
-
-} // end of namespace KJS
-
-#endif // ENABLE(JAVA_BINDINGS)
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _JNI_UTILITY_H_
-#define _JNI_UTILITY_H_
-
-#if ENABLE(JAVA_BINDINGS)
-
-#include <list.h>
-
-#include <JavaVM/jni.h>
-
-// The order of these items can not be modified as they are tightly
-// bound with the JVM on Mac OSX. If new types need to be added, they
-// should be added to the end. It is used in jni_obc.mm when calling
-// through to the JVM. Newly added items need to be made compatible
-// in that file.
-typedef enum {
- invalid_type = 0,
- void_type,
- object_type,
- boolean_type,
- byte_type,
- char_type,
- short_type,
- int_type,
- long_type,
- float_type,
- double_type,
- array_type
-} JNIType;
-
-namespace KJS {
-
-namespace Bindings {
-
-class JavaParameter;
-
-const char *getCharactersFromJString(jstring aJString);
-void releaseCharactersForJString(jstring aJString, const char *s);
-
-const char *getCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
-void releaseCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const char *s);
-const jchar *getUCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
-void releaseUCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const jchar *s);
-
-JNIType JNITypeFromClassName(const char *name);
-JNIType JNITypeFromPrimitiveType(char type);
-const char *signatureFromPrimitiveType(JNIType type);
-
-jvalue convertValueToJValue(ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName);
-
-jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature);
-
-jmethodID getMethodID(jobject obj, const char *name, const char *sig);
-
-jobject callJNIObjectMethod(jobject obj, const char *name, const char *sig, ... );
-void callJNIVoidMethod(jobject obj, const char *name, const char *sig, ... );
-jboolean callJNIBooleanMethod(jobject obj, const char *name, const char *sig, ... );
-jboolean callJNIStaticBooleanMethod(jclass cls, const char *name, const char *sig, ... );
-jbyte callJNIByteMethod(jobject obj, const char *name, const char *sig, ... );
-jchar callJNICharMethod(jobject obj, const char *name, const char *sig, ... );
-jshort callJNIShortMethod(jobject obj, const char *name, const char *sig, ... );
-jint callJNIIntMethod(jobject obj, const char *name, const char *sig, ... );
-jlong callJNILongMethod(jobject obj, const char *name, const char *sig, ... );
-jfloat callJNIFloatMethod(jobject obj, const char *name, const char *sig, ... );
-jdouble callJNIDoubleMethod(jobject obj, const char *name, const char *sig, ... );
-
-jobject callJNIObjectMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-void callJNIVoidMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jboolean callJNIBooleanMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jbyte callJNIByteMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jchar callJNICharMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jshort callJNIShortMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jint callJNIIntMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jlong callJNILongMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jfloat callJNIFloatMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-jdouble callJNIDoubleMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
-
-jobject callJNIObjectMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-void callJNIVoidMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jboolean callJNIBooleanMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jbyte callJNIByteMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jchar callJNICharMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jshort callJNIShortMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jint callJNIIntMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jlong callJNILongMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jfloat callJNIFloatMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-jdouble callJNIDoubleMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
-
-JavaVM *getJavaVM();
-void setJavaVM(JavaVM *javaVM);
-JNIEnv *getJNIEnv();
-
-bool dispatchJNICall(const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char *callingURL, JSValue *&exceptionDescription);
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // ENABLE(JAVA_BINDINGS)
-
-#endif // _JNI_UTILITY_H_
+++ /dev/null
-cc -g -o testbindingsM testbindings.mm -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
-cc -g -o testbindingsC testbindings.cpp -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
+++ /dev/null
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
- /*
- * Netscape client plug-in API spec
- */
-
-
-#ifndef _NPAPI_H_
-#define _NPAPI_H_
-
-#include <wtf/Platform.h>
-
-#if ENABLE(NETSCAPE_API)
-
-#ifdef INCLUDE_JAVA
-#include "jri.h" /* Java Runtime Interface */
-#else
-#define jref void *
-#define JRIEnv void
-#endif
-
-#ifdef _WIN32
-# ifndef XP_WIN
-# define XP_WIN 1
-# endif /* XP_WIN */
-#endif /* _WIN32 */
-
-#ifdef __MWERKS__
-# define _declspec __declspec
-# ifdef macintosh
-# ifndef XP_MAC
-# define XP_MAC 1
-# endif /* XP_MAC */
-# endif /* macintosh */
-# ifdef __INTEL__
-# undef NULL
-# ifndef XP_WIN
-# define XP_WIN 1
-# endif /* __INTEL__ */
-# endif /* XP_PC */
-#endif /* __MWERKS__ */
-
-#if defined(__APPLE_CC__) && !defined(__MACOS_CLASSIC__) && !defined(XP_UNIX)
-# define XP_MACOSX
-#endif
-
-#ifdef XP_MAC
- #include <Quickdraw.h>
- #include <Events.h>
-#endif
-
-#ifdef XP_MACOSX
- #include <Carbon/Carbon.h>
- #include <ApplicationServices/ApplicationServices.h>
- #include <OpenGL/OpenGL.h>
-#endif
-
-#ifdef XP_UNIX
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <stdio.h>
-#endif
-
-#ifdef XP_WIN
- #include <windows.h>
-#endif
-
-#if defined(XP_MACOSX) && defined(__LP64__)
-#error 64-bit Netscape plug-ins are not supported on Mac OS X
-#endif
-
-/*----------------------------------------------------------------------*/
-/* Plugin Version Constants */
-/*----------------------------------------------------------------------*/
-
-#define NP_VERSION_MAJOR 0
-#define NP_VERSION_MINOR 18
-
-
-
-/*----------------------------------------------------------------------*/
-/* Definition of Basic Types */
-/*----------------------------------------------------------------------*/
-
-#ifndef _UINT16
-#define _UINT16
-typedef unsigned short uint16;
-#endif
-
-#ifndef _UINT32
-#define _UINT32
-#ifdef __LP64__
-typedef unsigned int uint32;
-#else /* __LP64__ */
-typedef unsigned long uint32;
-#endif /* __LP64__ */
-#endif
-
-#ifndef _INT16
-#define _INT16
-typedef short int16;
-#endif
-
-#ifndef _INT32
-#define _INT32
-#ifdef __LP64__
-typedef int int32;
-#else /* __LP64__ */
-typedef long int32;
-#endif /* __LP64__ */
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-#ifndef TRUE
-#define TRUE (1)
-#endif
-#ifndef NULL
-#define NULL (0L)
-#endif
-
-typedef unsigned char NPBool;
-typedef int16 NPError;
-typedef int16 NPReason;
-typedef char* NPMIMEType;
-
-
-
-/*----------------------------------------------------------------------*/
-/* Structures and definitions */
-/*----------------------------------------------------------------------*/
-
-#if !defined(__LP64__)
-#if defined(XP_MAC) || defined(XP_MACOSX)
-#pragma options align=mac68k
-#endif
-#endif /* __LP64__ */
-
-/*
- * NPP is a plug-in's opaque instance handle
- */
-typedef struct _NPP
-{
- void* pdata; /* plug-in private data */
- void* ndata; /* netscape private data */
-} NPP_t;
-
-typedef NPP_t* NPP;
-
-
-typedef struct _NPStream
-{
- void* pdata; /* plug-in private data */
- void* ndata; /* netscape private data */
- const char* url;
- uint32 end;
- uint32 lastmodified;
- void* notifyData;
- const char* headers; /* Response headers from host.
- * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
- * Used for HTTP only; NULL for non-HTTP.
- * Available from NPP_NewStream onwards.
- * Plugin should copy this data before storing it.
- * Includes HTTP status line and all headers,
- * preferably verbatim as received from server,
- * headers formatted as in HTTP ("Header: Value"),
- * and newlines (\n, NOT \r\n) separating lines.
- * Terminated by \n\0 (NOT \n\n\0). */
-} NPStream;
-
-
-typedef struct _NPByteRange
-{
- int32 offset; /* negative offset means from the end */
- uint32 length;
- struct _NPByteRange* next;
-} NPByteRange;
-
-
-typedef struct _NPSavedData
-{
- int32 len;
- void* buf;
-} NPSavedData;
-
-
-typedef struct _NPRect
-{
- uint16 top;
- uint16 left;
- uint16 bottom;
- uint16 right;
-} NPRect;
-
-
-#ifdef XP_UNIX
-/*
- * Unix specific structures and definitions
- */
-
-/*
- * Callback Structures.
- *
- * These are used to pass additional platform specific information.
- */
-enum {
- NP_SETWINDOW = 1,
- NP_PRINT
-};
-
-typedef struct
-{
- int32 type;
-} NPAnyCallbackStruct;
-
-typedef struct
-{
- int32 type;
- Display* display;
- Visual* visual;
- Colormap colormap;
- unsigned int depth;
-} NPSetWindowCallbackStruct;
-
-typedef struct
-{
- int32 type;
- FILE* fp;
-} NPPrintCallbackStruct;
-
-#endif /* XP_UNIX */
-
-/*
- * The following masks are applied on certain platforms to NPNV and
- * NPPV selectors that pass around pointers to COM interfaces. Newer
- * compilers on some platforms may generate vtables that are not
- * compatible with older compilers. To prevent older plugins from
- * not understanding a new browser's ABI, these masks change the
- * values of those selectors on those platforms. To remain backwards
- * compatible with differenet versions of the browser, plugins can
- * use these masks to dynamically determine and use the correct C++
- * ABI that the browser is expecting. This does not apply to Windows
- * as Microsoft's COM ABI will likely not change.
- */
-
-#define NP_ABI_GCC3_MASK 0x10000000
-/*
- * gcc 3.x generated vtables on UNIX and OSX are incompatible with
- * previous compilers.
- */
-#if (defined (XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
-#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
-#else
-#define _NP_ABI_MIXIN_FOR_GCC3 0
-#endif
-
-#define NP_ABI_MACHO_MASK 0x01000000
-/*
- * On OSX, the Mach-O executable format is significantly
- * different than CFM. In addition to having a different
- * C++ ABI, it also has has different C calling convention.
- * You must use glue code when calling between CFM and
- * Mach-O C functions.
- */
-#if (defined(TARGET_RT_MAC_MACHO))
-#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
-#else
-#define _NP_ABI_MIXIN_FOR_MACHO 0
-#endif
-
-
-#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
-
-/*
- * List of variable names for which NPP_GetValue shall be implemented
- */
-typedef enum {
- NPPVpluginNameString = 1,
- NPPVpluginDescriptionString,
- NPPVpluginWindowBool,
- NPPVpluginTransparentBool,
-
- NPPVjavaClass, /* Not implemented in WebKit */
- NPPVpluginWindowSize, /* Not implemented in WebKit */
- NPPVpluginTimerInterval, /* Not implemented in WebKit */
-
- NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
- NPPVpluginScriptableIID = 11, /* Not implemented in WebKit */
-
- /* 12 and over are available on Mozilla builds starting with 0.9.9 */
- NPPVjavascriptPushCallerBool = 12, /* Not implemented in WebKit */
- NPPVpluginKeepLibraryInMemory = 13, /* Not implemented in WebKit */
- NPPVpluginNeedsXEmbed = 14, /* Not implemented in WebKit */
-
- /* Get the NPObject for scripting the plugin. */
- NPPVpluginScriptableNPObject = 15,
-
- /* Get the plugin value (as \0-terminated UTF-8 string data) for
- * form submission if the plugin is part of a form. Use
- * NPN_MemAlloc() to allocate memory for the string data.
- */
- NPPVformValue = 16, /* Not implemented in WebKit */
-#ifdef XP_MACOSX
- /* Used for negotiating drawing models */
- NPPVpluginDrawingModel = 1000
-#endif
-} NPPVariable;
-
-/*
- * List of variable names for which NPN_GetValue is implemented by Mozilla
- */
-typedef enum {
- NPNVxDisplay = 1,
- NPNVxtAppContext,
- NPNVnetscapeWindow,
- NPNVjavascriptEnabledBool,
- NPNVasdEnabledBool,
- NPNVisOfflineBool,
-
- /* 10 and over are available on Mozilla builds starting with 0.9.4 */
- NPNVserviceManager = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
- NPNVDOMElement = (11 | NP_ABI_MASK), /* Not implemented in WebKit */
- NPNVDOMWindow = (12 | NP_ABI_MASK), /* Not implemented in WebKit */
- NPNVToolkit = (13 | NP_ABI_MASK), /* Not implemented in WebKit */
- NPNVSupportsXEmbedBool = 14, /* Not implemented in WebKit */
-
- /* Get the NPObject wrapper for the browser window. */
- NPNVWindowNPObject = 15,
-
- /* Get the NPObject wrapper for the plugins DOM element. */
- NPNVPluginElementNPObject
-
-#ifdef XP_MACOSX
- , NPNVpluginDrawingModel = 1000 /* The NPDrawingModel specified by the plugin */
-
-#ifndef NP_NO_QUICKDRAW
- , NPNVsupportsQuickDrawBool = 2000 /* TRUE if the browser supports the QuickDraw drawing model */
-#endif
- , NPNVsupportsCoreGraphicsBool = 2001 /* TRUE if the browser supports the CoreGraphics drawing model */
- , NPNVsupportsOpenGLBool = 2002 /* TRUE if the browser supports the OpenGL drawing model (CGL on Mac) */
-#endif /* XP_MACOSX */
-} NPNVariable;
-
-/*
- * The type of a NPWindow - it specifies the type of the data structure
- * returned in the window field.
- */
-typedef enum {
- NPWindowTypeWindow = 1,
- NPWindowTypeDrawable
-} NPWindowType;
-
-#ifdef XP_MACOSX
-
-/*
- * The drawing model for a Mac OS X plugin. These are the possible values for the NPNVpluginDrawingModel variable.
- */
-
-typedef enum {
-#ifndef NP_NO_QUICKDRAW
- NPDrawingModelQuickDraw = 0,
-#endif
- NPDrawingModelCoreGraphics = 1,
- NPDrawingModelOpenGL = 2
-} NPDrawingModel;
-
-#endif
-
-typedef struct _NPWindow
-{
- void* window; /* Platform specific window handle */
- int32 x; /* Position of top left corner relative */
- int32 y; /* to a netscape page. */
- uint32 width; /* Maximum window size */
- uint32 height;
- NPRect clipRect; /* Clipping rectangle in port coordinates */
- /* Used by MAC only. */
-#ifdef XP_UNIX
- void * ws_info; /* Platform-dependent additonal data */
-#endif /* XP_UNIX */
- NPWindowType type; /* Is this a window or a drawable? */
-} NPWindow;
-
-
-typedef struct _NPFullPrint
-{
- NPBool pluginPrinted; /* Set TRUE if plugin handled fullscreen */
- /* printing */
- NPBool printOne; /* TRUE if plugin should print one copy */
- /* to default printer */
- void* platformPrint; /* Platform-specific printing info */
-} NPFullPrint;
-
-typedef struct _NPEmbedPrint
-{
- NPWindow window;
- void* platformPrint; /* Platform-specific printing info */
-} NPEmbedPrint;
-
-typedef struct _NPPrint
-{
- uint16 mode; /* NP_FULL or NP_EMBED */
- union
- {
- NPFullPrint fullPrint; /* if mode is NP_FULL */
- NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
- } print;
-} NPPrint;
-
-#if defined(XP_MAC) || defined(XP_MACOSX)
-typedef EventRecord NPEvent;
-#elif defined(XP_WIN)
-typedef struct _NPEvent
-{
- uint16 event;
- uint32 wParam;
- uint32 lParam;
-} NPEvent;
-#elif defined (XP_UNIX)
-typedef XEvent NPEvent;
-#else
-typedef void* NPEvent;
-#endif /* XP_MAC */
-
-#if defined(XP_MAC)
-typedef RgnHandle NPRegion;
-#elif defined(XP_MACOSX)
-/*
- * NPRegion's type depends on the drawing model specified by the plugin (see NPNVpluginDrawingModel).
- * NPQDRegion represents a QuickDraw RgnHandle and is used with the QuickDraw drawing model.
- * NPCGRegion repesents a graphical region when using any other drawing model.
- */
-typedef void *NPRegion;
-#ifndef NP_NO_QUICKDRAW
-typedef RgnHandle NPQDRegion;
-#endif
-typedef CGPathRef NPCGRegion;
-#elif defined(XP_WIN)
-typedef HRGN NPRegion;
-#elif defined(XP_UNIX)
-typedef Region NPRegion;
-#else
-typedef void *NPRegion;
-#endif /* XP_MAC */
-
-#ifdef XP_MACOSX
-
-/*
- * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
- * as its drawing model.
- */
-
-typedef struct NP_CGContext
-{
- CGContextRef context;
- WindowRef window;
-} NP_CGContext;
-
-/*
- * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
- * drawing model.
- */
-
-typedef struct NP_GLContext
-{
- CGLContextObj context;
- WindowRef window;
-} NP_GLContext;
-
-#endif /* XP_MACOSX */
-
-#if defined(XP_MAC) || defined(XP_MACOSX)
-
-/*
- * Mac-specific structures and definitions.
- */
-
-#ifndef NP_NO_QUICKDRAW
-
-/*
- * NP_Port is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelQuickDraw as its
- * drawing model, or the plugin does not specify a drawing model.
- *
- * It is not recommended that new plugins use NPDrawingModelQuickDraw or NP_Port, as QuickDraw has been
- * deprecated in Mac OS X 10.5. CoreGraphics is the preferred drawing API.
- *
- * NP_Port is not available in 64-bit.
- */
-
-typedef struct NP_Port
-{
- CGrafPtr port; /* Grafport */
- int32 portx; /* position inside the topmost window */
- int32 porty;
-} NP_Port;
-
-#endif /* NP_NO_QUICKDRAW */
-
-/*
- * Non-standard event types that can be passed to HandleEvent
- */
-#define getFocusEvent (osEvt + 16)
-#define loseFocusEvent (osEvt + 17)
-#define adjustCursorEvent (osEvt + 18)
-
-#endif /* XP_MAC */
-
-
-/*
- * Values for mode passed to NPP_New:
- */
-#define NP_EMBED 1
-#define NP_FULL 2
-
-/*
- * Values for stream type passed to NPP_NewStream:
- */
-#define NP_NORMAL 1
-#define NP_SEEK 2
-#define NP_ASFILE 3
-#define NP_ASFILEONLY 4
-
-#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
-
-#if !defined(__LP64__)
-#if defined(XP_MAC) || defined(XP_MACOSX)
-#pragma options align=reset
-#endif
-#endif /* __LP64__ */
-
-
-/*----------------------------------------------------------------------*/
-/* Error and Reason Code definitions */
-/*----------------------------------------------------------------------*/
-
-/*
- * Values of type NPError:
- */
-#define NPERR_BASE 0
-#define NPERR_NO_ERROR (NPERR_BASE + 0)
-#define NPERR_GENERIC_ERROR (NPERR_BASE + 1)
-#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2)
-#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3)
-#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4)
-#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5)
-#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6)
-#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7)
-#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8)
-#define NPERR_INVALID_PARAM (NPERR_BASE + 9)
-#define NPERR_INVALID_URL (NPERR_BASE + 10)
-#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11)
-#define NPERR_NO_DATA (NPERR_BASE + 12)
-#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13)
-
-/*
- * Values of type NPReason:
- */
-#define NPRES_BASE 0
-#define NPRES_DONE (NPRES_BASE + 0)
-#define NPRES_NETWORK_ERR (NPRES_BASE + 1)
-#define NPRES_USER_BREAK (NPRES_BASE + 2)
-
-/*
- * Don't use these obsolete error codes any more.
- */
-#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
-#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
-#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
-
-/*
- * Version feature information
- */
-#define NPVERS_HAS_STREAMOUTPUT 8
-#define NPVERS_HAS_NOTIFICATION 9
-#define NPVERS_HAS_LIVECONNECT 9
-#define NPVERS_WIN16_HAS_LIVECONNECT 9
-#define NPVERS_68K_HAS_LIVECONNECT 11
-#define NPVERS_HAS_WINDOWLESS 11
-#define NPVERS_HAS_XPCONNECT_SCRIPTING 13 /* Not implemented in WebKit */
-#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
-#define NPVERS_HAS_FORM_VALUES 15 /* Not implemented in WebKit; see bug 13061 */
-#define NPVERS_HAS_POPUPS_ENABLED_STATE 16 /* Not implemented in WebKit */
-#define NPVERS_HAS_RESPONSE_HEADERS 17
-#define NPVERS_HAS_NPOBJECT_ENUM 18
-
-
-/*----------------------------------------------------------------------*/
-/* Function Prototypes */
-/*----------------------------------------------------------------------*/
-
-#if defined(_WINDOWS) && !defined(WIN32)
-#define NP_LOADDS _loadds
-#else
-#define NP_LOADDS
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * NPP_* functions are provided by the plugin and called by the navigator.
- */
-
-#ifdef XP_UNIX
-char* NPP_GetMIMEDescription(void);
-#endif /* XP_UNIX */
-
-NPError NPP_Initialize(void);
-void NPP_Shutdown(void);
-NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
- uint16 mode, int16 argc, char* argn[],
- char* argv[], NPSavedData* saved);
-NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
-NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
-NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
- NPStream* stream, NPBool seekable,
- uint16* stype);
-NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
- NPReason reason);
-int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
-int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset,
- int32 len, void* buffer);
-void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
- const char* fname);
-void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
-int16 NPP_HandleEvent(NPP instance, void* event);
-void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
- NPReason reason, void* notifyData);
-jref NP_LOADDS NPP_GetJavaClass(void);
-NPError NPP_GetValue(NPP instance, NPPVariable variable,
- void *value);
-NPError NPP_SetValue(NPP instance, NPNVariable variable,
- void *value);
-
-/*
- * NPN_* functions are provided by the navigator and called by the plugin.
- */
-
-void NPN_Version(int* plugin_major, int* plugin_minor,
- int* netscape_major, int* netscape_minor);
-NPError NPN_GetURLNotify(NPP instance, const char* url,
- const char* target, void* notifyData);
-NPError NPN_GetURL(NPP instance, const char* url,
- const char* target);
-NPError NPN_PostURLNotify(NPP instance, const char* url,
- const char* target, uint32 len,
- const char* buf, NPBool file,
- void* notifyData);
-NPError NPN_PostURL(NPP instance, const char* url,
- const char* target, uint32 len,
- const char* buf, NPBool file);
-NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
-NPError NPN_NewStream(NPP instance, NPMIMEType type,
- const char* target, NPStream** stream);
-int32 NPN_Write(NPP instance, NPStream* stream, int32 len,
- void* buffer);
-NPError NPN_DestroyStream(NPP instance, NPStream* stream,
- NPReason reason);
-void NPN_Status(NPP instance, const char* message);
-const char* NPN_UserAgent(NPP instance);
-void* NPN_MemAlloc(uint32 size);
-void NPN_MemFree(void* ptr);
-uint32 NPN_MemFlush(uint32 size);
-void NPN_ReloadPlugins(NPBool reloadPages);
-JRIEnv* NPN_GetJavaEnv(void);
-jref NPN_GetJavaPeer(NPP instance);
-NPError NPN_GetValue(NPP instance, NPNVariable variable,
- void *value);
-NPError NPN_SetValue(NPP instance, NPPVariable variable,
- void *value);
-void NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
-void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
-void NPN_ForceRedraw(NPP instance);
-void NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
-void NPN_PopPopupsEnabledState(NPP instance);
-
-#ifdef __cplusplus
-} /* end extern "C" */
-#endif
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif /* _NPAPI_H_ */
+++ /dev/null
-/*
- * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-#include "npruntime_impl.h"
-#include "npruntime_priv.h"
-
-#include "JSLock.h"
-#include "c_utility.h"
-#include "identifier.h"
-#include <wtf/Assertions.h>
-#include <wtf/HashMap.h>
-
-using namespace KJS::Bindings;
-
-typedef HashMap<RefPtr<KJS::UString::Rep>, PrivateIdentifier*> StringIdentifierMap;
-
-static StringIdentifierMap* getStringIdentifierMap()
-{
- static StringIdentifierMap* stringIdentifierMap = 0;
- if (!stringIdentifierMap)
- stringIdentifierMap = new StringIdentifierMap;
- return stringIdentifierMap;
-}
-
-typedef HashMap<int, PrivateIdentifier*> IntIdentifierMap;
-
-static IntIdentifierMap* getIntIdentifierMap()
-{
- static IntIdentifierMap* intIdentifierMap = 0;
- if (!intIdentifierMap)
- intIdentifierMap = new IntIdentifierMap;
- return intIdentifierMap;
-}
-
-NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
-{
- ASSERT(name);
-
- if (name) {
- PrivateIdentifier* identifier = 0;
-
- KJS::JSLock lock;
-
- identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep());
- if (identifier == 0) {
- identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
- // We never release identifier names, so this dictionary will grow, as will
- // the memory for the identifier name strings.
- identifier->isString = true;
- identifier->value.string = strdup(name);
-
- getStringIdentifierMap()->set(identifierFromNPIdentifier(name).ustring().rep(), identifier);
- }
- return (NPIdentifier)identifier;
- }
-
- return 0;
-}
-
-void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
-{
- ASSERT(names);
- ASSERT(identifiers);
-
- if (names && identifiers)
- for (int i = 0; i < nameCount; i++)
- identifiers[i] = _NPN_GetStringIdentifier(names[i]);
-}
-
-NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
-{
- PrivateIdentifier* identifier;
-
- if (intid == 0 || intid == -1) {
- static PrivateIdentifier* negativeOneAndZeroIdentifiers[2];
-
- identifier = negativeOneAndZeroIdentifiers[intid + 1];
- if (!identifier) {
- identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
- identifier->isString = false;
- identifier->value.number = intid;
-
- negativeOneAndZeroIdentifiers[intid + 1] = identifier;
- }
- } else {
- identifier = getIntIdentifierMap()->get(intid);
- if (!identifier) {
- identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
- // We never release identifier names, so this dictionary will grow.
- identifier->isString = false;
- identifier->value.number = intid;
-
- getIntIdentifierMap()->set(intid, identifier);
- }
- }
- return (NPIdentifier)identifier;
-}
-
-bool _NPN_IdentifierIsString(NPIdentifier identifier)
-{
- PrivateIdentifier* i = (PrivateIdentifier*)identifier;
- return i->isString;
-}
-
-NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier)
-{
- PrivateIdentifier* i = (PrivateIdentifier*)identifier;
- if (!i->isString || !i->value.string)
- return NULL;
-
- return (NPUTF8 *)strdup(i->value.string);
-}
-
-int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
-{
- PrivateIdentifier* i = (PrivateIdentifier*)identifier;
- if (!i->isString)
- return 0;
- return i->value.number;
-}
-
-void NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
-{
- variant->type = NPVariantType_String;
- variant->value.stringValue.UTF8Length = value->UTF8Length;
- variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
- memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
-}
-
-void _NPN_ReleaseVariantValue(NPVariant* variant)
-{
- ASSERT(variant);
-
- if (variant->type == NPVariantType_Object) {
- _NPN_ReleaseObject(variant->value.objectValue);
- variant->value.objectValue = 0;
- } else if (variant->type == NPVariantType_String) {
- free((void*)variant->value.stringValue.UTF8Characters);
- variant->value.stringValue.UTF8Characters = 0;
- variant->value.stringValue.UTF8Length = 0;
- }
-
- variant->type = NPVariantType_Void;
-}
-
-NPObject *_NPN_CreateObject(NPP npp, NPClass* aClass)
-{
- ASSERT(aClass);
-
- if (aClass) {
- NPObject* obj;
- if (aClass->allocate != NULL)
- obj = aClass->allocate(npp, aClass);
- else
- obj = (NPObject*)malloc(sizeof(NPObject));
-
- obj->_class = aClass;
- obj->referenceCount = 1;
-
- return obj;
- }
-
- return 0;
-}
-
-NPObject* _NPN_RetainObject(NPObject* obj)
-{
- ASSERT(obj);
-
- if (obj)
- obj->referenceCount++;
-
- return obj;
-}
-
-void _NPN_ReleaseObject(NPObject* obj)
-{
- ASSERT(obj);
- ASSERT(obj->referenceCount >= 1);
-
- if (obj && obj->referenceCount >= 1) {
- if (--obj->referenceCount == 0)
- _NPN_DeallocateObject(obj);
- }
-}
-
-void _NPN_DeallocateObject(NPObject *obj)
-{
- ASSERT(obj);
-
- if (obj) {
- if (obj->_class->deallocate)
- obj->_class->deallocate(obj);
- else
- free(obj);
- }
-}
-
-#endif // ENABLE(NETSCAPE_API)
+++ /dev/null
-/*
- * Copyright (C) 2004, Apple Computer, Inc. and The Mozilla Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
- * Foundation ("Mozilla") nor the names of their contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
- * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Revision 1 (March 4, 2004):
- * Initial proposal.
- *
- * Revision 2 (March 10, 2004):
- * All calls into script were made asynchronous. Results are
- * provided via the NPScriptResultFunctionPtr callback.
- *
- * Revision 3 (March 10, 2004):
- * Corrected comments to not refer to class retain/release FunctionPtrs.
- *
- * Revision 4 (March 11, 2004):
- * Added additional convenience NPN_SetExceptionWithUTF8().
- * Changed NPHasPropertyFunctionPtr and NPHasMethodFunctionPtr to take NPClass
- * pointers instead of NPObject pointers.
- * Added NPIsValidIdentifier().
- *
- * Revision 5 (March 17, 2004):
- * Added context parameter to result callbacks from ScriptObject functions.
- *
- * Revision 6 (March 29, 2004):
- * Renamed functions implemented by user agent to NPN_*. Removed _ from
- * type names.
- * Renamed "JavaScript" types to "Script".
- *
- * Revision 7 (April 21, 2004):
- * NPIdentifier becomes a void*, was int32_t
- * Remove NP_IsValidIdentifier, renamed NP_IdentifierFromUTF8 to NP_GetIdentifier
- * Added NPVariant and modified functions to use this new type.
- *
- * Revision 8 (July 9, 2004):
- * Updated to joint Apple-Mozilla license.
- *
- * Revision 9 (August 12, 2004):
- * Changed NPVariantType enum values to form PVariantType_XXX
- * Added NPP arguments to NPObject functions.
- * Replaced NPVariant functions with macros.
- */
-#ifndef _NP_RUNTIME_H_
-#define _NP_RUNTIME_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include "npapi.h"
-
-#if defined(XP_MACOSX) && defined(__LP64__)
-#error 64-bit Netscape plug-ins are not supported on Mac OS X
-#endif
-
-/*
- This API is used to facilitate binding code written in C to script
- objects. The API in this header does not assume the presence of a
- user agent. That is, it can be used to bind C code to scripting
- environments outside of the context of a user agent.
-
- However, the normal use of the this API is in the context of a
- scripting environment running in a browser or other user agent.
- In particular it is used to support the extended Netscape
- script-ability API for plugins (NP-SAP). NP-SAP is an extension
- of the Netscape plugin API. As such we have adopted the use of
- the "NP" prefix for this API.
-
- The following NP{N|P}Variables were added to the Netscape plugin
- API (in npapi.h):
-
- NPNVWindowNPObject
- NPNVPluginElementNPObject
- NPPVpluginScriptableNPObject
-
- These variables are exposed through NPN_GetValue() and
- NPP_GetValue() (respectively) and are used to establish the
- initial binding between the user agent and native code. The DOM
- objects in the user agent can be examined and manipulated using
- the NPN_ functions that operate on NPObjects described in this
- header.
-
- To the extent possible the assumptions about the scripting
- language used by the scripting environment have been minimized.
-*/
-
-
-/*
- Objects (non-primitive data) passed between 'C' and script is
- always wrapped in an NPObject. The 'interface' of an NPObject is
- described by an NPClass.
-*/
-typedef struct NPObject NPObject;
-typedef struct NPClass NPClass;
-
-typedef char NPUTF8;
-typedef struct _NPString {
- const NPUTF8 *UTF8Characters;
- uint32_t UTF8Length;
-} NPString;
-
-typedef enum {
- NPVariantType_Void,
- NPVariantType_Null,
- NPVariantType_Bool,
- NPVariantType_Int32,
- NPVariantType_Double,
- NPVariantType_String,
- NPVariantType_Object
-} NPVariantType;
-
-typedef struct _NPVariant {
- NPVariantType type;
- union {
- bool boolValue;
- int32_t intValue;
- double doubleValue;
- NPString stringValue;
- NPObject *objectValue;
- } value;
-} NPVariant;
-
-/*
- NPN_ReleaseVariantValue is called on all 'out' parameters references.
- Specifically it is called on variants that are resultant out parameters
- in NPGetPropertyFunctionPtr and NPInvokeFunctionPtr. Resultant variants
- from these two functions should be initialized using the
- NPN_InitializeVariantXXX() functions.
-
- After calling NPReleaseVariantValue, the type of the variant will
- be set to NPVariantUndefinedType.
-*/
-void NPN_ReleaseVariantValue (NPVariant *variant);
-
-#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void)
-#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null)
-#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
-#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32)
-#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double)
-#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String)
-#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object)
-
-#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
-#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue)
-#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue)
-#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue)
-#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue)
-
-#define NP_BEGIN_MACRO do {
-#define NP_END_MACRO } while (0)
-
-#define VOID_TO_NPVARIANT(_v) NP_BEGIN_MACRO (_v).type = NPVariantType_Void; (_v).value.objectValue = NULL; NP_END_MACRO
-#define NULL_TO_NPVARIANT(_v) NP_BEGIN_MACRO (_v).type = NPVariantType_Null; (_v).value.objectValue = NULL; NP_END_MACRO
-#define BOOLEAN_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Bool; (_v).value.boolValue = !!(_val); NP_END_MACRO
-#define INT32_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Int32; (_v).value.intValue = _val; NP_END_MACRO
-#define DOUBLE_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Double; (_v).value.doubleValue = _val; NP_END_MACRO
-#define STRINGZ_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, strlen(_val) }; (_v).value.stringValue = str; NP_END_MACRO
-#define STRINGN_TO_NPVARIANT(_val, _len, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, _len }; (_v).value.stringValue = str; NP_END_MACRO
-#define OBJECT_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Object; (_v).value.objectValue = _val; NP_END_MACRO
-
-/*
- Type mappings (JavaScript types have been used for illustration
- purposes):
-
- JavaScript to C (NPVariant with type:)
- undefined NPVariantType_Void
- null NPVariantType_Null
- Boolean NPVariantType_Bool
- Number NPVariantType_Double or NPVariantType_Int32
- String NPVariantType_String
- Object NPVariantType_Object
-
- C (NPVariant with type:) to JavaScript
- NPVariantType_Void undefined
- NPVariantType_Null null
- NPVariantType_Bool Boolean
- NPVariantType_Int32 Number
- NPVariantType_Double Number
- NPVariantType_String String
- NPVariantType_Object Object
-*/
-
-typedef void *NPIdentifier;
-
-/*
- NPObjects have methods and properties. Methods and properties are
- identified with NPIdentifiers. These identifiers may be reflected
- in script. NPIdentifiers can be either strings or integers, IOW,
- methods and properties can be identified by either strings or
- integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
- compared using ==. In case of any errors, the requested
- NPIdentifier(s) will be NULL.
-*/
-NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
-void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
-NPIdentifier NPN_GetIntIdentifier(int32_t intid);
-bool NPN_IdentifierIsString(NPIdentifier identifier);
-
-/*
- The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
-*/
-NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
-
-/*
- Get the integer represented by identifier. If identifier is not an
- integer identifier, the behaviour is undefined.
-*/
-int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
-
-/*
- NPObject behavior is implemented using the following set of
- callback functions.
-
- The NPVariant *result argument of these functions (where
- applicable) should be released using NPN_ReleaseVariantValue().
-*/
-typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
-typedef void (*NPDeallocateFunctionPtr)(NPObject *obj);
-typedef void (*NPInvalidateFunctionPtr)(NPObject *obj);
-typedef bool (*NPHasMethodFunctionPtr)(NPObject *obj, NPIdentifier name);
-typedef bool (*NPInvokeFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
-typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
-typedef bool (*NPHasPropertyFunctionPtr)(NPObject *obj, NPIdentifier name);
-typedef bool (*NPGetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, NPVariant *result);
-typedef bool (*NPSetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *value);
-typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
-typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, uint32_t *count);
-
-/*
- NPObjects returned by create have a reference count of one. It is the caller's responsibility
- to release the returned object.
-
- NPInvokeFunctionPtr function may return false to indicate a the method could not be invoked.
-
- NPGetPropertyFunctionPtr and NPSetPropertyFunctionPtr may return false to indicate a property doesn't
- exist.
-
- NPInvalidateFunctionPtr is called by the scripting environment when the native code is
- shutdown. Any attempt to message a NPObject instance after the invalidate
- callback has been called will result in undefined behavior, even if the
- native code is still retaining those NPObject instances.
- (The runtime will typically return immediately, with 0 or NULL, from an attempt to
- dispatch to a NPObject, but this behavior should not be depended upon.)
-
- The NPEnumerationFunctionPtr function may pass an array of
- NPIdentifiers back to the caller. The callee allocs the memory of
- the array using NPN_MemAlloc(), and it's the caller's responsibility
- to release it using NPN_MemFree().
-*/
-struct NPClass
-{
- uint32_t structVersion;
- NPAllocateFunctionPtr allocate;
- NPDeallocateFunctionPtr deallocate;
- NPInvalidateFunctionPtr invalidate;
- NPHasMethodFunctionPtr hasMethod;
- NPInvokeFunctionPtr invoke;
- NPInvokeDefaultFunctionPtr invokeDefault;
- NPHasPropertyFunctionPtr hasProperty;
- NPGetPropertyFunctionPtr getProperty;
- NPSetPropertyFunctionPtr setProperty;
- NPRemovePropertyFunctionPtr removeProperty;
- NPEnumerationFunctionPtr enumerate;
-};
-
-#define NP_CLASS_STRUCT_VERSION 2
-#define NP_CLASS_STRUCT_VERSION_ENUM 2
-#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
- ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
-
-struct NPObject {
- NPClass *_class;
- uint32_t referenceCount;
- // Additional space may be allocated here by types of NPObjects
-};
-
-/*
- If the class has an allocate function, NPN_CreateObject invokes that function,
- otherwise a NPObject is allocated and returned. If a class has an allocate
- function it is the responsibility of that implementation to set the initial retain
- count to 1.
-*/
-NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
-
-/*
- Increment the NPObject's reference count.
-*/
-NPObject *NPN_RetainObject (NPObject *obj);
-
-/*
- Decremented the NPObject's reference count. If the reference
- count goes to zero, the class's destroy function is invoke if
- specified, otherwise the object is freed directly.
-*/
-void NPN_ReleaseObject (NPObject *obj);
-
-/*
- Functions to access script objects represented by NPObject.
-
- Calls to script objects are synchronous. If a function returns a
- value, it will be supplied via the result NPVariant
- argument. Successful calls will return true, false will be
- returned in case of an error.
-
- Calls made from plugin code to script must be made from the thread
- on which the plugin was initialized.
-*/
-bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
-bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
-bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
-bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
-bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
-bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
-bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
-bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
-bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
-
-/*
- NPN_SetException may be called to trigger a script exception upon return
- from entry points into NPObjects.
-*/
-void NPN_SetException (NPObject *obj, const NPUTF8 *message);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _NP_RUNTIME_IMPL_H_
-#define _NP_RUNTIME_IMPL_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void _NPN_ReleaseVariantValue(NPVariant *variant);
-extern NPIdentifier _NPN_GetStringIdentifier(const NPUTF8 *name);
-extern void _NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
-extern NPIdentifier _NPN_GetIntIdentifier(int32_t intid);
-extern bool _NPN_IdentifierIsString(NPIdentifier identifier);
-extern NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier);
-extern int32_t _NPN_IntFromIdentifier(NPIdentifier identifier);
-extern NPObject *_NPN_CreateObject(NPP npp, NPClass *aClass);
-extern NPObject *_NPN_RetainObject(NPObject *obj);
-extern void _NPN_ReleaseObject(NPObject *obj);
-extern void _NPN_DeallocateObject(NPObject *obj);
-extern bool _NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
-extern bool _NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
-extern bool _NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
-extern bool _NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
-extern bool _NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
-extern bool _NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
-extern bool _NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
-extern bool _NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
-extern void _NPN_SetException(NPObject *obj, const NPUTF8 *message);
-extern bool _NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
-
-#ifdef __cplusplus
-} /* end extern "C" */
-#endif
-
-#endif // ENABLE(NETSCAPE_API)
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2007 Collabora, Ltd. 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * This is a internal include header for npapi.h
- *
- * Some of the #defines which are in X11 headers conflict with type and enum
- * names in JavaScriptCore and WebCore
- * This header #undefs those defines to fix the conflicts
- * If you need to include npapi.h or npruntime.h when building on X11,
- * include this file instead of the actual npapi.h or npruntime.h
- */
-
-#include "npruntime.h"
-
-#ifdef XP_UNIX
- #include <X11/Xresource.h>
-
- #undef None
- #undef Above
- #undef Below
- #undef Auto
- #undef Complex
- #undef Status
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef NP_RUNTIME_PRIV_H_
-#define NP_RUNTIME_PRIV_H_
-
-#if ENABLE(NETSCAPE_API)
-
-#include "npruntime_internal.h"
-
-/*
- NPN_InitializeVariantWithStringCopy() will copy string data. The string data
- will be deallocated by calls to NPReleaseVariantValue().
-*/
-void NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*);
-
-#endif // ENABLE(NETSCAPE_API)
-#endif
-
+++ /dev/null
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "internal.h"
-#include "runtime_root.h"
-
-@class WebUndefined;
-
-@protocol WebScriptObject
-+ (NSString *)webScriptNameForSelector:(SEL)aSelector;
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
-+ (NSString *)webScriptNameForKey:(const char *)name;
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
-
-+ (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:(KJS::Bindings::RootObject*)originRootObject rootObject:(KJS::Bindings::RootObject*)rootObject;
-- _initWithJSObject:(KJS::JSObject*)imp originRootObject:(PassRefPtr<KJS::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<KJS::Bindings::RootObject>)rootObject;
-- (KJS::JSObject *)_imp;
-@end
-
-@protocol WebUndefined
-+ (WebUndefined *)undefined;
-@end
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef KJS_BINDINGS_OBJC_CLASS_H
-#define KJS_BINDINGS_OBJC_CLASS_H
-
-#include <JavaScriptCore/objc_runtime.h>
-
-namespace KJS {
-namespace Bindings {
-
-class ObjcClass : public Class
-{
-protected:
- ObjcClass (ClassStructPtr aClass); // Use classForIsA to create an ObjcClass.
-
-public:
- // Return the cached ObjC of the specified name.
- static ObjcClass *classForIsA(ClassStructPtr);
-
- virtual const char *name() const;
-
- virtual MethodList methodsNamed(const Identifier&, Instance *instance) const;
- virtual Field *fieldNamed(const Identifier&, Instance *instance) const;
-
- virtual JSValue *fallbackObject(ExecState *exec, Instance *instance, const Identifier &propertyName);
-
- ClassStructPtr isa() { return _isa; }
-
-private:
- ClassStructPtr _isa;
- RetainPtr<CFMutableDictionaryRef> _methods;
- RetainPtr<CFMutableDictionaryRef> _fields;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "objc_class.h"
-
-#include "objc_instance.h"
-#include "WebScriptObject.h"
-
-namespace KJS {
-namespace Bindings {
-
-static void deleteMethod(CFAllocatorRef, const void* value)
-{
- delete static_cast<const Method*>(value);
-}
-
-static void deleteField(CFAllocatorRef, const void* value)
-{
- delete static_cast<const Field*>(value);
-}
-
-const CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };
-const CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };
-
-ObjcClass::ObjcClass(ClassStructPtr aClass)
- : _isa(aClass)
- , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))
- , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks))
-{
-}
-
-static CFMutableDictionaryRef classesByIsA = 0;
-
-static void _createClassesByIsAIfNecessary()
-{
- if (!classesByIsA)
- classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-}
-
-ObjcClass* ObjcClass::classForIsA(ClassStructPtr isa)
-{
- _createClassesByIsAIfNecessary();
-
- ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);
- if (!aClass) {
- aClass = new ObjcClass(isa);
- CFDictionaryAddValue(classesByIsA, isa, aClass);
- }
-
- return aClass;
-}
-
-const char* ObjcClass::name() const
-{
- return object_getClassName(_isa);
-}
-
-MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
-{
- MethodList methodList;
- char fixedSizeBuffer[1024];
- char* buffer = fixedSizeBuffer;
- const char* JSName = identifier.ascii();
- if (!convertJSMethodNameToObjc(JSName, buffer, sizeof(fixedSizeBuffer))) {
- int length = strlen(JSName) + 1;
- buffer = new char[length];
- if (!buffer || !convertJSMethodNameToObjc(JSName, buffer, length))
- return methodList;
- }
-
-
- RetainPtr<CFStringRef> methodName(AdoptCF, CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII));
- Method* method = (Method*)CFDictionaryGetValue(_methods.get(), methodName.get());
- if (method) {
- methodList.append(method);
- return methodList;
- }
-
- ClassStructPtr thisClass = _isa;
- while (thisClass && methodList.isEmpty()) {
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- unsigned numMethodsInClass = 0;
- MethodStructPtr* objcMethodList = class_copyMethodList(thisClass, &numMethodsInClass);
-#else
- void* iterator = 0;
- struct objc_method_list* objcMethodList;
- while ((objcMethodList = class_nextMethodList(thisClass, &iterator))) {
- unsigned numMethodsInClass = objcMethodList->method_count;
-#endif
- for (unsigned i = 0; i < numMethodsInClass; i++) {
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- MethodStructPtr objcMethod = objcMethodList[i];
- SEL objcMethodSelector = method_getName(objcMethod);
-#else
- struct objc_method* objcMethod = &objcMethodList->method_list[i];
- SEL objcMethodSelector = objcMethod->method_name;
-#endif
- const char* objcMethodSelectorName = sel_getName(objcMethodSelector);
- NSString* mappedName = nil;
-
- // See if the class wants to exclude the selector from visibility in JavaScript.
- if ([thisClass respondsToSelector:@selector(isSelectorExcludedFromWebScript:)])
- if ([thisClass isSelectorExcludedFromWebScript:objcMethodSelector])
- continue;
-
- // See if the class want to provide a different name for the selector in JavaScript.
- // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
- // of the class.
- if ([thisClass respondsToSelector:@selector(webScriptNameForSelector:)])
- mappedName = [thisClass webScriptNameForSelector:objcMethodSelector];
-
- if ((mappedName && [mappedName isEqual:(NSString*)methodName.get()]) || strcmp(objcMethodSelectorName, buffer) == 0) {
- Method* aMethod = new ObjcMethod(thisClass, objcMethodSelectorName); // deleted when the dictionary is destroyed
- CFDictionaryAddValue(_methods.get(), methodName.get(), aMethod);
- methodList.append(aMethod);
- break;
- }
- }
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- thisClass = class_getSuperclass(thisClass);
- free(objcMethodList);
-#else
- }
- thisClass = thisClass->super_class;
-#endif
- }
-
- if (buffer != fixedSizeBuffer)
- delete [] buffer;
-
- return methodList;
-}
-
-Field* ObjcClass::fieldNamed(const Identifier& identifier, Instance* instance) const
-{
- ClassStructPtr thisClass = _isa;
-
- const char* name = identifier.ascii();
- RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII));
- Field* aField = (Field*)CFDictionaryGetValue(_fields.get(), fieldName.get());
- if (aField)
- return aField;
-
- id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();
- id attributes = [targetObject respondsToSelector:@selector(attributeKeys)] ? [targetObject performSelector:@selector(attributeKeys)] : nil;
- if (attributes) {
- // Class overrides attributeKeys, use that array of key names.
- unsigned count = [attributes count];
- for (unsigned i = 0; i < count; i++) {
- NSString* keyName = [attributes objectAtIndex:i];
- const char* UTF8KeyName = [keyName UTF8String]; // ObjC actually only supports ASCII names.
-
- // See if the class wants to exclude the selector from visibility in JavaScript.
- if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
- if ([thisClass isKeyExcludedFromWebScript:UTF8KeyName])
- continue;
-
- // See if the class want to provide a different name for the selector in JavaScript.
- // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
- // of the class.
- NSString* mappedName = nil;
- if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
- mappedName = [thisClass webScriptNameForKey:UTF8KeyName];
-
- if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || [keyName isEqual:(NSString*)fieldName.get()]) {
- aField = new ObjcField((CFStringRef)keyName); // deleted when the dictionary is destroyed
- CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
- break;
- }
- }
- } else {
- // Class doesn't override attributeKeys, so fall back on class runtime
- // introspection.
-
- while (thisClass) {
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- unsigned numFieldsInClass = 0;
- IvarStructPtr* ivarsInClass = class_copyIvarList(thisClass, &numFieldsInClass);
-#else
- struct objc_ivar_list* fieldsInClass = thisClass->ivars;
- if (fieldsInClass) {
- unsigned numFieldsInClass = fieldsInClass->ivar_count;
-#endif
- for (unsigned i = 0; i < numFieldsInClass; i++) {
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- IvarStructPtr objcIVar = ivarsInClass[i];
- const char* objcIvarName = ivar_getName(objcIVar);
-#else
- IvarStructPtr objcIVar = &fieldsInClass->ivar_list[i];
- const char* objcIvarName = objcIVar->ivar_name;
-#endif
- NSString* mappedName = 0;
-
- // See if the class wants to exclude the selector from visibility in JavaScript.
- if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
- if ([thisClass isKeyExcludedFromWebScript:objcIvarName])
- continue;
-
- // See if the class want to provide a different name for the selector in JavaScript.
- // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
- // of the class.
- if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
- mappedName = [thisClass webScriptNameForKey:objcIvarName];
-
- if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || strcmp(objcIvarName, name) == 0) {
- aField = new ObjcField(objcIVar); // deleted when the dictionary is destroyed
- CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
- break;
- }
- }
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- thisClass = class_getSuperclass(thisClass);
- free(ivarsInClass);
-#else
- }
- thisClass = thisClass->super_class;
-#endif
- }
- }
-
- return aField;
-}
-
-JSValue* ObjcClass::fallbackObject(ExecState*, Instance* instance, const Identifier &propertyName)
-{
- ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
- id targetObject = objcInstance->getObject();
-
- if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
- return jsUndefined();
- return new ObjcFallbackObjectImp(objcInstance, propertyName);
-}
-
-}
-}
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef KJS_BINDINGS_OBJC_HEADER_H
-#define KJS_BINDINGS_OBJC_HEADER_H
-
-#ifdef __OBJC__
-
-#include <objc/objc.h>
-#include <objc/objc-class.h>
-#include <objc/objc-runtime.h>
-
-typedef Class ClassStructPtr;
-typedef id ObjectStructPtr;
-typedef Method MethodStructPtr;
-typedef Ivar IvarStructPtr;
-
-@class NSMethodSignature;
-
-#else
-
-typedef struct objc_class* ClassStructPtr;
-typedef struct objc_object* ObjectStructPtr;
-typedef struct objc_method* MethodStructPtr;
-typedef struct objc_ivar* IvarStructPtr;
-
-class NSMethodSignature;
-
-#endif
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BINDINGS_OBJC_INSTANCE_H_
-#define BINDINGS_OBJC_INSTANCE_H_
-
-#include <JavaScriptCore/objc_class.h>
-#include <JavaScriptCore/objc_utility.h>
-
-namespace KJS {
-
-namespace Bindings {
-
-class ObjcClass;
-
-class ObjcInstance : public Instance {
-public:
- ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>);
-
- ~ObjcInstance();
-
- virtual Class *getClass() const;
-
- virtual void begin();
- virtual void end();
-
- virtual JSValue *valueOf() const;
- virtual JSValue *defaultValue(JSType hint) const;
-
- virtual bool implementsCall() const;
-
- virtual JSValue *invokeMethod(ExecState *exec, const MethodList &method, const List &args);
- virtual JSValue *invokeDefaultMethod(ExecState *exec, const List &args);
-
- virtual bool supportsSetValueOfUndefinedField();
- virtual void setValueOfUndefinedField(ExecState *exec, const Identifier &property, JSValue *aValue);
-
- virtual JSValue *getValueOfUndefinedField(ExecState *exec, const Identifier &property, JSType hint) const;
-
- ObjectStructPtr getObject() const { return _instance.get(); }
-
- JSValue *stringValue() const;
- JSValue *numberValue() const;
- JSValue *booleanValue() const;
-
- virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
-
-private:
- RetainPtr<ObjectStructPtr> _instance;
- mutable ObjcClass *_class;
- ObjectStructPtr _pool;
- int _beginCount;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // BINDINGS_OBJC_INSTANCE_H_
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "objc_instance.h"
-
-#import "WebScriptObject.h"
-#include <wtf/Assertions.h>
-
-#ifdef NDEBUG
-#define OBJC_LOG(formatAndArgs...) ((void)0)
-#else
-#define OBJC_LOG(formatAndArgs...) { \
- fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
- fprintf(stderr, formatAndArgs); \
-}
-#endif
-
-using namespace KJS::Bindings;
-using namespace KJS;
-
-ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject)
- : Instance(rootObject)
- , _instance(instance)
- , _class(0)
- , _pool(0)
- , _beginCount(0)
-{
-}
-
-ObjcInstance::~ObjcInstance()
-{
- begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
- if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
- [_instance.get() performSelector:@selector(finalizeForWebScript)];
- _instance = 0;
- end();
-}
-
-void ObjcInstance::begin()
-{
- if (!_pool)
- _pool = [[NSAutoreleasePool alloc] init];
- _beginCount++;
-}
-
-void ObjcInstance::end()
-{
- _beginCount--;
- ASSERT(_beginCount >= 0);
- if (!_beginCount) {
- [_pool drain];
- _pool = 0;
- }
-}
-
-Bindings::Class* ObjcInstance::getClass() const
-{
- if (!_instance)
- return 0;
- if (!_class)
- _class = ObjcClass::classForIsA(_instance->isa);
- return static_cast<Bindings::Class*>(_class);
-}
-
-bool ObjcInstance::implementsCall() const
-{
- return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
-}
-
-JSValue* ObjcInstance::invokeMethod(ExecState* exec, const MethodList &methodList, const List &args)
-{
- JSValue* result = jsUndefined();
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
- // Overloading methods is not allowed in ObjectiveC. Should only be one
- // name match for a particular method.
- ASSERT(methodList.size() == 1);
-
-@try {
- ObjcMethod* method = 0;
- method = static_cast<ObjcMethod*>(methodList[0]);
- NSMethodSignature* signature = method->getMethodSignature();
- NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- [invocation setSelector:sel_registerName(method->name())];
-#else
- [invocation setSelector:(SEL)method->name()];
-#endif
- [invocation setTarget:_instance.get()];
-
- if (method->isFallbackMethod()) {
- if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
- NSLog(@"Incorrect signature for invokeUndefinedMethodFromWebScript:withArguments: -- return type must be object.");
- return result;
- }
-
- // Invoke invokeUndefinedMethodFromWebScript:withArguments:, pass JavaScript function
- // name as first (actually at 2) argument and array of args as second.
- NSString* jsName = (NSString* )method->javaScriptName();
- [invocation setArgument:&jsName atIndex:2];
-
- NSMutableArray* objcArgs = [NSMutableArray array];
- int count = args.size();
- for (int i = 0; i < count; i++) {
- ObjcValue value = convertValueToObjcValue(exec, args.at(i), ObjcObjectType);
- [objcArgs addObject:value.objectValue];
- }
- [invocation setArgument:&objcArgs atIndex:3];
- } else {
- unsigned count = [signature numberOfArguments];
- for (unsigned i = 2; i < count ; i++) {
- const char* type = [signature getArgumentTypeAtIndex:i];
- ObjcValueType objcValueType = objcValueTypeForType(type);
-
- // Must have a valid argument type. This method signature should have
- // been filtered already to ensure that it has acceptable argument
- // types.
- ASSERT(objcValueType != ObjcInvalidType && objcValueType != ObjcVoidType);
-
- ObjcValue value = convertValueToObjcValue(exec, args.at(i-2), objcValueType);
-
- switch (objcValueType) {
- case ObjcObjectType:
- [invocation setArgument:&value.objectValue atIndex:i];
- break;
- case ObjcCharType:
- case ObjcUnsignedCharType:
- [invocation setArgument:&value.charValue atIndex:i];
- break;
- case ObjcShortType:
- case ObjcUnsignedShortType:
- [invocation setArgument:&value.shortValue atIndex:i];
- break;
- case ObjcIntType:
- case ObjcUnsignedIntType:
- [invocation setArgument:&value.intValue atIndex:i];
- break;
- case ObjcLongType:
- case ObjcUnsignedLongType:
- [invocation setArgument:&value.longValue atIndex:i];
- break;
- case ObjcLongLongType:
- case ObjcUnsignedLongLongType:
- [invocation setArgument:&value.longLongValue atIndex:i];
- break;
- case ObjcFloatType:
- [invocation setArgument:&value.floatValue atIndex:i];
- break;
- case ObjcDoubleType:
- [invocation setArgument:&value.doubleValue atIndex:i];
- break;
- default:
- // Should never get here. Argument types are filtered (and
- // the assert above should have fired in the impossible case
- // of an invalid type anyway).
- fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)objcValueType);
- ASSERT(false);
- }
- }
- }
-
- [invocation invoke];
-
- // Get the return value type.
- const char* type = [signature methodReturnType];
- ObjcValueType objcValueType = objcValueTypeForType(type);
-
- // Must have a valid return type. This method signature should have
- // been filtered already to ensure that it have an acceptable return
- // type.
- ASSERT(objcValueType != ObjcInvalidType);
-
- // Get the return value and convert it to a JavaScript value. Length
- // of return value will never exceed the size of largest scalar
- // or a pointer.
- char buffer[1024];
- ASSERT([signature methodReturnLength] < 1024);
-
- if (*type != 'v') {
- [invocation getReturnValue:buffer];
- result = convertObjcValueToValue(exec, buffer, objcValueType, _rootObject.get());
- }
-} @catch(NSException* localException) {
-}
- return result;
-}
-
-JSValue* ObjcInstance::invokeDefaultMethod(ExecState* exec, const List &args)
-{
- JSValue* result = jsUndefined();
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
-@try {
- if (![_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)])
- return result;
-
- NSMethodSignature* signature = [_instance.get() methodSignatureForSelector:@selector(invokeDefaultMethodWithArguments:)];
- NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
- [invocation setSelector:@selector(invokeDefaultMethodWithArguments:)];
- [invocation setTarget:_instance.get()];
-
- if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
- NSLog(@"Incorrect signature for invokeDefaultMethodWithArguments: -- return type must be object.");
- return result;
- }
-
- NSMutableArray* objcArgs = [NSMutableArray array];
- unsigned count = args.size();
- for (unsigned i = 0; i < count; i++) {
- ObjcValue value = convertValueToObjcValue(exec, args.at(i), ObjcObjectType);
- [objcArgs addObject:value.objectValue];
- }
- [invocation setArgument:&objcArgs atIndex:2];
-
- [invocation invoke];
-
- // Get the return value type, should always be "@" because of
- // check above.
- const char* type = [signature methodReturnType];
- ObjcValueType objcValueType = objcValueTypeForType(type);
-
- // Get the return value and convert it to a JavaScript value. Length
- // of return value will never exceed the size of a pointer, so we're
- // OK with 32 here.
- char buffer[32];
- [invocation getReturnValue:buffer];
- result = convertObjcValueToValue(exec, buffer, objcValueType, _rootObject.get());
-} @catch(NSException* localException) {
-}
-
- return result;
-}
-
-bool ObjcInstance::supportsSetValueOfUndefinedField()
-{
- id targetObject = getObject();
- if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)])
- return true;
- return false;
-}
-
-void ObjcInstance::setValueOfUndefinedField(ExecState* exec, const Identifier &property, JSValue* aValue)
-{
- id targetObject = getObject();
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
- // This check is not really necessary because NSObject implements
- // setValue:forUndefinedKey:, and unfortnately the default implementation
- // throws an exception.
- if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
- ObjcValue objcValue = convertValueToObjcValue(exec, aValue, ObjcObjectType);
-
- @try {
- [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
- } @catch(NSException* localException) {
- // Do nothing. Class did not override valueForUndefinedKey:.
- }
- }
-}
-
-JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property, JSType) const
-{
- JSValue* result = jsUndefined();
-
- id targetObject = getObject();
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
- // This check is not really necessary because NSObject implements
- // valueForUndefinedKey:, and unfortnately the default implementation
- // throws an exception.
- if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
- @try {
- id objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
- result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, _rootObject.get());
- } @catch(NSException* localException) {
- // Do nothing. Class did not override valueForUndefinedKey:.
- }
- }
-
- return result;
-}
-
-JSValue* ObjcInstance::defaultValue(JSType hint) const
-{
- switch (hint) {
- case StringType:
- return stringValue();
- case NumberType:
- return numberValue();
- case BooleanType:
- return booleanValue();
- case UnspecifiedType:
- if ([_instance.get() isKindOfClass:[NSString class]])
- return stringValue();
- if ([_instance.get() isKindOfClass:[NSNumber class]])
- return numberValue();
- default:
- return valueOf();
- }
-}
-
-JSValue* ObjcInstance::stringValue() const
-{
- return convertNSStringToString([getObject() description]);
-}
-
-JSValue* ObjcInstance::numberValue() const
-{
- // FIXME: Implement something sensible
- return jsNumber(0);
-}
-
-JSValue* ObjcInstance::booleanValue() const
-{
- // FIXME: Implement something sensible
- return jsBoolean(false);
-}
-
-JSValue* ObjcInstance::valueOf() const
-{
- return stringValue();
-}
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef KJS_BINDINGS_OBJC_RUNTIME_H
-#define KJS_BINDINGS_OBJC_RUNTIME_H
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <JavaScriptCore/objc_header.h>
-#include <JavaScriptCore/object.h>
-#include <JavaScriptCore/runtime.h>
-
-#include <wtf/RetainPtr.h>
-
-namespace KJS {
-namespace Bindings {
-
-extern ClassStructPtr webScriptObjectClass();
-extern ClassStructPtr webUndefinedClass();
-
-class ObjcInstance;
-
-class ObjcField : public Field
-{
-public:
- ObjcField(IvarStructPtr ivar);
- ObjcField(CFStringRef name);
-
- virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
- virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
-
- virtual const char *name() const;
-
-private:
- IvarStructPtr _ivar;
- RetainPtr<CFStringRef> _name;
-};
-
-class ObjcMethod : public Method
-{
-public:
- ObjcMethod() : _objcClass(0), _selector(0), _javaScriptName(0) {}
- ObjcMethod(ClassStructPtr aClass, const char *_selector);
-
- virtual const char *name() const;
-
- virtual int numParameters() const;
-
- NSMethodSignature *getMethodSignature() const;
-
- bool isFallbackMethod() const { return strcmp(_selector, "invokeUndefinedMethodFromWebScript:withArguments:") == 0; }
- void setJavaScriptName(CFStringRef n) { _javaScriptName = n; }
- CFStringRef javaScriptName() const { return _javaScriptName.get(); }
-
-private:
- ClassStructPtr _objcClass;
- const char *_selector;
- RetainPtr<CFStringRef> _javaScriptName;
-};
-
-class ObjcArray : public Array
-{
-public:
- ObjcArray(ObjectStructPtr, PassRefPtr<RootObject>);
-
- virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const;
- virtual JSValue *valueAt(ExecState *exec, unsigned int index) const;
- virtual unsigned int getLength() const;
-
- ObjectStructPtr getObjcArray() const { return _array.get(); }
-
- static JSValue *convertObjcArrayToArray(ExecState *exec, ObjectStructPtr anObject);
-
-private:
- RetainPtr<ObjectStructPtr> _array;
-};
-
-class ObjcFallbackObjectImp : public JSObject {
-public:
- ObjcFallbackObjectImp(ObjcInstance *i, const Identifier propertyName);
-
- const ClassInfo *classInfo() const { return &info; }
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
- virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
- virtual bool implementsCall() const;
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
- virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
-
- virtual JSType type() const;
- virtual bool toBoolean(ExecState *exec) const;
-
-private:
- ObjcFallbackObjectImp(); // prevent default construction
-
- static const ClassInfo info;
-
- RefPtr<ObjcInstance> _instance;
- Identifier _item;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "objc_runtime.h"
-
-#include "objc_instance.h"
-#include "runtime_array.h"
-#include "runtime_object.h"
-#include "WebScriptObject.h"
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-extern ClassStructPtr KJS::Bindings::webScriptObjectClass()
-{
- static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
- return webScriptObjectClass;
-}
-
-extern ClassStructPtr KJS::Bindings::webUndefinedClass()
-{
- static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
- return webUndefinedClass;
-}
-
-// ---------------------- ObjcMethod ----------------------
-
-ObjcMethod::ObjcMethod(ClassStructPtr aClass, const char* name)
-{
- _objcClass = aClass;
- _selector = name; // Assume ObjC runtime keeps these around forever.
- _javaScriptName = 0;
-}
-
-const char* ObjcMethod::name() const
-{
- return _selector;
-}
-
-int ObjcMethod::numParameters() const
-{
- return [getMethodSignature() numberOfArguments] - 2;
-}
-
-NSMethodSignature* ObjcMethod::getMethodSignature() const
-{
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- return [_objcClass instanceMethodSignatureForSelector:sel_registerName(_selector)];
-#else
- return [_objcClass instanceMethodSignatureForSelector:(SEL)_selector];
-#endif
-}
-
-// ---------------------- ObjcField ----------------------
-
-ObjcField::ObjcField(Ivar ivar)
-{
- _ivar = ivar; // Assume ObjectiveC runtime will keep this alive forever
- _name = 0;
-}
-
-ObjcField::ObjcField(CFStringRef name)
-{
- _ivar = 0;
- _name = (CFStringRef)CFRetain(name);
-}
-
-const char* ObjcField::name() const
-{
-#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
- if (_ivar)
- return ivar_getName(_ivar);
-#else
- if (_ivar)
- return _ivar->ivar_name;
-#endif
- return [(NSString*)_name.get() UTF8String];
-}
-
-JSValue* ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const
-{
- JSValue* result = jsUndefined();
-
- id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
- @try {
- NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
- if (id objcValue = [targetObject valueForKey:key])
- result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());
- } @catch(NSException* localException) {
- JSLock::lock();
- throwError(exec, GeneralError, [localException reason]);
- JSLock::unlock();
- }
-
- return result;
-}
-
-static id convertValueToObjcObject(ExecState* exec, JSValue* value)
-{
- RefPtr<RootObject> rootObject = findRootObject(exec->dynamicGlobalObject());
- if (!rootObject)
- return nil;
- return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()];
-}
-
-void ObjcField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue* aValue) const
-{
- id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
- id value = convertValueToObjcObject(exec, aValue);
-
- JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
-
- @try {
- NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
- [targetObject setValue:value forKey:key];
- } @catch(NSException* localException) {
- JSLock::lock();
- throwError(exec, GeneralError, [localException reason]);
- JSLock::unlock();
- }
-}
-
-// ---------------------- ObjcArray ----------------------
-
-ObjcArray::ObjcArray(ObjectStructPtr a, PassRefPtr<RootObject> rootObject)
- : Array(rootObject)
- , _array(a)
-{
-}
-
-void ObjcArray::setValueAt(ExecState* exec, unsigned int index, JSValue* aValue) const
-{
- if (![_array.get() respondsToSelector:@selector(insertObject:atIndex:)]) {
- throwError(exec, TypeError, "Array is not mutable.");
- return;
- }
-
- if (index > [_array.get() count]) {
- throwError(exec, RangeError, "Index exceeds array size.");
- return;
- }
-
- // Always try to convert the value to an ObjC object, so it can be placed in the
- // array.
- ObjcValue oValue = convertValueToObjcValue (exec, aValue, ObjcObjectType);
-
- @try {
- [_array.get() insertObject:oValue.objectValue atIndex:index];
- } @catch(NSException* localException) {
- throwError(exec, GeneralError, "Objective-C exception.");
- }
-}
-
-JSValue* ObjcArray::valueAt(ExecState* exec, unsigned int index) const
-{
- if (index > [_array.get() count])
- return throwError(exec, RangeError, "Index exceeds array size.");
- @try {
- id obj = [_array.get() objectAtIndex:index];
- if (obj)
- return convertObjcValueToValue (exec, &obj, ObjcObjectType, _rootObject.get());
- } @catch(NSException* localException) {
- return throwError(exec, GeneralError, "Objective-C exception.");
- }
- return jsUndefined();
-}
-
-unsigned int ObjcArray::getLength() const
-{
- return [_array.get() count];
-}
-
-const ClassInfo ObjcFallbackObjectImp::info = { "ObjcFallbackObject", 0, 0 };
-
-ObjcFallbackObjectImp::ObjcFallbackObjectImp(ObjcInstance* i, const KJS::Identifier propertyName)
-: _instance(i)
-, _item(propertyName)
-{
-}
-
-bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot& slot)
-{
- // keep the prototype from getting called instead of just returning false
- slot.setUndefined(this);
- return true;
-}
-
-void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue*, int)
-{
-}
-
-bool ObjcFallbackObjectImp::canPut(ExecState*, const Identifier&) const
-{
- return false;
-}
-
-
-JSType ObjcFallbackObjectImp::type() const
-{
- id targetObject = _instance->getObject();
-
- if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
- return ObjectType;
-
- return UndefinedType;
-}
-
-bool ObjcFallbackObjectImp::implementsCall() const
-{
- id targetObject = _instance->getObject();
-
- if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
- return true;
-
- return false;
-}
-
-JSValue* ObjcFallbackObjectImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
-{
- if (thisObj->classInfo() != &KJS::RuntimeObjectImp::info)
- return throwError(exec, TypeError);
-
- JSValue* result = jsUndefined();
-
- RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(thisObj);
- Instance* instance = imp->getInternalInstance();
-
- if (!instance)
- return RuntimeObjectImp::throwInvalidAccessError(exec);
-
- instance->begin();
-
- ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
- id targetObject = objcInstance->getObject();
-
- if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
- MethodList methodList;
- ObjcClass* objcClass = static_cast<ObjcClass*>(instance->getClass());
- ObjcMethod* fallbackMethod = new ObjcMethod (objcClass->isa(), sel_getName(@selector(invokeUndefinedMethodFromWebScript:withArguments:)));
- fallbackMethod->setJavaScriptName((CFStringRef)[NSString stringWithCString:_item.ascii() encoding:NSASCIIStringEncoding]);
- methodList.append(fallbackMethod);
- result = instance->invokeMethod(exec, methodList, args);
- delete fallbackMethod;
- }
-
- instance->end();
-
- return result;
-}
-
-bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
-{
- return false;
-}
-
-JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, JSType hint) const
-{
- return _instance->getValueOfUndefinedField(exec, _item, hint);
-}
-
-bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
-{
- id targetObject = _instance->getObject();
-
- if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
- return true;
-
- return false;
-}
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef KJS_BINDINGS_OBJC_UTILITY_H
-#define KJS_BINDINGS_OBJC_UTILITY_H
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <JavaScriptCore/object.h>
-#include <JavaScriptCore/objc_header.h>
-
-#ifdef __OBJC__
-@class NSString;
-#else
-class NSString;
-#endif
-
-namespace KJS {
-namespace Bindings {
-
-typedef union {
- ObjectStructPtr objectValue;
- bool booleanValue;
- char charValue;
- short shortValue;
- int intValue;
- long longValue;
- long long longLongValue;
- float floatValue;
- double doubleValue;
-} ObjcValue;
-
-typedef enum {
- ObjcVoidType,
- ObjcObjectType,
- ObjcCharType,
- ObjcUnsignedCharType,
- ObjcShortType,
- ObjcUnsignedShortType,
- ObjcIntType,
- ObjcUnsignedIntType,
- ObjcLongType,
- ObjcUnsignedLongType,
- ObjcLongLongType,
- ObjcUnsignedLongLongType,
- ObjcFloatType,
- ObjcDoubleType,
- ObjcInvalidType
-} ObjcValueType;
-
-class RootObject;
-
-ObjcValue convertValueToObjcValue(ExecState *exec, JSValue *value, ObjcValueType type);
-JSValue *convertNSStringToString(NSString *nsstring);
-JSValue *convertObjcValueToValue(ExecState *exec, void *buffer, ObjcValueType type, RootObject*);
-ObjcValueType objcValueTypeForType(const char *type);
-
-bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
-
-JSObject *throwError(ExecState *, ErrorType, NSString *message);
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "objc_utility.h"
-
-#include "objc_instance.h"
-#include "JSGlobalObject.h"
-#include "runtime_array.h"
-#include "runtime_object.h"
-#include "WebScriptObject.h"
-#include <wtf/Assertions.h>
-
-#if !defined(_C_LNG_LNG)
-#define _C_LNG_LNG 'q'
-#endif
-
-#if !defined(_C_ULNG_LNG)
-#define _C_ULNG_LNG 'Q'
-#endif
-
-#if !defined(_C_CONST)
-#define _C_CONST 'r'
-#endif
-
-#if !defined(_C_BYCOPY)
-#define _C_BYCOPY 'O'
-#endif
-
-#if !defined(_C_BYREF)
-#define _C_BYREF 'R'
-#endif
-
-#if !defined(_C_ONEWAY)
-#define _C_ONEWAY 'V'
-#endif
-
-#if !defined(_C_GCINVISIBLE)
-#define _C_GCINVISIBLE '!'
-#endif
-
-namespace KJS {
-namespace Bindings {
-
-/*
- By default, a JavaScript method name is produced by concatenating the
- components of an ObjectiveC method name, replacing ':' with '_', and
- escaping '_' and '$' with a leading '$', such that '_' becomes "$_" and
- '$' becomes "$$". For example:
-
- ObjectiveC name Default JavaScript name
- moveTo:: moveTo__
- moveTo_ moveTo$_
- moveTo$_ moveTo$$$_
-
- This function performs the inverse of that operation.
-
- @result Fills 'buffer' with the ObjectiveC method name that corresponds to 'JSName'.
- Returns true for success, false for failure. (Failure occurs when 'buffer'
- is not big enough to hold the result.)
-*/
-bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize)
-{
- ASSERT(JSName && buffer);
-
- const char *sp = JSName; // source pointer
- char *dp = buffer; // destination pointer
-
- char *end = buffer + bufferSize;
- while (dp < end) {
- if (*sp == '$') {
- ++sp;
- *dp = *sp;
- } else if (*sp == '_')
- *dp = ':';
- else
- *dp = *sp;
-
- // If a future coder puts funny ++ operators above, we might write off the end
- // of the buffer in the middle of this loop. Let's make sure to check for that.
- ASSERT(dp < end);
-
- if (*sp == 0) { // We finished converting JSName
- ASSERT(strlen(JSName) < bufferSize);
- return true;
- }
-
- ++sp;
- ++dp;
- }
-
- return false; // We ran out of buffer before converting JSName
-}
-
-/*
-
- JavaScript to ObjC
- Number coerced to char, short, int, long, float, double, or NSNumber, as appropriate
- String NSString
- wrapper id
- Object WebScriptObject
- null NSNull
- [], other exception
-
-*/
-ObjcValue convertValueToObjcValue(ExecState *exec, JSValue *value, ObjcValueType type)
-{
- ObjcValue result;
- double d = 0;
-
- if (value->isNumber() || value->isString() || value->isBoolean())
- d = value->toNumber(exec);
-
- switch (type) {
- case ObjcObjectType: {
- JSLock lock;
-
- JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
- RootObject* originRootObject = findRootObject(originGlobalObject);
-
- JSGlobalObject* globalObject = 0;
- if (value->isObject() && static_cast<JSObject*>(value)->isGlobalObject())
- globalObject = static_cast<JSGlobalObject*>(value);
-
- if (!globalObject)
- globalObject = originGlobalObject;
-
- RootObject* rootObject = findRootObject(globalObject);
- result.objectValue = rootObject
- ? [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject]
- : nil;
- }
- break;
-
- case ObjcCharType:
- case ObjcUnsignedCharType:
- result.charValue = (char)d;
- break;
- case ObjcShortType:
- case ObjcUnsignedShortType:
- result.shortValue = (short)d;
- break;
- case ObjcIntType:
- case ObjcUnsignedIntType:
- result.intValue = (int)d;
- break;
- case ObjcLongType:
- case ObjcUnsignedLongType:
- result.longValue = (long)d;
- break;
- case ObjcLongLongType:
- case ObjcUnsignedLongLongType:
- result.longLongValue = (long long)d;
- break;
- case ObjcFloatType:
- result.floatValue = (float)d;
- break;
- case ObjcDoubleType:
- result.doubleValue = (double)d;
- break;
- case ObjcVoidType:
- bzero(&result, sizeof(ObjcValue));
- break;
-
- case ObjcInvalidType:
- default:
- // FIXME: throw an exception?
- break;
- }
-
- return result;
-}
-
-JSValue *convertNSStringToString(NSString *nsstring)
-{
- JSLock lock;
-
- unichar *chars;
- unsigned int length = [nsstring length];
- chars = (unichar *)malloc(sizeof(unichar)*length);
- [nsstring getCharacters:chars];
- UString u((const UChar*)chars, length);
- JSValue *aValue = jsString(u);
- free((void *)chars);
- return aValue;
-}
-
-/*
- ObjC to JavaScript
- ---- ----------
- char number
- short number
- int number
- long number
- float number
- double number
- NSNumber boolean or number
- NSString string
- NSArray array
- NSNull null
- WebScriptObject underlying JavaScript object
- WebUndefined undefined
- id object wrapper
- other should not happen
-*/
-JSValue* convertObjcValueToValue(ExecState* exec, void* buffer, ObjcValueType type, RootObject* rootObject)
-{
- JSLock lock;
-
- switch (type) {
- case ObjcObjectType: {
- id obj = *(id*)buffer;
- if ([obj isKindOfClass:[NSString class]])
- return convertNSStringToString((NSString *)obj);
- if ([obj isKindOfClass:webUndefinedClass()])
- return jsUndefined();
- if ((CFBooleanRef)obj == kCFBooleanTrue)
- return jsBoolean(true);
- if ((CFBooleanRef)obj == kCFBooleanFalse)
- return jsBoolean(false);
- if ([obj isKindOfClass:[NSNumber class]])
- return jsNumber([obj doubleValue]);
- if ([obj isKindOfClass:[NSArray class]])
- return new RuntimeArray(exec, new ObjcArray(obj, rootObject));
- if ([obj isKindOfClass:webScriptObjectClass()]) {
- JSObject* imp = [obj _imp];
- return imp ? imp : jsUndefined();
- }
- if ([obj isKindOfClass:[NSNull class]])
- return jsNull();
- if (obj == 0)
- return jsUndefined();
- return Instance::createRuntimeObject(Instance::ObjectiveCLanguage, obj, rootObject);
- }
- case ObjcCharType:
- return jsNumber(*(char *)buffer);
- case ObjcUnsignedCharType:
- return jsNumber(*(unsigned char *)buffer);
- case ObjcShortType:
- return jsNumber(*(short *)buffer);
- case ObjcUnsignedShortType:
- return jsNumber(*(unsigned short *)buffer);
- case ObjcIntType:
- return jsNumber(*(int *)buffer);
- case ObjcUnsignedIntType:
- return jsNumber(*(unsigned int *)buffer);
- case ObjcLongType:
- return jsNumber(*(long *)buffer);
- case ObjcUnsignedLongType:
- return jsNumber(*(unsigned long *)buffer);
- case ObjcLongLongType:
- return jsNumber(*(long long *)buffer);
- case ObjcUnsignedLongLongType:
- return jsNumber(*(unsigned long long *)buffer);
- case ObjcFloatType:
- return jsNumber(*(float *)buffer);
- case ObjcDoubleType:
- return jsNumber(*(double *)buffer);
- default:
- // Should never get here. Argument types are filtered.
- fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
- ASSERT(false);
- }
-
- return 0;
-}
-
-ObjcValueType objcValueTypeForType(const char *type)
-{
- int typeLength = strlen(type);
- ObjcValueType objcValueType = ObjcInvalidType;
-
- for (int i = 0; i < typeLength; ++i) {
- char typeChar = type[i];
- switch (typeChar) {
- case _C_CONST:
- case _C_BYCOPY:
- case _C_BYREF:
- case _C_ONEWAY:
- case _C_GCINVISIBLE:
- // skip these type modifiers
- break;
- case _C_ID:
- objcValueType = ObjcObjectType;
- break;
- case _C_CHR:
- objcValueType = ObjcCharType;
- break;
- case _C_UCHR:
- objcValueType = ObjcUnsignedCharType;
- break;
- case _C_SHT:
- objcValueType = ObjcShortType;
- break;
- case _C_USHT:
- objcValueType = ObjcUnsignedShortType;
- break;
- case _C_INT:
- objcValueType = ObjcIntType;
- break;
- case _C_UINT:
- objcValueType = ObjcUnsignedIntType;
- break;
- case _C_LNG:
- objcValueType = ObjcLongType;
- break;
- case _C_ULNG:
- objcValueType = ObjcUnsignedLongType;
- break;
- case _C_LNG_LNG:
- objcValueType = ObjcLongLongType;
- break;
- case _C_ULNG_LNG:
- objcValueType = ObjcUnsignedLongLongType;
- break;
- case _C_FLT:
- objcValueType = ObjcFloatType;
- break;
- case _C_DBL:
- objcValueType = ObjcDoubleType;
- break;
- case _C_VOID:
- objcValueType = ObjcVoidType;
- break;
- default:
- // Unhandled type. We don't handle C structs, unions, etc.
- // FIXME: throw an exception?
- ASSERT(false);
- }
-
- if (objcValueType != ObjcInvalidType)
- break;
- }
-
- return objcValueType;
-}
-
-JSObject *throwError(ExecState *exec, ErrorType type, NSString *message)
-{
- ASSERT(message);
- size_t length = [message length];
- unichar *buffer = new unichar[length];
- [message getCharacters:buffer];
- JSObject *error = throwError(exec, type, UString(reinterpret_cast<UChar *>(buffer), length));
- delete [] buffer;
- return error;
-}
-
-}
-}
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "identifier.h"
-
-#include "qt_class.h"
-#include "qt_instance.h"
-#include "qt_runtime.h"
-
-#include <qmetaobject.h>
-#include <qdebug.h>
-
-namespace KJS {
-namespace Bindings {
-
-QtClass::QtClass(const QMetaObject* mo)
- : m_metaObject(mo)
-{
-}
-
-QtClass::~QtClass()
-{
-}
-
-typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
-static ClassesByMetaObject* classesByMetaObject = 0;
-
-QtClass* QtClass::classForObject(QObject* o)
-{
- if (!classesByMetaObject)
- classesByMetaObject = new ClassesByMetaObject;
-
- const QMetaObject* mo = o->metaObject();
- QtClass* aClass = classesByMetaObject->get(mo);
- if (!aClass) {
- aClass = new QtClass(mo);
- classesByMetaObject->set(mo, aClass);
- }
-
- return aClass;
-}
-
-const char* QtClass::name() const
-{
- return m_metaObject->className();
-}
-
-// We use this to get at signals (so we can return a proper function object,
-// and not get wrapped in RuntimeMethod). Also, use this for methods,
-// so we can cache the JSValue* and return the same JSValue for the same
-// identifier...
-//
-// Unfortunately... we need to gcProtect our JSValues, since we don't have
-// access to an actual JS class that can mark() our JSValues.
-//
-JSValue* QtClass::fallbackObject(ExecState *exec, Instance *inst, const Identifier &identifier)
-{
- QtInstance* qtinst = static_cast<QtInstance*>(inst);
-
- QByteArray name(identifier.ascii());
-
- // First see if we have a cache hit
- JSValue* val = qtinst->m_methods.value(name);
- if (val)
- return val;
-
- // Nope, create an entry
- QByteArray normal = QMetaObject::normalizedSignature(name.constData());
-
- // See if there is an exact match
- int index = -1;
- if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
- QMetaMethod m = m_metaObject->method(index);
- if (m.access() != QMetaMethod::Private) {
- JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
- gcProtect(val);
- qtinst->m_methods.insert(name, val);
- return val;
- }
- }
-
- // Nope.. try a basename match
- int count = m_metaObject->methodCount();
- for (index = count - 1; index >= 0; --index) {
- const QMetaMethod m = m_metaObject->method(index);
- if (m.access() == QMetaMethod::Private)
- continue;
-
- QByteArray signature = m.signature();
- signature.truncate(signature.indexOf('('));
-
- if (normal == signature) {
- JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
- gcProtect(val);
- qtinst->m_methods.insert(name, val);
- return val;
- }
- }
-
- return jsUndefined();
-}
-
-// This functionality is handled by the fallback case above...
-MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
-{
- return MethodList();
-}
-
-// ### we may end up with a different search order than QtScript by not
-// folding this code into the fallbackMethod above, but Fields propagate out
-// of the binding code
-Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
-{
- // Check static properties first
- QtInstance* qtinst = static_cast<QtInstance*>(instance);
-
- QObject* obj = qtinst->getObject();
- UString ustring = identifier.ustring();
- QString objName(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
- QByteArray ba = objName.toAscii();
-
- // First check for a cached field
- QtField* f = qtinst->m_fields.value(objName);
-
- if (obj) {
- if (f) {
- // We only cache real metaproperties, but we do store the
- // other types so we can delete them later
- if (f->fieldType() == QtField::MetaProperty)
- return f;
- else if (f->fieldType() == QtField::DynamicProperty) {
- if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
- return f;
- else {
- // Dynamic property that disappeared
- qtinst->m_fields.remove(objName);
- delete f;
- }
- } else {
- QList<QObject*> children = obj->children();
- for (int index = 0; index < children.count(); ++index) {
- QObject *child = children.at(index);
- if (child->objectName() == objName)
- return f;
- }
-
- // Didn't find it, delete it from the cache
- qtinst->m_fields.remove(objName);
- delete f;
- }
- }
-
- int index = m_metaObject->indexOfProperty(identifier.ascii());
- if (index >= 0) {
- QMetaProperty prop = m_metaObject->property(index);
-
- if (prop.isScriptable(obj)) {
- f = new QtField(prop);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
- }
-
- // Dynamic properties
- index = obj->dynamicPropertyNames().indexOf(ba);
- if (index >= 0) {
- f = new QtField(ba);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
-
- // Child objects
-
- QList<QObject*> children = obj->children();
- for (index = 0; index < children.count(); ++index) {
- QObject *child = children.at(index);
- if (child->objectName() == objName) {
- f = new QtField(child);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
- }
-
- // Nothing named this
- return 0;
- } else {
- QByteArray ba(identifier.ascii());
- // For compatibility with qtscript, cached methods don't cause
- // errors until they are accessed, so don't blindly create an error
- // here.
- if (qtinst->m_methods.contains(ba))
- return 0;
-
- // deleted qobject, but can't throw an error from here (no exec)
- // create a fake QtField that will throw upon access
- if (!f) {
- f = new QtField(ba);
- qtinst->m_fields.insert(objName, f);
- }
- return f;
- }
-}
-
-}
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef BINDINGS_QT_CLASS_H_
-#define BINDINGS_QT_CLASS_H_
-
-#include "runtime.h"
-class QObject;
-class QMetaObject;
-
-namespace KJS {
-namespace Bindings {
-
-
-class QtClass : public Class {
-protected:
- QtClass(const QMetaObject*);
-
-public:
- static QtClass* classForObject(QObject*);
- virtual ~QtClass();
-
- virtual const char* name() const;
- virtual MethodList methodsNamed(const Identifier&, Instance*) const;
- virtual Field* fieldNamed(const Identifier&, Instance*) const;
-
- virtual JSValue* fallbackObject(ExecState*, Instance*, const Identifier&);
-
-private:
- QtClass(const QtClass&); // prohibit copying
- QtClass& operator=(const QtClass&); // prohibit assignment
-
- const QMetaObject* m_metaObject;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "qt_instance.h"
-
-#include "JSGlobalObject.h"
-#include "list.h"
-#include "qt_class.h"
-#include "qt_runtime.h"
-#include "PropertyNameArray.h"
-#include "runtime_object.h"
-#include "object_object.h"
-
-#include <qmetaobject.h>
-#include <qdebug.h>
-#include <qmetatype.h>
-#include <qhash.h>
-
-namespace KJS {
-namespace Bindings {
-
-// Cache QtInstances
-typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
-static QObjectInstanceMap cachedInstances;
-
-// Cache JSObjects
-typedef QHash<QtInstance*, JSObject*> InstanceJSObjectMap;
-static InstanceJSObjectMap cachedObjects;
-
-// Derived RuntimeObject
-class QtRuntimeObjectImp : public RuntimeObjectImp {
- public:
- QtRuntimeObjectImp(Instance*);
- ~QtRuntimeObjectImp();
- virtual void invalidate();
-
- // Additions
- virtual bool implementsConstruct() const {return implementsCall();}
- virtual JSObject* construct(ExecState* exec, const List& args);
- protected:
- void removeFromCache();
-};
-
-QtRuntimeObjectImp::QtRuntimeObjectImp(Instance* instance)
- : RuntimeObjectImp(instance)
-{
-}
-
-QtRuntimeObjectImp::~QtRuntimeObjectImp()
-{
- removeFromCache();
-}
-
-void QtRuntimeObjectImp::invalidate()
-{
- removeFromCache();
- RuntimeObjectImp::invalidate();
-}
-
-void QtRuntimeObjectImp::removeFromCache()
-{
- JSLock lock;
- QtInstance* key = cachedObjects.key(this);
- if (key)
- cachedObjects.remove(key);
-}
-
-JSObject* QtRuntimeObjectImp::construct(ExecState* exec, const List& args)
-{
- // ECMA 15.2.2.1 (?)
- JSValue *val = callAsFunction(exec, this, args);
-
- if (!val || val->type() == NullType || val->type() == UndefinedType)
- return new JSObject(exec->lexicalGlobalObject()->objectPrototype());
- else
- return val->toObject(exec);
-}
-
-// QtInstance
-QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
- : Instance(rootObject)
- , m_class(0)
- , m_object(o)
- , m_hashkey(o)
- , m_defaultMethod(0)
- , m_defaultMethodIndex(-2)
-{
-}
-
-QtInstance::~QtInstance()
-{
- JSLock lock;
-
- cachedObjects.remove(this);
- cachedInstances.remove(m_hashkey);
-
- // clean up (unprotect from gc) the JSValues we've created
- foreach(JSValue* val, m_methods.values()) {
- gcUnprotect(val);
- }
- m_methods.clear();
-
- foreach(QtField* f, m_fields.values()) {
- delete f;
- }
- m_fields.clear();
-
- if (m_defaultMethod)
- gcUnprotect(m_defaultMethod);
-}
-
-QtInstance* QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
-{
- JSLock lock;
-
- foreach(QtInstance* instance, cachedInstances.values(o)) {
- if (instance->rootObject() == rootObject)
- return instance;
- }
-
- QtInstance* ret = new QtInstance(o, rootObject);
- cachedInstances.insert(o, ret);
-
- return ret;
-}
-
-JSObject* QtInstance::getRuntimeObject(QtInstance* instance)
-{
- JSLock lock;
- JSObject* ret = cachedObjects.value(instance);
- if (!ret) {
- ret = new QtRuntimeObjectImp(instance);
- cachedObjects.insert(instance, ret);
- }
- return ret;
-}
-
-Class* QtInstance::getClass() const
-{
- if (!m_class)
- m_class = QtClass::classForObject(m_object);
- return m_class;
-}
-
-void QtInstance::begin()
-{
- // Do nothing.
-}
-
-void QtInstance::end()
-{
- // Do nothing.
-}
-
-void QtInstance::getPropertyNames(ExecState* , PropertyNameArray& array)
-{
- // This is the enumerable properties, so put:
- // properties
- // dynamic properties
- // slots
- QObject* obj = getObject();
- if (obj) {
- const QMetaObject* meta = obj->metaObject();
-
- int i;
- for (i=0; i < meta->propertyCount(); i++) {
- QMetaProperty prop = meta->property(i);
- if (prop.isScriptable()) {
- array.add(Identifier(prop.name()));
- }
- }
-
- QList<QByteArray> dynProps = obj->dynamicPropertyNames();
- foreach(QByteArray ba, dynProps) {
- array.add(Identifier(ba.constData()));
- }
-
- for (i=0; i < meta->methodCount(); i++) {
- QMetaMethod method = meta->method(i);
- if (method.access() != QMetaMethod::Private) {
- array.add(Identifier(method.signature()));
- }
- }
- }
-}
-
-JSValue* QtInstance::invokeMethod(ExecState*, const MethodList&, const List&)
-{
- // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
- return jsUndefined();
-}
-
-bool QtInstance::implementsCall() const
-{
- // See if we have qscript_call
- if (m_defaultMethodIndex == -2) {
- if (m_object) {
- const QMetaObject* meta = m_object->metaObject();
- int count = meta->methodCount();
- const QByteArray defsig("qscript_call");
- for (int index = count - 1; index >= 0; --index) {
- const QMetaMethod m = meta->method(index);
-
- QByteArray signature = m.signature();
- signature.truncate(signature.indexOf('('));
-
- if (defsig == signature) {
- m_defaultMethodIndex = index;
- break;
- }
- }
- }
-
- if (m_defaultMethodIndex == -2) // Not checked
- m_defaultMethodIndex = -1; // No qscript_call
- }
-
- // typeof object that implements call == function
- return (m_defaultMethodIndex >= 0);
-}
-
-JSValue* QtInstance::invokeDefaultMethod(ExecState* exec, const List& args)
-{
- // QtScript tries to invoke a meta method qscript_call
- if (!getObject())
- return throwError(exec, GeneralError, "cannot call function of deleted QObject");
-
- // implementsCall will update our default method cache, if possible
- if (implementsCall()) {
- if (!m_defaultMethod) {
- m_defaultMethod = new QtRuntimeMetaMethod(exec, Identifier("[[Call]]"),this, m_defaultMethodIndex, QByteArray("qscript_call"), true);
- gcProtect(m_defaultMethod);
- }
-
- return m_defaultMethod->callAsFunction(exec, 0, args); // Luckily QtRuntimeMetaMethod ignores the obj parameter
- } else
- return throwError(exec, TypeError, "not a function");
-}
-
-JSValue* QtInstance::defaultValue(JSType hint) const
-{
- if (hint == StringType)
- return stringValue();
- if (hint == NumberType)
- return numberValue();
- if (hint == BooleanType)
- return booleanValue();
- return valueOf();
-}
-
-JSValue* QtInstance::stringValue() const
-{
- // Hmm.. see if there is a toString defined
- QByteArray buf;
- bool useDefault = true;
- getClass();
- QObject* obj = getObject();
- if (m_class && obj) {
- // Cheat and don't use the full name resolution
- int index = obj->metaObject()->indexOfMethod("toString()");
- if (index >= 0) {
- QMetaMethod m = obj->metaObject()->method(index);
- // Check to see how much we can call it
- if (m.access() != QMetaMethod::Private
- && m.methodType() != QMetaMethod::Signal
- && m.parameterTypes().count() == 0) {
- const char* retsig = m.typeName();
- if (retsig && *retsig) {
- QVariant ret(QMetaType::type(retsig), (void*)0);
- void * qargs[1];
- qargs[0] = ret.data();
-
- if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, index, qargs) < 0) {
- if (ret.isValid() && ret.canConvert(QVariant::String)) {
- buf = ret.toString().toLatin1().constData(); // ### Latin 1? Ascii?
- useDefault = false;
- }
- }
- }
- }
- }
- }
-
- if (useDefault) {
- const QMetaObject* meta = obj ? obj->metaObject() : &QObject::staticMetaObject;
- QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed");
- QString str = QString::fromUtf8("%0(name = \"%1\")")
- .arg(QLatin1String(meta->className())).arg(name);
-
- buf = str.toLatin1();
- }
- return jsString(buf.constData());
-}
-
-JSValue* QtInstance::numberValue() const
-{
- return jsNumber(0);
-}
-
-JSValue* QtInstance::booleanValue() const
-{
- // ECMA 9.2
- return jsBoolean(true);
-}
-
-JSValue* QtInstance::valueOf() const
-{
- return stringValue();
-}
-
-// In qt_runtime.cpp
-JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
-QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance);
-
-const char* QtField::name() const
-{
- if (m_type == MetaProperty)
- return m_property.name();
- else if (m_type == ChildObject && m_childObject)
- return m_childObject->objectName().toLatin1();
- else if (m_type == DynamicProperty)
- return m_dynamicProperty.constData();
- return ""; // deleted child object
-}
-
-JSValue* QtField::valueFromInstance(ExecState* exec, const Instance* inst) const
-{
- const QtInstance* instance = static_cast<const QtInstance*>(inst);
- QObject* obj = instance->getObject();
-
- if (obj) {
- QVariant val;
- if (m_type == MetaProperty) {
- if (m_property.isReadable())
- val = m_property.read(obj);
- else
- return jsUndefined();
- } else if (m_type == ChildObject)
- val = QVariant::fromValue((QObject*) m_childObject);
- else if (m_type == DynamicProperty)
- val = obj->property(m_dynamicProperty);
-
- return convertQVariantToValue(exec, inst->rootObject(), val);
- } else {
- QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
- return throwError(exec, GeneralError, msg.toLatin1().constData());
- }
-}
-
-void QtField::setValueToInstance(ExecState* exec, const Instance* inst, JSValue* aValue) const
-{
- if (m_type == ChildObject) // QtScript doesn't allow setting to a named child
- return;
-
- const QtInstance* instance = static_cast<const QtInstance*>(inst);
- QObject* obj = instance->getObject();
- if (obj) {
- QMetaType::Type argtype = QMetaType::Void;
- if (m_type == MetaProperty)
- argtype = (QMetaType::Type) QMetaType::type(m_property.typeName());
-
- // dynamic properties just get any QVariant
- QVariant val = convertValueToQVariant(exec, aValue, argtype, 0);
- if (m_type == MetaProperty) {
- if (m_property.isWritable())
- m_property.write(obj, val);
- } else if (m_type == DynamicProperty)
- obj->setProperty(m_dynamicProperty.constData(), val);
- } else {
- QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
- throwError(exec, GeneralError, msg.toLatin1().constData());
- }
-}
-
-
-}
-}
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef BINDINGS_QT_INSTANCE_H_
-#define BINDINGS_QT_INSTANCE_H_
-
-#include "runtime.h"
-#include "runtime_root.h"
-#include <qpointer.h>
-#include <qhash.h>
-
-class QObject;
-
-namespace KJS {
-
-namespace Bindings {
-
-class QtClass;
-class QtField;
-class QtRuntimeMetaMethod;
-
-class QtInstance : public Instance
-{
-public:
- ~QtInstance ();
-
- virtual Class* getClass() const;
-
- virtual void begin();
- virtual void end();
-
- virtual JSValue* valueOf() const;
- virtual JSValue* defaultValue (JSType hint) const;
-
- virtual bool implementsCall() const;
-
- virtual JSValue* invokeMethod (ExecState *exec, const MethodList &method, const List &args);
- virtual JSValue* invokeDefaultMethod (ExecState *exec, const List &args);
-
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual BindingLanguage getBindingLanguage() const { return QtLanguage; }
-
- JSValue* stringValue() const;
- JSValue* numberValue() const;
- JSValue* booleanValue() const;
-
- QObject* getObject() const { return m_object; }
-
- static QtInstance* getQtInstance(QObject*, PassRefPtr<RootObject>);
- static JSObject* getRuntimeObject(QtInstance*);
-
-private:
- friend class QtClass;
- QtInstance(QObject*, PassRefPtr<RootObject>); // Factory produced only..
- mutable QtClass* m_class;
- QPointer<QObject> m_object;
- QObject* m_hashkey;
- mutable QHash<QByteArray,JSValue*> m_methods;
- mutable QHash<QString,QtField*> m_fields;
- mutable QtRuntimeMetaMethod* m_defaultMethod;
- mutable int m_defaultMethodIndex;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "qt_runtime.h"
-#include "qt_instance.h"
-#include "object.h"
-#include "array_instance.h"
-#include "date_object.h"
-#include "DateMath.h"
-#include "regexp_object.h"
-#include <runtime_object.h>
-#include <runtime_array.h>
-#include <function.h>
-#include "PropertyNameArray.h"
-#include "qmetatype.h"
-#include "qmetaobject.h"
-#include "qobject.h"
-#include "qstringlist.h"
-#include "qdebug.h"
-#include "qvarlengtharray.h"
-#include "qdatetime.h"
-#include <limits.h>
-
-// QtScript has these
-Q_DECLARE_METATYPE(QObjectList);
-Q_DECLARE_METATYPE(QList<int>);
-Q_DECLARE_METATYPE(QVariant);
-
-
-namespace KJS {
-namespace Bindings {
-
-// Debugging
-//#define QTWK_RUNTIME_CONVERSION_DEBUG
-//#define QTWK_RUNTIME_MATCH_DEBUG
-
-class QWKNoDebug
-{
-public:
- inline QWKNoDebug(){}
- inline ~QWKNoDebug(){}
-
- template<typename T>
- inline QWKNoDebug &operator<<(const T &) { return *this; }
-};
-
-#ifdef QTWK_RUNTIME_CONVERSION_DEBUG
-#define qConvDebug() qDebug()
-#else
-#define qConvDebug() QWKNoDebug()
-#endif
-
-#ifdef QTWK_RUNTIME_MATCH_DEBUG
-#define qMatchDebug() qDebug()
-#else
-#define qMatchDebug() QWKNoDebug()
-#endif
-
-typedef enum {
- Variant,
- Number,
- Boolean,
- String,
- Date,
- RegExp,
- Array,
- QObj,
- Object,
- Null
-} JSRealType;
-
-static JSRealType valueRealType(ExecState* exec, JSValue* val)
-{
- if (val->isNumber())
- return Number;
- else if (val->isString())
- return String;
- else if (val->isBoolean())
- return Boolean;
- else if (val->isNull())
- return Null;
- else if (val->isObject()) {
- JSObject *object = val->toObject(exec);
- if (object->inherits(&ArrayInstance::info))
- return Array;
- else if (object->inherits(&DateInstance::info))
- return Date;
- else if (object->inherits(&RegExpImp::info))
- return RegExp;
- else if (object->inherits(&RuntimeObjectImp::info))
- return QObj;
- return Object;
- }
-
- return String; // I don't know.
-}
-
-QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance)
-{
- // check magic pointer values before dereferencing value
- if (value == jsNaN() || value == jsUndefined()) {
- if (distance)
- *distance = -1;
- return QVariant();
- }
-
- JSLock lock;
- JSRealType type = valueRealType(exec, value);
- if (hint == QMetaType::Void) {
- switch(type) {
- case Number:
- hint = QMetaType::Double;
- break;
- case Boolean:
- hint = QMetaType::Bool;
- break;
- case String:
- default:
- hint = QMetaType::QString;
- break;
- case Date:
- hint = QMetaType::QDateTime;
- break;
- case RegExp:
- hint = QMetaType::QRegExp;
- break;
- case QObj:
- hint = QMetaType::QObjectStar;
- break;
- case Array:
- hint = QMetaType::QVariantList;
- break;
- }
- }
-
- if (value == jsNull()
- && hint != QMetaType::QObjectStar
- && hint != QMetaType::VoidStar) {
- if (distance)
- *distance = -1;
- return QVariant();
- }
-
- QVariant ret;
- int dist = -1;
- switch (hint) {
- case QMetaType::Bool:
- ret = QVariant(value->toBoolean(exec));
- if (type == Boolean)
- dist = 0;
- else
- dist = 10;
- break;
-
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Long:
- case QMetaType::ULong:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::Short:
- case QMetaType::UShort:
- case QMetaType::Float:
- case QMetaType::Double:
- ret = QVariant(value->toNumber(exec));
- ret.convert((QVariant::Type)hint);
- if (type == Number) {
- switch (hint) {
- case QMetaType::Double:
- dist = 0;
- break;
- case QMetaType::Float:
- dist = 1;
- break;
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- dist = 2;
- break;
- case QMetaType::Long:
- case QMetaType::ULong:
- dist = 3;
- break;
- case QMetaType::Int:
- case QMetaType::UInt:
- dist = 4;
- break;
- case QMetaType::Short:
- case QMetaType::UShort:
- dist = 5;
- break;
- break;
- default:
- dist = 10;
- break;
- }
- } else {
- dist = 10;
- }
- break;
-
- case QMetaType::QChar:
- if (type == Number || type == Boolean) {
- ret = QVariant(QChar((ushort)value->toNumber(exec)));
- if (type == Boolean)
- dist = 3;
- else
- dist = 6;
- } else {
- UString str = value->toString(exec);
- ret = QVariant(QChar(str.size() ? *(const ushort*)str.rep()->data() : 0));
- if (type == String)
- dist = 3;
- else
- dist = 10;
- }
- break;
-
- case QMetaType::QString: {
- UString ustring = value->toString(exec);
- ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
- if (type == String)
- dist = 0;
- else
- dist = 10;
- break;
- }
-
- case QMetaType::QVariantMap:
- if (type == Object || type == Array) {
- // Enumerate the contents of the object
- JSObject* object = value->toObject(exec);
-
- PropertyNameArray properties;
- object->getPropertyNames(exec, properties);
- PropertyNameArray::const_iterator it = properties.begin();
-
- QVariantMap result;
- int objdist = 0;
- while(it != properties.end()) {
- if (object->propertyIsEnumerable(exec, *it)) {
- JSValue* val = object->get(exec, *it);
- QVariant v = convertValueToQVariant(exec, val, QMetaType::Void, &objdist);
- if (objdist >= 0) {
- UString ustring = (*it).ustring();
- QString id = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
- result.insert(id, v);
- }
- }
- ++it;
- }
- dist = 1;
- ret = QVariant(result);
- }
- break;
-
- case QMetaType::QVariantList:
- if (type == Array) {
- JSObject* object = value->toObject(exec);
- ArrayInstance* array = static_cast<ArrayInstance*>(object);
-
- QVariantList result;
- int len = array->getLength();
- int objdist = 0;
- for (int i = 0; i < len; ++i) {
- JSValue *val = array->getItem(i);
- result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist));
- if (objdist == -1)
- break; // Failed converting a list entry, so fail the array
- }
- if (objdist != -1) {
- dist = 5;
- ret = QVariant(result);
- }
- } else {
- // Make a single length array
- QVariantList result;
- int objdist;
- result.append(convertValueToQVariant(exec, value, QMetaType::Void, &objdist));
- if (objdist != -1) {
- ret = QVariant(result);
- dist = 10;
- }
- }
- break;
-
- case QMetaType::QStringList: {
- if (type == Array) {
- JSObject* object = value->toObject(exec);
- ArrayInstance* array = static_cast<ArrayInstance*>(object);
-
- QStringList result;
- int len = array->getLength();
- for (int i = 0; i < len; ++i) {
- JSValue* val = array->getItem(i);
- UString ustring = val->toString(exec);
- QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
-
- result.append(qstring);
- }
- dist = 5;
- ret = QVariant(result);
- } else {
- // Make a single length array
- UString ustring = value->toString(exec);
- QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
- QStringList result;
- result.append(qstring);
- ret = QVariant(result);
- dist = 10;
- }
- break;
- }
-
- case QMetaType::QByteArray: {
- UString ustring = value->toString(exec);
- ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()).toLatin1());
- if (type == String)
- dist = 5;
- else
- dist = 10;
- break;
- }
-
- case QMetaType::QDateTime:
- case QMetaType::QDate:
- case QMetaType::QTime:
- if (type == Date) {
- JSObject* object = value->toObject(exec);
- DateInstance* date = static_cast<DateInstance*>(object);
- GregorianDateTime gdt;
- date->getUTCTime(gdt);
- if (hint == QMetaType::QDateTime) {
- ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
- dist = 0;
- } else if (hint == QMetaType::QDate) {
- ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
- dist = 1;
- } else {
- ret = QTime(gdt.hour + 1900, gdt.minute, gdt.second);
- dist = 2;
- }
- } else if (type == Number) {
- double b = value->toNumber(exec);
- GregorianDateTime gdt;
- msToGregorianDateTime(b, true, gdt);
- if (hint == QMetaType::QDateTime) {
- ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
- dist = 6;
- } else if (hint == QMetaType::QDate) {
- ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
- dist = 8;
- } else {
- ret = QTime(gdt.hour, gdt.minute, gdt.second);
- dist = 10;
- }
- } else if (type == String) {
- UString ustring = value->toString(exec);
- QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
-
- if (hint == QMetaType::QDateTime) {
- QDateTime dt = QDateTime::fromString(qstring, Qt::ISODate);
- if (!dt.isValid())
- dt = QDateTime::fromString(qstring, Qt::TextDate);
- if (!dt.isValid())
- dt = QDateTime::fromString(qstring, Qt::SystemLocaleDate);
- if (!dt.isValid())
- dt = QDateTime::fromString(qstring, Qt::LocaleDate);
- if (dt.isValid()) {
- ret = dt;
- dist = 2;
- }
- } else if (hint == QMetaType::QDate) {
- QDate dt = QDate::fromString(qstring, Qt::ISODate);
- if (!dt.isValid())
- dt = QDate::fromString(qstring, Qt::TextDate);
- if (!dt.isValid())
- dt = QDate::fromString(qstring, Qt::SystemLocaleDate);
- if (!dt.isValid())
- dt = QDate::fromString(qstring, Qt::LocaleDate);
- if (dt.isValid()) {
- ret = dt;
- dist = 3;
- }
- } else {
- QTime dt = QTime::fromString(qstring, Qt::ISODate);
- if (!dt.isValid())
- dt = QTime::fromString(qstring, Qt::TextDate);
- if (!dt.isValid())
- dt = QTime::fromString(qstring, Qt::SystemLocaleDate);
- if (!dt.isValid())
- dt = QTime::fromString(qstring, Qt::LocaleDate);
- if (dt.isValid()) {
- ret = dt;
- dist = 3;
- }
- }
- }
- break;
-
- case QMetaType::QRegExp:
- if (type == RegExp) {
-/* JSObject *object = value->toObject(exec);
- RegExpImp *re = static_cast<RegExpImp*>(object);
-*/
- // Attempt to convert.. a bit risky
- UString ustring = value->toString(exec);
- QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
-
- // this is of the form '/xxxxxx/i'
- int firstSlash = qstring.indexOf('/');
- int lastSlash = qstring.lastIndexOf('/');
- if (firstSlash >=0 && lastSlash > firstSlash) {
- QRegExp realRe;
-
- realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
-
- if (qstring.mid(lastSlash + 1).contains('i'))
- realRe.setCaseSensitivity(Qt::CaseInsensitive);
-
- ret = qVariantFromValue(realRe);
- dist = 0;
- } else {
- qConvDebug() << "couldn't parse a JS regexp";
- }
- } else if (type == String) {
- UString ustring = value->toString(exec);
- QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
-
- QRegExp re(qstring);
- if (re.isValid()) {
- ret = qVariantFromValue(re);
- dist = 10;
- }
- }
- break;
-
- case QMetaType::QObjectStar:
- if (type == QObj) {
- JSObject* object = value->toObject(exec);
- QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
- if (qtinst) {
- if (qtinst->getObject()) {
- qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
- ret = qVariantFromValue(qtinst->getObject());
- qConvDebug() << ret;
- dist = 0;
- } else {
- qConvDebug() << "can't convert deleted qobject";
- }
- } else {
- qConvDebug() << "wasn't a qtinstance";
- }
- } else if (type == Null) {
- QObject* nullobj = 0;
- ret = qVariantFromValue(nullobj);
- dist = 0;
- } else {
- qConvDebug() << "previous type was not an object:" << type;
- }
- break;
-
- case QMetaType::VoidStar:
- if (type == QObj) {
- JSObject* object = value->toObject(exec);
- QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
- if (qtinst) {
- if (qtinst->getObject()) {
- qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
- ret = qVariantFromValue((void *)qtinst->getObject());
- qConvDebug() << ret;
- dist = 0;
- } else {
- qConvDebug() << "can't convert deleted qobject";
- }
- } else {
- qConvDebug() << "wasn't a qtinstance";
- }
- } else if (type == Null) {
- ret = qVariantFromValue((void*)0);
- dist = 0;
- } else if (type == Number) {
- // I don't think that converting a double to a pointer is a wise
- // move. Except maybe 0.
- qConvDebug() << "got number for void * - not converting, seems unsafe:" << value->toNumber(exec);
- } else {
- qConvDebug() << "void* - unhandled type" << type;
- }
- break;
-
- default:
- // Non const type ids
- if (hint == (QMetaType::Type) qMetaTypeId<QObjectList>())
- {
- if (type == Array) {
- JSObject* object = value->toObject(exec);
- ArrayInstance* array = static_cast<ArrayInstance *>(object);
-
- QObjectList result;
- int len = array->getLength();
- for (int i = 0; i < len; ++i) {
- JSValue *val = array->getItem(i);
- int itemdist = -1;
- QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist);
- if (itemdist >= 0)
- result.append(item.value<QObject*>());
- else
- break;
- }
- // If we didn't fail conversion
- if (result.count() == len) {
- dist = 5;
- ret = QVariant::fromValue(result);
- } else {
- qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
- }
- } else {
- // Make a single length array
- QObjectList result;
- int itemdist = -1;
- QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist);
- if (itemdist >= 0) {
- result.append(item.value<QObject*>());
- dist = 10;
- ret = QVariant::fromValue(result);
- }
- }
- break;
- } else if (hint == (QMetaType::Type) qMetaTypeId<QList<int> >()) {
- if (type == Array) {
- JSObject* object = value->toObject(exec);
- ArrayInstance* array = static_cast<ArrayInstance *>(object);
-
- QList<int> result;
- int len = array->getLength();
- for (int i = 0; i < len; ++i) {
- JSValue* val = array->getItem(i);
- int itemdist = -1;
- QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist);
- if (itemdist >= 0)
- result.append(item.value<int>());
- else
- break;
- }
- // If we didn't fail conversion
- if (result.count() == len) {
- dist = 5;
- ret = QVariant::fromValue(result);
- } else {
- qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
- }
- } else {
- // Make a single length array
- QList<int> result;
- int itemdist = -1;
- QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist);
- if (itemdist >= 0) {
- result.append(item.value<int>());
- dist = 10;
- ret = QVariant::fromValue(result);
- }
- }
- break;
- } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
- // Well.. we can do anything... just recurse with the autodetect flag
- ret = convertValueToQVariant(exec, value, QMetaType::Void, distance);
- dist = 10;
- break;
- }
-
- dist = 10;
- break;
- }
-
- if (!ret.isValid())
- dist = -1;
- if (distance)
- *distance = dist;
-
- return ret;
-}
-
-JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
-{
- // Variants with QObject * can be isNull but not a null pointer
- // An empty QString variant is also null
- QMetaType::Type type = (QMetaType::Type) variant.userType();
- if (variant.isNull() &&
- type != QMetaType::QObjectStar &&
- type != QMetaType::VoidStar &&
- type != QMetaType::QWidgetStar &&
- type != QMetaType::QString) {
- return jsNull();
- }
-
- JSLock lock;
-
- if (type == QMetaType::Bool)
- return jsBoolean(variant.toBool());
-
- if (type == QMetaType::Int ||
- type == QMetaType::UInt ||
- type == QMetaType::Long ||
- type == QMetaType::ULong ||
- type == QMetaType::LongLong ||
- type == QMetaType::ULongLong ||
- type == QMetaType::Short ||
- type == QMetaType::UShort ||
- type == QMetaType::Float ||
- type == QMetaType::Double)
- return jsNumber(variant.toDouble());
-
- if (type == QMetaType::QRegExp) {
- QRegExp re = variant.value<QRegExp>();
-
- if (re.isValid()) {
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
- List args;
- UString uflags;
-
- if (re.caseSensitivity() == Qt::CaseInsensitive)
- uflags = "i"; // ### Can't do g or m
- UString ustring((KJS::UChar*)re.pattern().utf16(), re.pattern().length());
- args.append(jsString(ustring));
- args.append(jsString(uflags));
- return regExpObj->construct(exec, args);
- }
- }
-
- if (type == QMetaType::QDateTime ||
- type == QMetaType::QDate ||
- type == QMetaType::QTime) {
- DateObjectImp *dateObj = static_cast<DateObjectImp*>(exec->lexicalGlobalObject()->dateConstructor());
- List args;
-
- QDate date = QDate::currentDate();
- QTime time(0,0,0); // midnight
-
- if (type == QMetaType::QDate)
- date = variant.value<QDate>();
- else if (type == QMetaType::QTime)
- time = variant.value<QTime>();
- else {
- QDateTime dt = variant.value<QDateTime>().toLocalTime();
- date = dt.date();
- time = dt.time();
- }
-
- // Dates specified this way are in local time (we convert DateTimes above)
- args.append(jsNumber(date.year()));
- args.append(jsNumber(date.month() - 1));
- args.append(jsNumber(date.day()));
- args.append(jsNumber(time.hour()));
- args.append(jsNumber(time.minute()));
- args.append(jsNumber(time.second()));
- args.append(jsNumber(time.msec()));
- return dateObj->construct(exec, args);
- }
-
- if (type == QMetaType::QByteArray) {
- QByteArray ba = variant.value<QByteArray>();
- UString ustring(ba.constData());
- return jsString(ustring);
- }
-
- if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
- QObject* obj = variant.value<QObject*>();
- return Instance::createRuntimeObject(Instance::QtLanguage, obj, root);
- }
-
- if (type == QMetaType::QVariantMap) {
- // create a new object, and stuff properties into it
- JSObject* ret = new JSObject(exec->lexicalGlobalObject()->objectPrototype());
- QVariantMap map = variant.value<QVariantMap>();
- QVariantMap::const_iterator i = map.constBegin();
- while (i != map.constEnd()) {
- QString s = i.key();
- JSValue* val = convertQVariantToValue(exec, root, i.value());
- if (val)
- ret->put(exec, Identifier((const UChar *)s.constData(), s.length()), val);
- // ### error case?
- ++i;
- }
-
- return ret;
- }
-
- // List types
- if (type == QMetaType::QVariantList) {
- QVariantList vl = variant.toList();
- return new RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
- } else if (type == QMetaType::QStringList) {
- QStringList sl = variant.value<QStringList>();
- return new RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
- } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
- QObjectList ol= variant.value<QObjectList>();
- return new RuntimeArray(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
- } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
- QList<int> il= variant.value<QList<int> >();
- return new RuntimeArray(exec, new QtArray<int>(il, QMetaType::Int, root));
- }
-
- if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
- QVariant real = variant.value<QVariant>();
- qConvDebug() << "real variant is:" << real;
- return convertQVariantToValue(exec, root, real);
- }
-
- qConvDebug() << "fallback path for" << variant << variant.userType();
-
- QString string = variant.toString();
- UString ustring((KJS::UChar*)string.utf16(), string.length());
- return jsString(ustring);
-}
-
-// ===============
-
-// Qt-like macros
-#define QW_D(Class) Class##Data* d = d_func()
-#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
-
-QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState *exec, const Identifier &ident, PassRefPtr<QtInstance> inst)
- : InternalFunctionImp (static_cast<FunctionPrototype*>(exec->lexicalGlobalObject()->functionPrototype()), ident)
- , d_ptr(dd)
-{
- QW_D(QtRuntimeMethod);
- d->m_instance = inst;
-}
-
-QtRuntimeMethod::~QtRuntimeMethod()
-{
- delete d_ptr;
-}
-
-CodeType QtRuntimeMethod::codeType() const
-{
- return FunctionCode;
-}
-
-Completion QtRuntimeMethod::execute(ExecState*)
-{
- return Completion(Normal, jsUndefined());
-}
-
-// ===============
-
-QtRuntimeMethodData::~QtRuntimeMethodData()
-{
-}
-
-QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData()
-{
-
-}
-
-QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData()
-{
-
-}
-
-// ===============
-
-// Type conversion metadata (from QtScript originally)
-class QtMethodMatchType
-{
-public:
- enum Kind {
- Invalid,
- Variant,
- MetaType,
- Unresolved,
- MetaEnum
- };
-
-
- QtMethodMatchType()
- : m_kind(Invalid) { }
-
- Kind kind() const
- { return m_kind; }
-
- QMetaType::Type typeId() const;
-
- bool isValid() const
- { return (m_kind != Invalid); }
-
- bool isVariant() const
- { return (m_kind == Variant); }
-
- bool isMetaType() const
- { return (m_kind == MetaType); }
-
- bool isUnresolved() const
- { return (m_kind == Unresolved); }
-
- bool isMetaEnum() const
- { return (m_kind == MetaEnum); }
-
- QByteArray name() const;
-
- int enumeratorIndex() const
- { Q_ASSERT(isMetaEnum()); return m_typeId; }
-
- static QtMethodMatchType variant()
- { return QtMethodMatchType(Variant); }
-
- static QtMethodMatchType metaType(int typeId, const QByteArray &name)
- { return QtMethodMatchType(MetaType, typeId, name); }
-
- static QtMethodMatchType metaEnum(int enumIndex, const QByteArray &name)
- { return QtMethodMatchType(MetaEnum, enumIndex, name); }
-
- static QtMethodMatchType unresolved(const QByteArray &name)
- { return QtMethodMatchType(Unresolved, /*typeId=*/0, name); }
-
-private:
- QtMethodMatchType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
- : m_kind(kind), m_typeId(typeId), m_name(name) { }
-
- Kind m_kind;
- int m_typeId;
- QByteArray m_name;
-};
-
-QMetaType::Type QtMethodMatchType::typeId() const
-{
- if (isVariant())
- return (QMetaType::Type) QMetaType::type("QVariant");
- return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId);
-}
-
-QByteArray QtMethodMatchType::name() const
-{
- if (!m_name.isEmpty())
- return m_name;
- else if (m_kind == Variant)
- return "QVariant";
- return QByteArray();
-}
-
-struct QtMethodMatchData
-{
- int matchDistance;
- int index;
- QVector<QtMethodMatchType> types;
- QVarLengthArray<QVariant, 10> args;
-
- QtMethodMatchData(int dist, int idx, QVector<QtMethodMatchType> typs,
- const QVarLengthArray<QVariant, 10> &as)
- : matchDistance(dist), index(idx), types(typs), args(as) { }
- QtMethodMatchData()
- : index(-1) { }
-
- bool isValid() const
- { return (index != -1); }
-
- int firstUnresolvedIndex() const
- {
- for (int i=0; i < types.count(); i++) {
- if (types.at(i).isUnresolved())
- return i;
- }
- return -1;
- }
-};
-
-static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
-{
- QByteArray scope;
- QByteArray name;
- int scopeIdx = str.indexOf("::");
- if (scopeIdx != -1) {
- scope = str.left(scopeIdx);
- name = str.mid(scopeIdx + 2);
- } else {
- name = str;
- }
- for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = meta->enumerator(i);
- if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/)
- return i;
- }
- return -1;
-}
-
-// Helper function for resolving methods
-// Largely based on code in QtScript for compatibility reasons
-static int findMethodIndex(ExecState* exec,
- const QMetaObject* meta,
- const QByteArray& signature,
- bool allowPrivate,
- const List& jsArgs,
- QVarLengthArray<QVariant, 10> &vars,
- void** vvars,
- JSObject **pError)
-{
- QList<int> matchingIndices;
-
- bool overloads = !signature.contains('(');
-
- int count = meta->methodCount();
- for (int i = count - 1; i >= 0; --i) {
- const QMetaMethod m = meta->method(i);
-
- // Don't choose private methods
- if (m.access() == QMetaMethod::Private && !allowPrivate)
- continue;
-
- // try and find all matching named methods
- if (m.signature() == signature)
- matchingIndices.append(i);
- else if (overloads) {
- QByteArray rawsignature = m.signature();
- rawsignature.truncate(rawsignature.indexOf('('));
- if (rawsignature == signature)
- matchingIndices.append(i);
- }
- }
-
- int chosenIndex = -1;
- *pError = 0;
- QVector<QtMethodMatchType> chosenTypes;
-
- QVarLengthArray<QVariant, 10> args;
- QVector<QtMethodMatchData> candidates;
- QVector<QtMethodMatchData> unresolved;
- QVector<int> tooFewArgs;
- QVector<int> conversionFailed;
-
- foreach(int index, matchingIndices) {
- QMetaMethod method = meta->method(index);
-
- QVector<QtMethodMatchType> types;
- bool unresolvedTypes = false;
-
- // resolve return type
- QByteArray returnTypeName = method.typeName();
- int rtype = QMetaType::type(returnTypeName);
- if ((rtype == 0) && !returnTypeName.isEmpty()) {
- if (returnTypeName == "QVariant") {
- types.append(QtMethodMatchType::variant());
- } else if (returnTypeName.endsWith('*')) {
- types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName));
- } else {
- int enumIndex = indexOfMetaEnum(meta, returnTypeName);
- if (enumIndex != -1)
- types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName));
- else {
- unresolvedTypes = true;
- types.append(QtMethodMatchType::unresolved(returnTypeName));
- }
- }
- } else {
- if (returnTypeName == "QVariant")
- types.append(QtMethodMatchType::variant());
- else
- types.append(QtMethodMatchType::metaType(rtype, returnTypeName));
- }
-
- // resolve argument types
- QList<QByteArray> parameterTypeNames = method.parameterTypes();
- for (int i = 0; i < parameterTypeNames.count(); ++i) {
- QByteArray argTypeName = parameterTypeNames.at(i);
- int atype = QMetaType::type(argTypeName);
- if (atype == 0) {
- if (argTypeName == "QVariant") {
- types.append(QtMethodMatchType::variant());
- } else {
- int enumIndex = indexOfMetaEnum(meta, argTypeName);
- if (enumIndex != -1)
- types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName));
- else {
- unresolvedTypes = true;
- types.append(QtMethodMatchType::unresolved(argTypeName));
- }
- }
- } else {
- if (argTypeName == "QVariant")
- types.append(QtMethodMatchType::variant());
- else
- types.append(QtMethodMatchType::metaType(atype, argTypeName));
- }
- }
-
- if (jsArgs.size() < (types.count() - 1)) {
- qMatchDebug() << "Match:too few args for" << method.signature();
- tooFewArgs.append(index);
- continue;
- }
-
- if (unresolvedTypes) {
- qMatchDebug() << "Match:unresolved arg types for" << method.signature();
- // remember it so we can give an error message later, if necessary
- unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index,
- types, QVarLengthArray<QVariant, 10>()));
- continue;
- }
-
- // Now convert arguments
- if (args.count() != types.count())
- args.resize(types.count());
-
- QtMethodMatchType retType = types[0];
- args[0] = QVariant(retType.typeId(), (void *)0); // the return value
-
- bool converted = true;
- int matchDistance = 0;
- for (int i = 0; converted && i < types.count() - 1; ++i) {
- JSValue* arg = i < jsArgs.size() ? jsArgs[i] : jsUndefined();
-
- int argdistance = -1;
- QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance);
- if (argdistance >= 0) {
- matchDistance += argdistance;
- args[i+1] = v;
- } else {
- qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId());
- converted = false;
- }
- }
-
- qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
-
- if (converted) {
- if ((jsArgs.size() == types.count() - 1)
- && (matchDistance == 0)) {
- // perfect match, use this one
- chosenIndex = index;
- break;
- } else {
- QtMethodMatchData metaArgs(matchDistance, index, types, args);
- if (candidates.isEmpty()) {
- candidates.append(metaArgs);
- } else {
- QtMethodMatchData otherArgs = candidates.at(0);
- if ((args.count() > otherArgs.args.count())
- || ((args.count() == otherArgs.args.count())
- && (matchDistance <= otherArgs.matchDistance))) {
- candidates.prepend(metaArgs);
- } else {
- candidates.append(metaArgs);
- }
- }
- }
- } else {
- conversionFailed.append(index);
- }
-
- if (!overloads)
- break;
- }
-
- if (chosenIndex == -1 && candidates.count() == 0) {
- // No valid functions at all - format an error message
- if (!conversionFailed.isEmpty()) {
- QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
- .arg(QLatin1String(signature));
- for (int i = 0; i < conversionFailed.size(); ++i) {
- if (i > 0)
- message += QLatin1String("\n");
- QMetaMethod mtd = meta->method(conversionFailed.at(i));
- message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
- }
- *pError = throwError(exec, TypeError, message.toLatin1().constData());
- } else if (!unresolved.isEmpty()) {
- QtMethodMatchData argsInstance = unresolved.first();
- int unresolvedIndex = argsInstance.firstUnresolvedIndex();
- Q_ASSERT(unresolvedIndex != -1);
- QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex);
- QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
- .arg(QString::fromLatin1(signature))
- .arg(QLatin1String(unresolvedType.name()));
- *pError = throwError(exec, TypeError, message.toLatin1().constData());
- } else {
- QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
- .arg(QLatin1String(signature));
- for (int i = 0; i < tooFewArgs.size(); ++i) {
- if (i > 0)
- message += QLatin1String("\n");
- QMetaMethod mtd = meta->method(tooFewArgs.at(i));
- message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
- }
- *pError = throwError(exec, SyntaxError, message.toLatin1().constData());
- }
- }
-
- if (chosenIndex == -1 && candidates.count() > 0) {
- QtMethodMatchData metaArgs = candidates.at(0);
- if ((candidates.size() > 1)
- && (metaArgs.args.count() == candidates.at(1).args.count())
- && (metaArgs.matchDistance == candidates.at(1).matchDistance)) {
- // ambiguous call
- QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
- .arg(QLatin1String(signature));
- for (int i = 0; i < candidates.size(); ++i) {
- if (i > 0)
- message += QLatin1String("\n");
- QMetaMethod mtd = meta->method(candidates.at(i).index);
- message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
- }
- *pError = throwError(exec, TypeError, message.toLatin1().constData());
- } else {
- chosenIndex = metaArgs.index;
- args = metaArgs.args;
- }
- }
-
- if (chosenIndex != -1) {
- /* Copy the stuff over */
- int i;
- vars.resize(args.count());
- for (i=0; i < args.count(); i++) {
- vars[i] = args[i];
- vvars[i] = vars[i].data();
- }
- }
-
- return chosenIndex;
-}
-
-// Signals are not fuzzy matched as much as methods
-static int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature)
-{
- int index = initialIndex;
- QMetaMethod method = meta->method(index);
- bool overloads = !signature.contains('(');
- if (overloads && (method.attributes() & QMetaMethod::Cloned)) {
- // find the most general method
- do {
- method = meta->method(--index);
- } while (method.attributes() & QMetaMethod::Cloned);
- }
- return index;
-}
-
-QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate)
- : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst)
-{
- QW_D(QtRuntimeMetaMethod);
- d->m_signature = signature;
- d->m_index = index;
- d->m_connect = 0;
- d->m_disconnect = 0;
- d->m_allowPrivate = allowPrivate;
-}
-
-void QtRuntimeMetaMethod::mark()
-{
- QtRuntimeMethod::mark();
- QW_D(QtRuntimeMetaMethod);
- if (d->m_connect)
- d->m_connect->mark();
- if (d->m_disconnect)
- d->m_disconnect->mark();
-}
-
-JSValue* QtRuntimeMetaMethod::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- QW_D(QtRuntimeMetaMethod);
-
- // We're limited to 10 args
- if (args.size() > 10)
- return jsUndefined();
-
- // We have to pick a method that matches..
- JSLock lock;
-
- QObject *obj = d->m_instance->getObject();
- if (obj) {
- QVarLengthArray<QVariant, 10> vargs;
- void *qargs[11];
-
- int methodIndex;
- JSObject* errorObj = 0;
- if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, args, vargs, (void **)qargs, &errorObj)) != -1) {
- if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
- return jsUndefined();
-
- if (vargs[0].isValid())
- return convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0]);
- }
-
- if (errorObj)
- return errorObj;
- } else {
- return throwError(exec, GeneralError, "cannot call function of deleted QObject");
- }
-
- // void functions return undefined
- return jsUndefined();
-}
-
-bool QtRuntimeMetaMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == "connect") {
- slot.setCustom(this, connectGetter);
- return true;
- } else if (propertyName == "disconnect") {
- slot.setCustom(this, disconnectGetter);
- return true;
- } else if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-JSValue *QtRuntimeMetaMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
-{
- // QtScript always returns 0
- return jsNumber(0);
-}
-
-JSValue *QtRuntimeMetaMethod::connectGetter(ExecState* exec, JSObject*, const Identifier& ident, const PropertySlot& slot)
-{
- QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(slot.slotBase());
- QW_DS(QtRuntimeMetaMethod, thisObj);
-
- if (!d->m_connect)
- d->m_connect = new QtRuntimeConnectionMethod(exec, ident, true, d->m_instance, d->m_index, d->m_signature);
- return d->m_connect;
-}
-
-JSValue* QtRuntimeMetaMethod::disconnectGetter(ExecState* exec, JSObject*, const Identifier& ident, const PropertySlot& slot)
-{
- QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(slot.slotBase());
- QW_DS(QtRuntimeMetaMethod, thisObj);
-
- if (!d->m_disconnect)
- d->m_disconnect = new QtRuntimeConnectionMethod(exec, ident, false, d->m_instance, d->m_index, d->m_signature);
- return d->m_disconnect;
-}
-
-// ===============
-
-QMultiMap<QObject*, QtConnectionObject*> QtRuntimeConnectionMethod::connections;
-
-QtRuntimeConnectionMethod::QtRuntimeConnectionMethod(ExecState* exec, const Identifier& ident, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature)
- : QtRuntimeMethod (new QtRuntimeConnectionMethodData(), exec, ident, inst)
-{
- QW_D(QtRuntimeConnectionMethod);
-
- d->m_signature = signature;
- d->m_index = index;
- d->m_isConnect = isConnect;
-}
-
-JSValue *QtRuntimeConnectionMethod::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- QW_D(QtRuntimeConnectionMethod);
-
- JSLock lock;
-
- QObject* sender = d->m_instance->getObject();
-
- if (sender) {
-
- JSObject* thisObject = exec->lexicalGlobalObject();
- JSObject* funcObject = 0;
-
- // QtScript checks signalness first, arguments second
- int signalIndex = -1;
-
- // Make sure the initial index is a signal
- QMetaMethod m = sender->metaObject()->method(d->m_index);
- if (m.methodType() == QMetaMethod::Signal)
- signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_signature);
-
- if (signalIndex != -1) {
- if (args.size() == 1) {
- funcObject = args[0]->toObject(exec);
- if (!funcObject->implementsCall()) {
- if (d->m_isConnect)
- return throwError(exec, TypeError, "QtMetaMethod.connect: target is not a function");
- else
- return throwError(exec, TypeError, "QtMetaMethod.disconnect: target is not a function");
- }
- } else if (args.size() >= 2) {
- if (args[0]->type() == ObjectType) {
- thisObject = args[0]->toObject(exec);
-
- // Get the actual function to call
- JSObject *asObj = args[1]->toObject(exec);
- if (asObj->implementsCall()) {
- // Function version
- funcObject = asObj;
- } else {
- // Convert it to a string
- UString funcName = args[1]->toString(exec);
- Identifier funcIdent(funcName);
-
- // ### DropAllLocks
- // This is resolved at this point in QtScript
- JSValue* val = thisObject->get(exec, funcIdent);
- JSObject* asFuncObj = val->toObject(exec);
-
- if (asFuncObj->implementsCall()) {
- funcObject = asFuncObj;
- } else {
- if (d->m_isConnect)
- return throwError(exec, TypeError, "QtMetaMethod.connect: target is not a function");
- else
- return throwError(exec, TypeError, "QtMetaMethod.disconnect: target is not a function");
- }
- }
- } else {
- if (d->m_isConnect)
- return throwError(exec, TypeError, "QtMetaMethod.connect: thisObject is not an object");
- else
- return throwError(exec, TypeError, "QtMetaMethod.disconnect: thisObject is not an object");
- }
- } else {
- if (d->m_isConnect)
- return throwError(exec, GeneralError, "QtMetaMethod.connect: no arguments given");
- else
- return throwError(exec, GeneralError, "QtMetaMethod.disconnect: no arguments given");
- }
-
- if (d->m_isConnect) {
- // to connect, we need:
- // target object [from ctor]
- // target signal index etc. [from ctor]
- // receiver function [from arguments]
- // receiver this object [from arguments]
-
- QtConnectionObject* conn = new QtConnectionObject(d->m_instance, signalIndex, thisObject, funcObject);
- bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
- if (!ok) {
- delete conn;
- QString msg = QString("QtMetaMethod.connect: failed to connect to %1::%2()")
- .arg(sender->metaObject()->className())
- .arg(QLatin1String(d->m_signature));
- return throwError(exec, GeneralError, msg.toLatin1().constData());
- }
- else {
- // Store connection
- connections.insert(sender, conn);
- }
- } else {
- // Now to find our previous connection object. Hmm.
- QList<QtConnectionObject*> conns = connections.values(sender);
- bool ret = false;
-
- foreach(QtConnectionObject* conn, conns) {
- // Is this the right connection?
- if (conn->match(sender, signalIndex, thisObject, funcObject)) {
- // Yep, disconnect it
- QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
- delete conn; // this will also remove it from the map
- ret = true;
- break;
- }
- }
-
- if (!ret) {
- QString msg = QString("QtMetaMethod.disconnect: failed to disconnect from %1::%2()")
- .arg(sender->metaObject()->className())
- .arg(QLatin1String(d->m_signature));
- return throwError(exec, GeneralError, msg.toLatin1().constData());
- }
- }
- } else {
- QString msg = QString("QtMetaMethod.%1: %2::%3() is not a signal")
- .arg(d->m_isConnect ? "connect": "disconnect")
- .arg(sender->metaObject()->className())
- .arg(QLatin1String(d->m_signature));
- return throwError(exec, TypeError, msg.toLatin1().constData());
- }
- } else {
- return throwError(exec, GeneralError, "cannot call function of deleted QObject");
- }
-
- return jsUndefined();
-}
-
-bool QtRuntimeConnectionMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-JSValue *QtRuntimeConnectionMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
-{
- // we have one formal argument, and one optional
- return jsNumber(1);
-}
-
-// ===============
-
-QtConnectionObject::QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject)
- : m_instance(instance)
- , m_signalIndex(signalIndex)
- , m_originalObject(m_instance->getObject())
- , m_thisObject(thisObject)
- , m_funcObject(funcObject)
-{
- setParent(m_originalObject);
- ASSERT(JSLock::currentThreadIsHoldingLock()); // so our ProtectedPtrs are safe
-}
-
-QtConnectionObject::~QtConnectionObject()
-{
- // Remove us from the map of active connections
- QtRuntimeConnectionMethod::connections.remove(m_originalObject, this);
-}
-
-static const uint qt_meta_data_QtConnectionObject[] = {
-
- // content:
- 1, // revision
- 0, // classname
- 0, 0, // classinfo
- 1, 10, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
-
- // slots: signature, parameters, type, tag, flags
- 28, 27, 27, 27, 0x0a,
-
- 0 // eod
-};
-
-static const char qt_meta_stringdata_QtConnectionObject[] = {
- "KJS::Bindings::QtConnectionObject\0\0execute()\0"
-};
-
-const QMetaObject QtConnectionObject::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_QtConnectionObject,
- qt_meta_data_QtConnectionObject, 0 }
-};
-
-const QMetaObject *QtConnectionObject::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *QtConnectionObject::qt_metacast(const char *_clname)
-{
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_QtConnectionObject))
- return static_cast<void*>(const_cast<QtConnectionObject*>(this));
- return QObject::qt_metacast(_clname);
-}
-
-int QtConnectionObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QObject::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- switch (_id) {
- case 0: execute(_a); break;
- }
- _id -= 1;
- }
- return _id;
-}
-
-void QtConnectionObject::execute(void **argv)
-{
- QObject* obj = m_instance->getObject();
- if (obj) {
- const QMetaObject* meta = obj->metaObject();
- const QMetaMethod method = meta->method(m_signalIndex);
-
- QList<QByteArray> parameterTypes = method.parameterTypes();
-
- int argc = parameterTypes.count();
-
- JSLock lock;
-
- // ### Should the Interpreter/ExecState come from somewhere else?
- RefPtr<RootObject> ro = m_instance->rootObject();
- if (ro) {
- JSGlobalObject* globalobj = ro->globalObject();
- if (globalobj) {
- ExecState* exec = globalobj->globalExec();
- if (exec) {
- // Build the argument list (up to the formal argument length of the slot)
- List l;
- // ### DropAllLocks?
- int funcArgC = m_funcObject->get(exec, exec->propertyNames().length)->toInt32(exec);
- int argTotal = qMax(funcArgC, argc);
- for(int i=0; i < argTotal; i++) {
- if (i < argc) {
- int argType = QMetaType::type(parameterTypes.at(i));
- l.append(convertQVariantToValue(exec, ro, QVariant(argType, argv[i+1])));
- } else {
- l.append(jsUndefined());
- }
- }
- // Stuff in the __qt_sender property, if we can
- if (m_funcObject->inherits(&FunctionImp::info)) {
- FunctionImp* fimp = static_cast<FunctionImp*>(m_funcObject.get());
-
- JSObject* qt_sender = Instance::createRuntimeObject(Instance::QtLanguage, sender(), ro);
- JSObject* wrapper = new JSObject();
- wrapper->put(exec, "__qt_sender__", qt_sender);
- ScopeChain oldsc = fimp->scope();
- ScopeChain sc = oldsc;
- sc.push(wrapper);
- fimp->setScope(sc);
- fimp->call(exec, m_thisObject, l);
- fimp->setScope(oldsc);
- } else
- m_funcObject->call(exec, m_thisObject, l);
- }
- }
- }
- } else {
- // A strange place to be - a deleted object emitted a signal here.
- qWarning() << "sender deleted, cannot deliver signal";
- }
-}
-
-bool QtConnectionObject::match(QObject* sender, int signalIndex, JSObject* thisObject, JSObject *funcObject)
-{
- if (m_originalObject == sender && m_signalIndex == signalIndex
- && thisObject == (JSObject*)m_thisObject && funcObject == (JSObject*)m_funcObject)
- return true;
- return false;
-}
-
-// ===============
-
-template <typename T> QtArray<T>::QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject> rootObject)
- : Array(rootObject)
- , m_list(list)
- , m_type(type)
-{
- m_length = m_list.count();
-}
-
-template <typename T> QtArray<T>::~QtArray ()
-{
-}
-
-template <typename T> RootObject* QtArray<T>::rootObject() const
-{
- return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
-}
-
-template <typename T> void QtArray<T>::setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const
-{
- // QtScript sets the value, but doesn't forward it to the original source
- // (e.g. if you do 'object.intList[5] = 6', the object is not updated, but the
- // copy of the list is).
- int dist = -1;
- QVariant val = convertValueToQVariant(exec, aValue, m_type, &dist);
-
- if (dist >= 0) {
- m_list[index] = val.value<T>();
- }
-}
-
-
-template <typename T> JSValue* QtArray<T>::valueAt(ExecState *exec, unsigned int index) const
-{
- if (index < m_length) {
- T val = m_list.at(index);
- return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
- }
-
- return jsUndefined();
-}
-
-// ===============
-
-} }
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef BINDINGS_QT_RUNTIME_H_
-#define BINDINGS_QT_RUNTIME_H_
-
-#include "runtime.h"
-#include "runtime_method.h"
-#include "protect.h"
-
-#include <qbytearray.h>
-#include <qmetaobject.h>
-#include <qpointer.h>
-
-namespace KJS {
-namespace Bindings {
-
-class QtInstance;
-
-class QtField : public Field {
-public:
-
- typedef enum {
- MetaProperty,
- DynamicProperty,
- ChildObject
- } QtFieldType;
-
- QtField(const QMetaProperty &p)
- : m_type(MetaProperty), m_property(p)
- {}
-
- QtField(const QByteArray &b)
- : m_type(DynamicProperty), m_dynamicProperty(b)
- {}
-
- QtField(QObject *child)
- : m_type(ChildObject), m_childObject(child)
- {}
-
- virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
- virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
- virtual const char* name() const;
- QtFieldType fieldType() const {return m_type;}
-private:
- QtFieldType m_type;
- QByteArray m_dynamicProperty;
- QMetaProperty m_property;
- QPointer<QObject> m_childObject;
-};
-
-
-class QtMethod : public Method
-{
-public:
- QtMethod(const QMetaObject *mo, int i, const QByteArray &ident, int numParameters)
- : m_metaObject(mo),
- m_index(i),
- m_identifier(ident),
- m_nParams(numParameters)
- { }
-
- virtual const char* name() const { return m_identifier.constData(); }
- virtual int numParameters() const { return m_nParams; }
-
-private:
- friend class QtInstance;
- const QMetaObject *m_metaObject;
- int m_index;
- QByteArray m_identifier;
- int m_nParams;
-};
-
-
-template <typename T> class QtArray : public Array
-{
-public:
- QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject>);
- virtual ~QtArray();
-
- RootObject* rootObject() const;
-
- virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const;
- virtual JSValue *valueAt(ExecState *exec, unsigned int index) const;
- virtual unsigned int getLength() const {return m_length;}
-
-private:
- mutable QList<T> m_list; // setValueAt is const!
- unsigned int m_length;
- QMetaType::Type m_type;
-};
-
-// Based on RuntimeMethod
-
-// Extra data classes (to avoid the CELL_SIZE limit on JS objects)
-
-class QtRuntimeMethodData {
- public:
- virtual ~QtRuntimeMethodData();
- RefPtr<QtInstance> m_instance;
-};
-
-class QtRuntimeConnectionMethod;
-class QtRuntimeMetaMethodData : public QtRuntimeMethodData {
- public:
- ~QtRuntimeMetaMethodData();
- QByteArray m_signature;
- bool m_allowPrivate;
- int m_index;
- QtRuntimeConnectionMethod *m_connect;
- QtRuntimeConnectionMethod *m_disconnect;
-};
-
-class QtRuntimeConnectionMethodData : public QtRuntimeMethodData {
- public:
- ~QtRuntimeConnectionMethodData();
- QByteArray m_signature;
- int m_index;
- bool m_isConnect;
-};
-
-// Common base class (doesn't really do anything interesting)
-class QtRuntimeMethod : public InternalFunctionImp
-{
-public:
- virtual ~QtRuntimeMethod();
-
- virtual CodeType codeType() const;
- virtual Completion execute(ExecState *exec);
-
-protected:
- QtRuntimeMethodData *d_func() const {return d_ptr;}
- QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst);
- QtRuntimeMethodData *d_ptr;
-};
-
-class QtRuntimeMetaMethod : public QtRuntimeMethod
-{
-public:
- QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate);
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
- virtual void mark();
-
-protected:
- QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
-
-private:
- static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue *connectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue *disconnectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
-};
-
-class QtConnectionObject;
-class QtRuntimeConnectionMethod : public QtRuntimeMethod
-{
-public:
- QtRuntimeConnectionMethod(ExecState *exec, const Identifier &n, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature );
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
-protected:
- QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
-
-private:
- static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static QMultiMap<QObject *, QtConnectionObject *> connections;
- friend class QtConnectionObject;
-};
-
-class QtConnectionObject: public QObject
-{
-public:
- QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject);
- ~QtConnectionObject();
-
- static const QMetaObject staticMetaObject;
- virtual const QMetaObject *metaObject() const;
- virtual void *qt_metacast(const char *);
- virtual int qt_metacall(QMetaObject::Call, int, void **argv);
-
- bool match(QObject *sender, int signalIndex, JSObject* thisObject, JSObject *funcObject);
-
- // actual slot:
- void execute(void **argv);
-
-private:
- RefPtr<QtInstance> m_instance;
- int m_signalIndex;
- QObject* m_originalObject; // only used as a key, not dereferenced
- ProtectedPtr<JSObject> m_thisObject;
- ProtectedPtr<JSObject> m_funcObject;
-};
-
-} // namespace Bindings
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "runtime.h"
-
-#include "JSLock.h"
-#if ENABLE(NETSCAPE_API)
-#include "NP_jsobject.h"
-#include "c_instance.h"
-#endif
-#include "runtime_object.h"
-#include "runtime_root.h"
-
-#if HAVE(JNI)
-#include "jni_instance.h"
-#endif
-#include "objc_instance.h"
-#if PLATFORM(QT)
-#include "qt_instance.h"
-#endif
-
-namespace KJS { namespace Bindings {
-
-Array::Array(PassRefPtr<RootObject> rootObject)
- : _rootObject(rootObject)
-{
- ASSERT(_rootObject);
-}
-
-Array::~Array()
-{
-}
-
-Instance::Instance(PassRefPtr<RootObject> rootObject)
- : _rootObject(rootObject)
- , _refCount(0)
-{
- ASSERT(_rootObject);
-}
-
-Instance::~Instance()
-{
-}
-
-static KJSDidExecuteFunctionPtr _DidExecuteFunction;
-
-void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func) { _DidExecuteFunction = func; }
-KJSDidExecuteFunctionPtr Instance::didExecuteFunction() { return _DidExecuteFunction; }
-
-JSValue *Instance::getValueOfField(ExecState *exec, const Field *aField) const
-{
- return aField->valueFromInstance(exec, this);
-}
-
-void Instance::setValueOfField(ExecState *exec, const Field *aField, JSValue *aValue) const
-{
- aField->setValueToInstance(exec, this, aValue);
-}
-
-Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject)
-{
- Instance *newInstance = 0;
-
- switch (language) {
-#if HAVE(JNI)
- case Instance::JavaLanguage: {
- newInstance = new Bindings::JavaInstance((jobject)nativeInstance, rootObject);
- break;
- }
-#endif
- case Instance::ObjectiveCLanguage: {
- newInstance = new Bindings::ObjcInstance((ObjectStructPtr)nativeInstance, rootObject);
- break;
- }
-#if ENABLE(NETSCAPE_API)
- case Instance::CLanguage: {
- newInstance = new Bindings::CInstance((NPObject *)nativeInstance, rootObject);
- break;
- }
-#endif
-#if PLATFORM(QT)
- case Instance::QtLanguage: {
- newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);
- break;
- }
-#endif
- default:
- break;
- }
-
- return newInstance;
-}
-
-JSObject* Instance::createRuntimeObject(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject)
-{
- Instance* instance = Instance::createBindingForLanguageInstance(language, nativeInstance, rootObject);
-
- return createRuntimeObject(instance);
-}
-
-JSObject* Instance::createRuntimeObject(Instance* instance)
-{
-#if PLATFORM(QT)
- if (instance->getBindingLanguage() == QtLanguage)
- return QtInstance::getRuntimeObject(static_cast<QtInstance*>(instance));
-#endif
- JSLock lock;
-
- return new RuntimeObjectImp(instance);
-}
-
-Instance* Instance::getInstance(JSObject* object, BindingLanguage language)
-{
- if (!object)
- return 0;
- if (!object->inherits(&RuntimeObjectImp::info))
- return 0;
- Instance* instance = (static_cast<RuntimeObjectImp*>(object))->getInternalInstance();
- if (!instance)
- return 0;
- if (instance->getBindingLanguage() != language)
- return 0;
- return instance;
-}
-
-RootObject* Instance::rootObject() const
-{
- return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
-}
-
-} } // namespace KJS::Bindings
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JAVASCRIPTCORE_BINDINGS_RUNTIME_H
-#define JAVASCRIPTCORE_BINDINGS_RUNTIME_H
-
-#include "value.h"
-
-#include <wtf/Noncopyable.h>
-#include <wtf/HashMap.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-
-class Identifier;
-class List;
-class PropertyNameArray;
-
-namespace Bindings {
-
-class Instance;
-class Method;
-class RootObject;
-
-typedef Vector<Method*> MethodList;
-
-class Field
-{
-public:
- virtual const char* name() const = 0;
-
- virtual JSValue* valueFromInstance(ExecState*, const Instance*) const = 0;
- virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const = 0;
-
- virtual ~Field() {}
-};
-
-class Method : Noncopyable
-{
-public:
- virtual const char *name() const = 0;
-
- virtual int numParameters() const = 0;
-
- virtual ~Method() {}
-};
-
-class Class : Noncopyable
-{
-public:
- virtual const char *name() const = 0;
-
- virtual MethodList methodsNamed(const Identifier&, Instance*) const = 0;
-
- virtual Field *fieldNamed(const Identifier&, Instance*) const = 0;
-
- virtual JSValue* fallbackObject(ExecState*, Instance*, const Identifier&) { return jsUndefined(); }
-
- virtual ~Class() {}
-};
-
-typedef void (*KJSDidExecuteFunctionPtr)(ExecState*, JSObject* rootObject);
-
-class Instance : Noncopyable {
-public:
- typedef enum {
- JavaLanguage,
- ObjectiveCLanguage,
- CLanguage
-#if PLATFORM(QT)
- , QtLanguage
-#endif
- } BindingLanguage;
-
- Instance(PassRefPtr<RootObject>);
-
- static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func);
- static KJSDidExecuteFunctionPtr didExecuteFunction();
-
- static Instance* createBindingForLanguageInstance(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
- static JSObject* createRuntimeObject(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
- static JSObject* createRuntimeObject(Instance*);
-
- static Instance* getInstance(JSObject*, BindingLanguage);
-
- void ref() { _refCount++; }
- void deref()
- {
- if (--_refCount == 0)
- delete this;
- }
-
- // These functions are called before and after the main entry points into
- // the native implementations. They can be used to establish and cleanup
- // any needed state.
- virtual void begin() {}
- virtual void end() {}
-
- virtual Class *getClass() const = 0;
-
- virtual JSValue* getValueOfField(ExecState*, const Field*) const;
- virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier&, JSType) const { return jsUndefined(); }
- virtual void setValueOfField(ExecState*, const Field*, JSValue*) const;
- virtual bool supportsSetValueOfUndefinedField() { return false; }
- virtual void setValueOfUndefinedField(ExecState*, const Identifier&, JSValue*) {}
-
- virtual bool implementsCall() const { return false; }
-
- virtual JSValue* invokeMethod(ExecState*, const MethodList&, const List& args) = 0;
- virtual JSValue* invokeDefaultMethod(ExecState*, const List&) { return jsUndefined(); }
-
- virtual void getPropertyNames(ExecState*, PropertyNameArray&) { }
-
- virtual JSValue* defaultValue(JSType hint) const = 0;
-
- virtual JSValue* valueOf() const { return jsString(getClass()->name()); }
-
- RootObject* rootObject() const;
-
- virtual ~Instance();
-
- virtual BindingLanguage getBindingLanguage() const = 0;
-
-protected:
- RefPtr<RootObject> _rootObject;
- unsigned _refCount;
-};
-
-class Array : Noncopyable
-{
-public:
- Array(PassRefPtr<RootObject>);
- virtual ~Array();
-
- virtual void setValueAt(ExecState *, unsigned index, JSValue*) const = 0;
- virtual JSValue* valueAt(ExecState *, unsigned index) const = 0;
- virtual unsigned int getLength() const = 0;
-protected:
- RefPtr<RootObject> _rootObject;
-};
-
-const char *signatureForParameters(const List&);
-
-typedef HashMap<RefPtr<UString::Rep>, MethodList*> MethodListMap;
-typedef HashMap<RefPtr<UString::Rep>, Method*> MethodMap;
-typedef HashMap<RefPtr<UString::Rep>, Field*> FieldMap;
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "runtime_array.h"
-
-#include "JSGlobalObject.h"
-#include "array_object.h"
-
-using namespace KJS;
-
-const ClassInfo RuntimeArray::info = { "RuntimeArray", &ArrayInstance::info, 0 };
-
-RuntimeArray::RuntimeArray(ExecState *exec, Bindings::Array *a)
- : JSObject(exec->lexicalGlobalObject()->arrayPrototype())
- , _array(a)
-{
-}
-
-JSValue *RuntimeArray::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
- return jsNumber(thisObj->getLength());
-}
-
-JSValue *RuntimeArray::indexGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
- return thisObj->getConcreteArray()->valueAt(exec, slot.index());
-}
-
-bool RuntimeArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- bool ok;
- unsigned index = propertyName.toArrayIndex(&ok);
- if (ok) {
- if (index < getLength()) {
- slot.setCustomIndex(this, index, indexGetter);
- return true;
- }
- }
-
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-bool RuntimeArray::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
-{
- if (index < getLength()) {
- slot.setCustomIndex(this, index, indexGetter);
- return true;
- }
-
- return JSObject::getOwnPropertySlot(exec, index, slot);
-}
-
-void RuntimeArray::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
-{
- if (propertyName == exec->propertyNames().length) {
- throwError(exec, RangeError);
- return;
- }
-
- bool ok;
- unsigned index = propertyName.toArrayIndex(&ok);
- if (ok) {
- getConcreteArray()->setValueAt(exec, index, value);
- return;
- }
-
- JSObject::put(exec, propertyName, value, attr);
-}
-
-void RuntimeArray::put(ExecState* exec, unsigned index, JSValue* value, int)
-{
- if (index >= getLength()) {
- throwError(exec, RangeError);
- return;
- }
-
- getConcreteArray()->setValueAt(exec, index, value);
-}
-
-bool RuntimeArray::deleteProperty(ExecState*, const Identifier&)
-{
- return false;
-}
-
-bool RuntimeArray::deleteProperty(ExecState*, unsigned)
-{
- return false;
-}
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef RUNTIME_ARRAY_H_
-#define RUNTIME_ARRAY_H_
-
-#include <wtf/OwnPtr.h>
-
-#include "array_instance.h"
-#include "runtime.h"
-
-namespace KJS {
-
-class RuntimeArray : public JSObject {
-public:
- RuntimeArray(ExecState *exec, Bindings::Array *i);
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
- virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
- virtual void put(ExecState *exec, unsigned propertyName, JSValue *value, int attr = None);
-
- virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
- virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
-
- virtual const ClassInfo *classInfo() const { return &info; }
-
- unsigned getLength() const { return getConcreteArray()->getLength(); }
-
- Bindings::Array *getConcreteArray() const { return _array.get(); }
-
- static const ClassInfo info;
-
-private:
- static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue *indexGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
-
- OwnPtr<Bindings::Array> _array;
-};
-
-} // namespace KJS
-
-#endif // RUNTIME_ARRAY_H_
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "runtime_method.h"
-
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "runtime_object.h"
-#include "function_object.h"
-
-using namespace KJS::Bindings;
-using namespace KJS;
-
-RuntimeMethod::RuntimeMethod(ExecState *exec, const Identifier &ident, Bindings::MethodList &m)
- : InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), ident)
- , _methodList(new MethodList(m))
-{
-}
-
-JSValue *RuntimeMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- RuntimeMethod *thisObj = static_cast<RuntimeMethod *>(slot.slotBase());
-
- // Ick! There may be more than one method with this name. Arbitrarily
- // just pick the first method. The fundamental problem here is that
- // JavaScript doesn't have the notion of method overloading and
- // Java does.
- // FIXME: a better solution might be to give the maximum number of parameters
- // of any method
- return jsNumber(thisObj->_methodList->at(0)->numParameters());
-}
-
-bool RuntimeMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-JSValue *RuntimeMethod::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
-{
- if (_methodList->isEmpty())
- return jsUndefined();
-
- RuntimeObjectImp *imp = 0;
-
- if (thisObj->classInfo() == &KJS::RuntimeObjectImp::info) {
- imp = static_cast<RuntimeObjectImp*>(thisObj);
- } else {
- // If thisObj is the DOM object for a plugin, get the corresponding
- // runtime object from the DOM object.
- JSValue* value = thisObj->get(exec, "__apple_runtime_object");
- if (value->isObject(&KJS::RuntimeObjectImp::info))
- imp = static_cast<RuntimeObjectImp*>(value);
- }
-
- if (!imp)
- return throwError(exec, TypeError);
-
- RefPtr<Instance> instance = imp->getInternalInstance();
- if (!instance)
- return RuntimeObjectImp::throwInvalidAccessError(exec);
-
- instance->begin();
- JSValue *aValue = instance->invokeMethod(exec, *_methodList, args);
- instance->end();
- return aValue;
-}
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef RUNTIME_FUNCTION_H_
-#define RUNTIME_FUNCTION_H_
-
-#include "function.h"
-#include "runtime.h"
-#include "object.h"
-
-namespace KJS {
-
-class RuntimeMethod : public InternalFunctionImp {
-public:
- RuntimeMethod(ExecState *exec, const Identifier &n, Bindings::MethodList &methodList);
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
-
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
-private:
- static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
-
- OwnPtr<Bindings::MethodList> _methodList;
-};
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "runtime_object.h"
-
-#include "error_object.h"
-#include "operations.h"
-#include "runtime_method.h"
-#include "runtime_root.h"
-
-using namespace KJS;
-using namespace Bindings;
-
-const ClassInfo RuntimeObjectImp::info = { "RuntimeObject", 0, 0 };
-
-RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i)
-: instance(i)
-{
- instance->rootObject()->addRuntimeObject(this);
-}
-
-RuntimeObjectImp::~RuntimeObjectImp()
-{
- if (instance)
- instance->rootObject()->removeRuntimeObject(this);
-}
-
-void RuntimeObjectImp::invalidate()
-{
- ASSERT(instance);
- instance = 0;
-}
-
-JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
-{
- RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
- RefPtr<Bindings::Instance> instance = thisObj->instance;
-
- if (!instance)
- return throwInvalidAccessError(exec);
-
- instance->begin();
-
- Class *aClass = instance->getClass();
- JSValue* result = aClass->fallbackObject(exec, instance.get(), propertyName);
-
- instance->end();
-
- return result;
-}
-
-JSValue *RuntimeObjectImp::fieldGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
-{
- RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
- RefPtr<Bindings::Instance> instance = thisObj->instance;
-
- if (!instance)
- return throwInvalidAccessError(exec);
-
- instance->begin();
-
- Class *aClass = instance->getClass();
- Field* aField = aClass->fieldNamed(propertyName, instance.get());
- JSValue *result = instance->getValueOfField(exec, aField);
-
- instance->end();
-
- return result;
-}
-
-JSValue *RuntimeObjectImp::methodGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
-{
- RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
- RefPtr<Bindings::Instance> instance = thisObj->instance;
-
- if (!instance)
- return throwInvalidAccessError(exec);
-
- instance->begin();
-
- Class *aClass = instance->getClass();
- MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
- JSValue *result = new RuntimeMethod(exec, propertyName, methodList);
-
- instance->end();
-
- return result;
-}
-
-bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (!instance) {
- throwInvalidAccessError(exec);
- return false;
- }
-
- instance->begin();
-
- Class *aClass = instance->getClass();
-
- if (aClass) {
- // See if the instance has a field with the specified name.
- Field *aField = aClass->fieldNamed(propertyName, instance.get());
- if (aField) {
- slot.setCustom(this, fieldGetter);
- instance->end();
- return true;
- } else {
- // Now check if a method with specified name exists, if so return a function object for
- // that method.
- MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
- if (methodList.size() > 0) {
- slot.setCustom(this, methodGetter);
-
- instance->end();
- return true;
- }
- }
-
- // Try a fallback object.
- if (!aClass->fallbackObject(exec, instance.get(), propertyName)->isUndefined()) {
- slot.setCustom(this, fallbackObjectGetter);
- instance->end();
- return true;
- }
- }
-
- instance->end();
-
- // don't call superclass, because runtime objects can't have custom properties or a prototype
- return false;
-}
-
-void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int)
-{
- if (!instance) {
- throwInvalidAccessError(exec);
- return;
- }
-
- RefPtr<Bindings::Instance> protector(instance);
- instance->begin();
-
- // Set the value of the property.
- Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
- if (aField)
- instance->setValueOfField(exec, aField, value);
- else if (instance->supportsSetValueOfUndefinedField())
- instance->setValueOfUndefinedField(exec, propertyName, value);
-
- instance->end();
-}
-
-bool RuntimeObjectImp::canPut(ExecState* exec, const Identifier& propertyName) const
-{
- if (!instance) {
- throwInvalidAccessError(exec);
- return false;
- }
-
- instance->begin();
-
- Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
-
- instance->end();
-
- return !!aField;
-}
-
-bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
-{
- // Can never remove a property of a RuntimeObject.
- return false;
-}
-
-JSValue *RuntimeObjectImp::defaultValue(ExecState* exec, JSType hint) const
-{
- if (!instance)
- return throwInvalidAccessError(exec);
-
- JSValue *result;
-
- RefPtr<Bindings::Instance> protector(instance);
- instance->begin();
-
- result = instance->defaultValue(hint);
-
- instance->end();
-
- return result;
-}
-
-bool RuntimeObjectImp::implementsCall() const
-{
- if (!instance)
- return false;
-
- return instance->implementsCall();
-}
-
-JSValue *RuntimeObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- if (!instance)
- return throwInvalidAccessError(exec);
-
- RefPtr<Bindings::Instance> protector(instance);
- instance->begin();
-
- JSValue *aValue = instance->invokeDefaultMethod(exec, args);
-
- instance->end();
-
- return aValue;
-}
-
-void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
-{
- if (!instance) {
- throwInvalidAccessError(exec);
- return;
- }
-
- instance->begin();
- instance->getPropertyNames(exec, propertyNames);
- instance->end();
-}
-
-JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec)
-{
- return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in.");
-}
+++ /dev/null
-/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef KJS_RUNTIME_OBJECT_H
-#define KJS_RUNTIME_OBJECT_H
-
-#include "runtime.h"
-#include "object.h"
-
-#include <wtf/Noncopyable.h>
-
-namespace KJS {
-
-class RuntimeObjectImp : public JSObject {
-public:
- virtual ~RuntimeObjectImp();
-
- const ClassInfo *classInfo() const { return &info; }
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
- virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
- virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
- virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
- virtual bool implementsCall() const;
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual void invalidate();
- Bindings::Instance *getInternalInstance() const { return instance.get(); }
-
- static JSObject* throwInvalidAccessError(ExecState*);
-
- static const ClassInfo info;
-
-protected:
- friend class Bindings::Instance;
- RuntimeObjectImp(Bindings::Instance*); // Only allow Instances and derived classes to create us
-
-private:
- RuntimeObjectImp(); // prevent default construction
-
- static JSValue *fallbackObjectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue *fieldGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue *methodGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
-
- RefPtr<Bindings::Instance> instance;
-};
-
-} // namespace
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "runtime_root.h"
-
-#include "JSGlobalObject.h"
-#include "object.h"
-#include "runtime.h"
-#include "runtime_object.h"
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashSet.h>
-
-namespace KJS { namespace Bindings {
-
-// This code attempts to solve two problems: (1) plug-ins leaking references to
-// JS and the DOM; (2) plug-ins holding stale references to JS and the DOM. Previous
-// comments in this file claimed that problem #1 was an issue in Java, in particular,
-// because Java, allegedly, didn't always call finalize when collecting an object.
-
-typedef HashSet<RootObject*> RootObjectSet;
-
-static RootObjectSet* rootObjectSet()
-{
- static RootObjectSet staticRootObjectSet;
- return &staticRootObjectSet;
-}
-
-// FIXME: These two functions are a potential performance problem. We could
-// fix them by adding a JSObject to RootObject dictionary.
-
-RootObject* findProtectingRootObject(JSObject* jsObject)
-{
- RootObjectSet::const_iterator end = rootObjectSet()->end();
- for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
- if ((*it)->gcIsProtected(jsObject))
- return *it;
- }
- return 0;
-}
-
-RootObject* findRootObject(JSGlobalObject* globalObject)
-{
- RootObjectSet::const_iterator end = rootObjectSet()->end();
- for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
- if ((*it)->globalObject() == globalObject)
- return *it;
- }
- return 0;
-}
-
-// May only be set by dispatchToJavaScriptThread().
-#if ENABLE(JAVA_BINDINGS)
-static CFRunLoopSourceRef completionSource;
-
-static void completedJavaScriptAccess (void *i)
-{
- assert (CFRunLoopGetCurrent() != RootObject::runLoop());
-
- JSObjectCallContext *callContext = (JSObjectCallContext *)i;
- CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;
-
- assert (CFRunLoopGetCurrent() == runLoop);
-
- CFRunLoopStop(runLoop);
-}
-
-static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;
-static pthread_mutex_t javaScriptAccessLock;
-static int javaScriptAccessLockCount = 0;
-
-static void initializeJavaScriptAccessLock()
-{
- pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
-
- pthread_mutex_init(&javaScriptAccessLock, &attr);
-}
-
-static inline void lockJavaScriptAccess()
-{
- // Perhaps add deadlock detection?
- pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);
- pthread_mutex_lock(&javaScriptAccessLock);
- javaScriptAccessLockCount++;
-}
-
-static inline void unlockJavaScriptAccess()
-{
- javaScriptAccessLockCount--;
- pthread_mutex_unlock(&javaScriptAccessLock);
-}
-
-
-void RootObject::dispatchToJavaScriptThread(JSObjectCallContext *context)
-{
- // This lock guarantees that only one thread can invoke
- // at a time, and also guarantees that completionSource;
- // won't get clobbered.
- lockJavaScriptAccess();
-
- CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
-
- assert (currentRunLoop != RootObject::runLoop());
-
- // Setup a source to signal once the invocation of the JavaScript
- // call completes.
- //
- // FIXME: This could be a potential performance issue. Creating and
- // adding run loop sources is expensive. We could create one source
- // per thread, as needed, instead.
- context->originatingLoop = currentRunLoop;
- CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};
- completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
- CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
-
- // Wakeup JavaScript access thread and make it do it's work.
- CFRunLoopSourceSignal(RootObject::performJavaScriptSource());
- if (CFRunLoopIsWaiting(RootObject::runLoop())) {
- CFRunLoopWakeUp(RootObject::runLoop());
- }
-
- // Wait until the JavaScript access thread is done.
- CFRunLoopRun ();
-
- CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
- CFRelease (completionSource);
-
- unlockJavaScriptAccess();
-}
-
-static void performJavaScriptAccess(void*)
-{
- assert (CFRunLoopGetCurrent() == RootObject::runLoop());
-
- // Dispatch JavaScript calls here.
- CFRunLoopSourceContext sourceContext;
- CFRunLoopSourceGetContext (completionSource, &sourceContext);
- JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;
- CFRunLoopRef originatingLoop = callContext->originatingLoop;
-
- JavaJSObject::invoke (callContext);
-
- // Signal the originating thread that we're done.
- CFRunLoopSourceSignal (completionSource);
- if (CFRunLoopIsWaiting(originatingLoop)) {
- CFRunLoopWakeUp(originatingLoop);
- }
-}
-#endif // ENABLE(JAVA_BINDINGS)
-
-CreateRootObjectFunction RootObject::_createRootObject = 0;
-CFRunLoopRef RootObject::_runLoop = 0;
-CFRunLoopSourceRef RootObject::_performJavaScriptSource = 0;
-
-// Must be called from the thread that will be used to access JavaScript.
-void RootObject::setCreateRootObject(CreateRootObjectFunction createRootObject) {
- // Should only be called once.
- ASSERT(!_createRootObject);
-
- _createRootObject = createRootObject;
-
- // Assume that we can retain this run loop forever. It'll most
- // likely (always?) be the main loop.
- _runLoop = (CFRunLoopRef)CFRetain (CFRunLoopGetCurrent ());
-
- // Setup a source the other threads can use to signal the _runLoop
- // thread that a JavaScript call needs to be invoked.
-
-#if ENABLE(JAVA_BINDINGS)
- CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};
- RootObject::_performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
- CFRunLoopAddSource(RootObject::_runLoop, RootObject::_performJavaScriptSource, kCFRunLoopDefaultMode);
-#endif // ENABLE(JAVA_BINDINGS)
-}
-
-
-PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject)
-{
- return new RootObject(nativeHandle, globalObject);
-}
-
-RootObject::RootObject(const void* nativeHandle, JSGlobalObject* globalObject)
- : m_isValid(true)
- , m_nativeHandle(nativeHandle)
- , m_globalObject(globalObject)
-{
- ASSERT(globalObject);
- rootObjectSet()->add(this);
-}
-
-RootObject::~RootObject()
-{
- if (m_isValid)
- invalidate();
-}
-
-void RootObject::invalidate()
-{
- if (!m_isValid)
- return;
-
- {
- HashSet<RuntimeObjectImp*>::iterator end = m_runtimeObjects.end();
- for (HashSet<RuntimeObjectImp*>::iterator it = m_runtimeObjects.begin(); it != end; ++it)
- (*it)->invalidate();
-
- m_runtimeObjects.clear();
- }
-
- m_isValid = false;
-
- m_nativeHandle = 0;
- m_globalObject = 0;
-
- ProtectCountSet::iterator end = m_protectCountSet.end();
- for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it) {
- JSLock lock;
- KJS::gcUnprotect(it->first);
- }
- m_protectCountSet.clear();
-
- rootObjectSet()->remove(this);
-}
-
-void RootObject::gcProtect(JSObject* jsObject)
-{
- ASSERT(m_isValid);
-
- if (!m_protectCountSet.contains(jsObject)) {
- JSLock lock;
- KJS::gcProtect(jsObject);
- }
- m_protectCountSet.add(jsObject);
-}
-
-void RootObject::gcUnprotect(JSObject* jsObject)
-{
- ASSERT(m_isValid);
-
- if (!jsObject)
- return;
-
- if (m_protectCountSet.count(jsObject) == 1) {
- JSLock lock;
- KJS::gcUnprotect(jsObject);
- }
- m_protectCountSet.remove(jsObject);
-}
-
-bool RootObject::gcIsProtected(JSObject* jsObject)
-{
- ASSERT(m_isValid);
- return m_protectCountSet.contains(jsObject);
-}
-
-const void* RootObject::nativeHandle() const
-{
- ASSERT(m_isValid);
- return m_nativeHandle;
-}
-
-JSGlobalObject* RootObject::globalObject() const
-{
- ASSERT(m_isValid);
- return m_globalObject;
-}
-
-void RootObject::addRuntimeObject(RuntimeObjectImp* object)
-{
- ASSERT(m_isValid);
- ASSERT(!m_runtimeObjects.contains(object));
-
- m_runtimeObjects.add(object);
-}
-
-void RootObject::removeRuntimeObject(RuntimeObjectImp* object)
-{
- ASSERT(m_isValid);
- ASSERT(m_runtimeObjects.contains(object));
-
- m_runtimeObjects.remove(object);
-}
-
-} } // namespace KJS::Bindings
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef RUNTIME_ROOT_H_
-#define RUNTIME_ROOT_H_
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#if ENABLE(JAVA_BINDINGS)
-#include "jni_jsobject.h"
-#endif
-#include "protect.h"
-
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/RefCounted.h>
-
-namespace KJS {
-
-class Interpreter;
-class JSGlobalObject;
-class RuntimeObjectImp;
-
-namespace Bindings {
-
-class RootObject;
-
-typedef PassRefPtr<RootObject> (*CreateRootObjectFunction)(void* nativeHandle);
-typedef HashCountedSet<JSObject*> ProtectCountSet;
-
-extern RootObject* findProtectingRootObject(JSObject*);
-extern RootObject* findRootObject(JSGlobalObject*);
-
-class RootObject : public RefCounted<RootObject> {
- friend class JavaJSObject;
-
-public:
- ~RootObject();
-
- static PassRefPtr<RootObject> create(const void* nativeHandle, JSGlobalObject*);
-
- bool isValid() { return m_isValid; }
- void invalidate();
-
- void gcProtect(JSObject*);
- void gcUnprotect(JSObject*);
- bool gcIsProtected(JSObject*);
-
- const void* nativeHandle() const;
- JSGlobalObject* globalObject() const;
-
- // Must be called from the thread that will be used to access JavaScript.
- static void setCreateRootObject(CreateRootObjectFunction);
- static CreateRootObjectFunction createRootObject() {
- return _createRootObject;
- }
-
- static CFRunLoopRef runLoop() { return _runLoop; }
- static CFRunLoopSourceRef performJavaScriptSource() { return _performJavaScriptSource; }
-
-#if ENABLE(JAVA_BINDINGS)
- static void dispatchToJavaScriptThread(JSObjectCallContext *context);
-#endif
-
- void addRuntimeObject(RuntimeObjectImp*);
- void removeRuntimeObject(RuntimeObjectImp*);
-private:
- RootObject(const void* nativeHandle, JSGlobalObject*);
-
- bool m_isValid;
-
- const void* m_nativeHandle;
- ProtectedPtr<JSGlobalObject> m_globalObject;
- ProtectCountSet m_protectCountSet;
-
- HashSet<RuntimeObjectImp*> m_runtimeObjects;
-
- static CreateRootObjectFunction _createRootObject;
- static CFRunLoopRef _runLoop;
- static CFRunLoopSourceRef _performJavaScriptSource;
-};
-
-} // namespace Bindings
-
-} // namespace KJS
-
-#endif // RUNTIME_ROOT_H_
+++ /dev/null
-myInterface.logMessage ("Starting test");
-
-myInterface.logMessage ("Testing properties:");
-myInterface.logMessage ("myInterface.doubleValue = " + myInterface.doubleValue);
-myInterface.logMessage ("myInterface.intValue = " + myInterface.intValue);
-myInterface.logMessage ("myInterface.stringValue = " + myInterface.stringValue);
-myInterface.logMessage ("myInterface.booleanValue = " + myInterface.booleanValue);
-myInterface.logMessage ("myInterface.nullValue = " + myInterface.nullValue);
-myInterface.logMessage ("myInterface.undefinedValue = " + myInterface.undefinedValue);
-
-myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
-myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
-myInterface.logMessage ("myInterface.getString() = " + myInterface.getString());
-myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
-myInterface.logMessage ("setting myInterface.myInt = 777");
-myInterface.myInt = 777;
-myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
-myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
-myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
+++ /dev/null
-myInterface.logMessage ("Starting test");
-
-myInterface.logMessage ("Testing properties:");
-myInterface.logMessage (" myInterface.doubleValue = " + myInterface.doubleValue);
-myInterface.logMessage (" myInterface.intValue = " + myInterface.intValue);
-myInterface.logMessage (" myInterface.stringValue = " + myInterface.stringValue);
-myInterface.logMessage (" myInterface.booleanValue = " + myInterface.booleanValue);
-myInterface.logMessage (" myInterface.nullValue = " + myInterface.nullValue);
-myInterface.logMessage (" myInterface.undefinedValue = " + myInterface.undefinedValue);
-
-myInterface.logMessage ("Testing methods:");
-myInterface.logMessage (" myInterface.setDoubleValue(1234.1234) = " + myInterface.setDoubleValue(1234.1234));
-myInterface.logMessage (" myInterface.setIntValue(5678) = " + myInterface.setIntValue(5678));
-myInterface.logMessage (" myInterface.setStringValue(Goodbye) = " + myInterface.setStringValue('Goodbye'));
-myInterface.logMessage (" myInterface.setBooleanValue(false) = " + myInterface.setBooleanValue(false));
-
-myInterface.logMessage ("Value of properties after calling setters:");
-myInterface.logMessage (" myInterface.getDoubleValue() = " + myInterface.getDoubleValue());
-myInterface.logMessage (" myInterface.getIntValue() = " + myInterface.getIntValue());
-myInterface.logMessage (" myInterface.getStringValue() = " + myInterface.getStringValue());
-myInterface.logMessage (" myInterface.getBooleanValue() = " + myInterface.getBooleanValue());
+++ /dev/null
-myInterface.logMessage ("Starting test");
-
-myInterface.logMessage ("Testing properties:");
-
-myInterface.jsobject = new Function ("arg1","arg2","return arg1 + arg2;");
-myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
-
-var functionBody = 'return arg1*arg2;'
-
-myInterface.setJSObject_(new Function ("arg1","arg2",functionBody));
-myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
-myInterface.callJSObject__(5,6);
-myInterface.callJSObject__(8,9);
-
-myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
-myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
-myInterface.logMessage ("myInterface.getString().foo() = " + myInterface.getString().foo());
-myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
-myInterface.logMessage ("setting myInterface.myInt = 777");
-myInterface.myInt = 777;
-myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
-myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
-myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
-
-myInterface.logMessageWithPrefix ("msg", "prefix");
-
-var strings = [ "one", "two", "three" ];
-
-myInterface.logMessages (strings);
\ No newline at end of file
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "config.h"
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#include "npruntime_internal.h"
-
-#include "runtime.h"
-#include "runtime_object.h"
-
-
-#define LOG(formatAndArgs...) { \
- fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
- fprintf(stderr, formatAndArgs); \
-}
-
-
-// ------------------ NP Interface definition --------------------
-typedef struct
-{
- NPObject object;
- double doubleValue;
- int intValue;
- NPVariant stringValue;
- bool boolValue;
-} MyObject;
-
-
-static bool identifiersInitialized = false;
-
-#define ID_DOUBLE_VALUE 0
-#define ID_INT_VALUE 1
-#define ID_STRING_VALUE 2
-#define ID_BOOLEAN_VALUE 3
-#define ID_NULL_VALUE 4
-#define ID_UNDEFINED_VALUE 5
-#define NUM_PROPERTY_IDENTIFIERS 6
-
-static NPIdentifier myPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
-static const NPUTF8 *myPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
- "doubleValue",
- "intValue",
- "stringValue",
- "booleanValue",
- "nullValue",
- "undefinedValue"
-};
-
-#define ID_LOG_MESSAGE 0
-#define ID_SET_DOUBLE_VALUE 1
-#define ID_SET_INT_VALUE 2
-#define ID_SET_STRING_VALUE 3
-#define ID_SET_BOOLEAN_VALUE 4
-#define ID_GET_DOUBLE_VALUE 5
-#define ID_GET_INT_VALUE 6
-#define ID_GET_STRING_VALUE 7
-#define ID_GET_BOOLEAN_VALUE 8
-#define NUM_METHOD_IDENTIFIERS 9
-
-static NPIdentifier myMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
-static const NPUTF8 *myMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
- "logMessage",
- "setDoubleValue",
- "setIntValue",
- "setStringValue",
- "setBooleanValue",
- "getDoubleValue",
- "getIntValue",
- "getStringValue",
- "getBooleanValue"
-};
-
-static void initializeIdentifiers()
-{
- NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers);
- NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers);
-};
-
-bool myHasProperty (NPClass *theClass, NPIdentifier name)
-{
- int i;
- for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) {
- if (name == myPropertyIdentifiers[i]){
- return true;
- }
- }
- return false;
-}
-
-bool myHasMethod (NPClass *theClass, NPIdentifier name)
-{
- int i;
- for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
- if (name == myMethodIdentifiers[i]){
- return true;
- }
- }
- return false;
-}
-
-
-void logMessage (const NPVariant *message)
-{
- if (message->type == NPVariantStringType) {
- char msgBuf[1024];
- strncpy (msgBuf, message->value.stringValue.UTF8Characters, message->value.stringValue.UTF8Length);
- msgBuf[message->value.stringValue.UTF8Length] = 0;
- printf ("%s\n", msgBuf);
- }
- else if (message->type == NPVariantDoubleType)
- printf ("%f\n", (float)message->value.doubleValue);
- else if (message->type == NPVariantInt32Type)
- printf ("%d\n", message->value.intValue);
- else if (message->type == NPVariantObjectType)
- printf ("%p\n", message->value.objectValue);
-}
-
-void setDoubleValue (MyObject *obj, const NPVariant *variant)
-{
- if (!NPN_VariantToDouble (variant, &obj->doubleValue)) {
- NPUTF8 *msg = "Attempt to set double value with invalid type.";
- NPString aString;
- aString.UTF8Characters = msg;
- aString.UTF8Length = strlen (msg);
- NPN_SetException ((NPObject *)obj, &aString);
- }
-}
-
-void setIntValue (MyObject *obj, const NPVariant *variant)
-{
- if (!NPN_VariantToInt32 (variant, &obj->intValue)) {
- NPUTF8 *msg = "Attempt to set int value with invalid type.";
- NPString aString;
- aString.UTF8Characters = msg;
- aString.UTF8Length = strlen (msg);
- NPN_SetException ((NPObject *)obj, &aString);
- }
-}
-
-void setStringValue (MyObject *obj, const NPVariant *variant)
-{
- NPN_ReleaseVariantValue (&obj->stringValue);
- NPN_InitializeVariantWithVariant (&obj->stringValue, variant);
-}
-
-void setBooleanValue (MyObject *obj, const NPVariant *variant)
-{
- if (!NPN_VariantToBool (variant, (NPBool *)&obj->boolValue)) {
- NPUTF8 *msg = "Attempt to set bool value with invalid type.";
- NPString aString;
- aString.UTF8Characters = msg;
- aString.UTF8Length = strlen (msg);
- NPN_SetException ((NPObject *)obj, &aString);
- }
-}
-
-void getDoubleValue (MyObject *obj, NPVariant *variant)
-{
- NPN_InitializeVariantWithDouble (variant, obj->doubleValue);
-}
-
-void getIntValue (MyObject *obj, NPVariant *variant)
-{
- NPN_InitializeVariantWithInt32 (variant, obj->intValue);
-}
-
-void getStringValue (MyObject *obj, NPVariant *variant)
-{
- NPN_InitializeVariantWithVariant (variant, &obj->stringValue);
-}
-
-void getBooleanValue (MyObject *obj, NPVariant *variant)
-{
- NPN_InitializeVariantWithBool (variant, obj->boolValue);
-}
-
-void myGetProperty (MyObject *obj, NPIdentifier name, NPVariant *variant)
-{
- if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]){
- getDoubleValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_INT_VALUE]){
- getIntValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_STRING_VALUE]){
- getStringValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]){
- getBooleanValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_NULL_VALUE]){
- return NPN_InitializeVariantAsNull (variant);
- }
- else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]){
- return NPN_InitializeVariantAsUndefined (variant);
- }
- else
- NPN_InitializeVariantAsUndefined(variant);
-}
-
-void mySetProperty (MyObject *obj, NPIdentifier name, const NPVariant *variant)
-{
- if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]) {
- setDoubleValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_INT_VALUE]) {
- setIntValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_STRING_VALUE]) {
- setStringValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]) {
- setBooleanValue (obj, variant);
- }
- else if (name == myPropertyIdentifiers[ID_NULL_VALUE]) {
- // Do nothing!
- }
- else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]) {
- // Do nothing!
- }
-}
-
-void myInvoke (MyObject *obj, NPIdentifier name, NPVariant *args, unsigned argCount, NPVariant *result)
-{
- if (name == myMethodIdentifiers[ID_LOG_MESSAGE]) {
- if (argCount == 1 && NPN_VariantIsString(&args[0]))
- logMessage (&args[0]);
- NPN_InitializeVariantAsVoid (result);
- }
- else if (name == myMethodIdentifiers[ID_SET_DOUBLE_VALUE]) {
- if (argCount == 1 && NPN_VariantIsDouble (&args[0]))
- setDoubleValue (obj, &args[0]);
- NPN_InitializeVariantAsVoid (result);
- }
- else if (name == myMethodIdentifiers[ID_SET_INT_VALUE]) {
- if (argCount == 1 && (NPN_VariantIsDouble (&args[0]) || NPN_VariantIsInt32 (&args[0])))
- setIntValue (obj, &args[0]);
- NPN_InitializeVariantAsVoid (result);
- }
- else if (name == myMethodIdentifiers[ID_SET_STRING_VALUE]) {
- if (argCount == 1 && NPN_VariantIsString (&args[0]))
- setStringValue (obj, &args[0]);
- NPN_InitializeVariantAsVoid (result);
- }
- else if (name == myMethodIdentifiers[ID_SET_BOOLEAN_VALUE]) {
- if (argCount == 1 && NPN_VariantIsBool (&args[0]))
- setBooleanValue (obj, &args[0]);
- NPN_InitializeVariantAsVoid (result);
- }
- else if (name == myMethodIdentifiers[ID_GET_DOUBLE_VALUE]) {
- getDoubleValue (obj, result);
- }
- else if (name == myMethodIdentifiers[ID_GET_INT_VALUE]) {
- getIntValue (obj, result);
- }
- else if (name == myMethodIdentifiers[ID_GET_STRING_VALUE]) {
- getStringValue (obj, result);
- }
- else if (name == myMethodIdentifiers[ID_GET_BOOLEAN_VALUE]) {
- getBooleanValue (obj, result);
- }
- else
- NPN_InitializeVariantAsUndefined (result);
-}
-
-NPObject *myAllocate ()
-{
- MyObject *newInstance = (MyObject *)malloc (sizeof(MyObject));
-
- if (!identifiersInitialized) {
- identifiersInitialized = true;
- initializeIdentifiers();
- }
-
-
- newInstance->doubleValue = 666.666;
- newInstance->intValue = 1234;
- newInstance->boolValue = true;
- newInstance->stringValue.type = NPVariantType_String;
- newInstance->stringValue.value.stringValue.UTF8Length = strlen ("Hello world");
- newInstance->stringValue.value.stringValue.UTF8Characters = strdup ("Hello world");
-
- return (NPObject *)newInstance;
-}
-
-void myInvalidate ()
-{
- // Make sure we've released any remaining references to JavaScript objects.
-}
-
-void myDeallocate (MyObject *obj)
-{
- free ((void *)obj);
-}
-
-static NPClass _myFunctionPtrs = {
- kNPClassStructVersionCurrent,
- (NPAllocateFunctionPtr) myAllocate,
- (NPDeallocateFunctionPtr) myDeallocate,
- (NPInvalidateFunctionPtr) myInvalidate,
- (NPHasMethodFunctionPtr) myHasMethod,
- (NPInvokeFunctionPtr) myInvoke,
- (NPHasPropertyFunctionPtr) myHasProperty,
- (NPGetPropertyFunctionPtr) myGetProperty,
- (NPSetPropertyFunctionPtr) mySetProperty,
-};
-static NPClass *myFunctionPtrs = &_myFunctionPtrs;
-
-// --------------------------------------------------------
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-class GlobalImp : public ObjectImp {
-public:
- virtual UString className() const { return "global"; }
-};
-
-#define BufferSize 200000
-static char code[BufferSize];
-
-const char *readJavaScriptFromFile (const char *file)
-{
- FILE *f = fopen(file, "r");
- if (!f) {
- fprintf(stderr, "Error opening %s.\n", file);
- return 0;
- }
-
- int num = fread(code, 1, BufferSize, f);
- code[num] = '\0';
- if(num >= BufferSize)
- fprintf(stderr, "Warning: File may have been too long.\n");
-
- fclose(f);
-
- return code;
-}
-
-int main(int argc, char **argv)
-{
- // expecting a filename
- if (argc < 2) {
- fprintf(stderr, "You have to specify at least one filename\n");
- return -1;
- }
-
- bool ret = true;
- {
- JSLock lock;
-
- // create interpreter w/ global object
- Object global(new GlobalImp());
- Interpreter interp;
- interp.setGlobalObject(global);
- ExecState *exec = interp.globalExec();
-
- MyObject *myObject = (MyObject *)NPN_CreateObject (myFunctionPtrs);
-
- global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject));
-
- for (int i = 1; i < argc; i++) {
- const char *code = readJavaScriptFromFile(argv[i]);
-
- if (code) {
- // run
- Completion comp(interp.evaluate(code));
-
- if (comp.complType() == Throw) {
- Value exVal = comp.value();
- char *msg = exVal.toString(exec).ascii();
- int lineno = -1;
- if (exVal.type() == ObjectType) {
- Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
- if (lineVal.type() == NumberType)
- lineno = int(lineVal.toNumber(exec));
- }
- if (lineno != -1)
- fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
- else
- fprintf(stderr,"Exception: %s\n",msg);
- ret = false;
- }
- else if (comp.complType() == ReturnValue) {
- char *msg = comp.value().toString(interp.globalExec()).ascii();
- fprintf(stderr,"Return value: %s\n",msg);
- }
- }
- }
-
- NPN_ReleaseObject ((NPObject *)myObject);
-
- } // end block, so that Interpreter and global get deleted
-
- return ret ? 0 : 3;
-}
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include <Foundation/Foundation.h>
-
-#import <WebKit/WebScriptObject.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#include "runtime.h"
-#include "runtime_object.h"
-
-#define LOG(formatAndArgs...) { \
- fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
- fprintf(stderr, formatAndArgs); \
-}
-
-@interface MySecondInterface : NSObject
-{
- double doubleValue;
-}
-
-- init;
-
-@end
-
-@implementation MySecondInterface
-
-- init
-{
- LOG ("\n");
- doubleValue = 666.666;
- return self;
-}
-
-@end
-
-@interface MyFirstInterface : NSObject
-{
- int myInt;
- MySecondInterface *mySecondInterface;
- id jsobject;
- NSString *string;
-}
-
-- (int)getInt;
-- (void)setInt: (int)anInt;
-- (MySecondInterface *)getMySecondInterface;
-- (void)logMessage:(NSString *)message;
-- (void)setJSObject:(id)jsobject;
-@end
-
-@implementation MyFirstInterface
-
-+ (NSString *)webScriptNameForSelector:(SEL)aSelector
-{
- if (aSelector == @selector(logMessage:))
- return @"logMessage";
- if (aSelector == @selector(logMessages:))
- return @"logMessages";
- if (aSelector == @selector(logMessage:prefix:))
- return @"logMessageWithPrefix";
- return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
-{
- return NO;
-}
-
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name
-{
- return NO;
-}
-
-/*
-- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args;
-{
- NSLog (@"Call to undefined method %@", name);
- NSLog (@"%d args\n", [args count]);
- int i;
- for (i = 0; i < [args count]; i++) {
- NSLog (@"%d: %@\n", i, [args objectAtIndex:i]);
- }
- return @"success";
-}
-*/
-
-/*
-- (id)valueForUndefinedKey:(NSString *)key
-{
- NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
- return @"aValue";
-}
-*/
-
-- (void)setValue:(id)value forUndefinedKey:(NSString *)key
-{
- NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
-}
-
-- init
-{
- LOG ("\n");
- mySecondInterface = [[MySecondInterface alloc] init];
- return self;
-}
-
-- (void)dealloc
-{
- LOG ("\n");
- [mySecondInterface release];
- [super dealloc];
-}
-
-- (int)getInt
-{
- LOG ("myInt = %d\n", myInt);
- return myInt;
-}
-
-- (void)setInt: (int)anInt
-{
- LOG ("anInt = %d\n", anInt);
- myInt = anInt;
-}
-
-- (NSString *)getString
-{
- return string;
-}
-
-- (MySecondInterface *)getMySecondInterface
-{
- LOG ("\n");
- return mySecondInterface;
-}
-
-- (void)logMessage:(NSString *)message
-{
- printf ("%s\n", [message lossyCString]);
-}
-
-- (void)logMessages:(id)messages
-{
- int i, count = [[messages valueForKey:@"length"] intValue];
- for (i = 0; i < count; i++)
- printf ("%s\n", [[messages webScriptValueAtIndex:i] lossyCString]);
-}
-
-- (void)logMessage:(NSString *)message prefix:(NSString *)prefix
-{
- printf ("%s:%s\n", [prefix lossyCString], [message lossyCString]);
-}
-
-- (void)setJSObject:(id)jso
-{
- [jsobject autorelease];
- jsobject = [jso retain];
-}
-
-- (void)callJSObject:(int)arg1 :(int)arg2
-{
- id foo1 = [jsobject callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:jsobject, [NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil]];
- printf ("foo (via call) = %s\n", [[foo1 description] lossyCString] );
- id foo2 = [jsobject callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:jsobject, [NSArray arrayWithObjects:[NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil], nil]];
- printf ("foo (via apply) = %s\n", [[foo2 description] lossyCString] );
-}
-
-@end
-
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-class GlobalImp : public ObjectImp {
-public:
- virtual UString className() const { return "global"; }
-};
-
-#define BufferSize 200000
-static char code[BufferSize];
-
-const char *readJavaScriptFromFile (const char *file)
-{
- FILE *f = fopen(file, "r");
- if (!f) {
- fprintf(stderr, "Error opening %s.\n", file);
- return 0;
- }
-
- int num = fread(code, 1, BufferSize, f);
- code[num] = '\0';
- if(num >= BufferSize)
- fprintf(stderr, "Warning: File may have been too long.\n");
-
- fclose(f);
-
- return code;
-}
-
-int main(int argc, char **argv)
-{
- // expecting a filename
- if (argc < 2) {
- fprintf(stderr, "You have to specify at least one filename\n");
- return -1;
- }
-
- bool ret = true;
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- JSLock lock;
-
- // create interpreter w/ global object
- Object global(new GlobalImp());
- Interpreter interp;
- interp.setGlobalObject(global);
- ExecState *exec = interp.globalExec();
-
- MyFirstInterface *myInterface = [[MyFirstInterface alloc] init];
-
- global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::ObjectiveCLanguage, (void *)myInterface));
-
- for (int i = 1; i < argc; i++) {
- const char *code = readJavaScriptFromFile(argv[i]);
-
- if (code) {
- // run
- Completion comp(interp.evaluate(code));
-
- if (comp.complType() == Throw) {
- Value exVal = comp.value();
- char *msg = exVal.toString(exec).ascii();
- int lineno = -1;
- if (exVal.type() == ObjectType) {
- Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
- if (lineVal.type() == NumberType)
- lineno = int(lineVal.toNumber(exec));
- }
- if (lineno != -1)
- fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
- else
- fprintf(stderr,"Exception: %s\n",msg);
- ret = false;
- }
- else if (comp.complType() == ReturnValue) {
- char *msg = comp.value().toString(interp.globalExec()).ascii();
- fprintf(stderr,"Return value: %s\n",msg);
- }
- }
- }
-
- [myInterface release];
- [pool drain];
- } // end block, so that Interpreter and global get deleted
-
- return ret ? 0 : 3;
-}
+++ /dev/null
-QT -= gui
-
-include(../../WebKit.pri)
-INCLUDEPATH += .. ../kjs .
-qt-port:INCLUDEPATH += bindings/qt
-
-SOURCES += testqtbindings.cpp
-
+++ /dev/null
-/*
- * Copyright (C) 2006 Trolltech ASA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "config.h"
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#include "qobject.h"
-#include "qdebug.h"
-
-#include "runtime.h"
-#include "runtime_object.h"
-
-
-
-class MyObject : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QString testString READ testString WRITE setTestString)
- Q_PROPERTY(int testInt READ testInt WRITE setTestInt)
-
-public:
- MyObject() : QObject(0), integer(0){}
-
- void setTestString(const QString &str) {
- qDebug() << "called setTestString" << str;
- string = str;
- }
- void setTestInt(int i) {
- qDebug() << "called setTestInt" << i;
- integer = i;
- }
- QString testString() const {
- qDebug() << "called testString" << string;
- return string;
- }
- int testInt() const {
- qDebug() << "called testInt" << integer;
- return integer;
- }
- QString string;
- int integer;
-
-public slots:
- void foo() { qDebug() << "foo invoked"; }
-};
-
-// --------------------------------------------------------
-
-using namespace KJS;
-using namespace KJS::Bindings;
-
-class Global : public JSObject {
-public:
- virtual UString className() const { return "global"; }
-};
-
-static char code[] =
- "myInterface.foo();\n"
- "myInterface.testString = \"Hello\";\n"
- "str = myInterface.testString;\n"
- "myInterface.testInt = 10;\n"
- "i = myInterface.testInt;\n";
-
-int main(int argc, char** argv)
-{
- // expecting a filename
- bool ret = true;
- {
- JSLock lock;
-
- // create interpreter w/ global object
- Global* global = new Global();
-
- // create interpreter
- RefPtr<Interpreter> interp = new Interpreter(global);
- ExecState* exec = interp->globalExec();
-
- MyObject* myObject = new MyObject;
-
- global->put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));
-
-
- if (code) {
- // run
- Completion comp(interp->evaluate("", 0, code));
-
- if (comp.complType() == Throw) {
- qDebug() << "exception thrown";
- JSValue* exVal = comp.value();
- char* msg = exVal->toString(exec).ascii();
- int lineno = -1;
- if (exVal->type() == ObjectType) {
- JSValue* lineVal = exVal->getObject()->get(exec, Identifier("line"));
- if (lineVal->type() == NumberType)
- lineno = int(lineVal->toNumber(exec));
- }
- if (lineno != -1)
- fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
- else
- fprintf(stderr,"Exception: %s\n",msg);
- ret = false;
- }
- else if (comp.complType() == ReturnValue) {
- char* msg = comp.value()->toString(interp->globalExec()).ascii();
- fprintf(stderr,"Return value: %s\n",msg);
- }
- }
-
- } // end block, so that Interpreter and global get deleted
-
- return ret ? 0 : 1;
-}
-
-#include "testqtbindings.moc"
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CodeBlock.h"
+
+#include "JIT.h"
+#include "JSValue.h"
+#include "Interpreter.h"
+#include "Debugger.h"
+#include "BytecodeGenerator.h"
+#include <stdio.h>
+#include <wtf/StringExtras.h>
+
+#define DUMP_CODE_BLOCK_STATISTICS 0
+
+namespace JSC {
+
+#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
+
+static UString escapeQuotes(const UString& str)
+{
+ UString result = str;
+ int pos = 0;
+ while ((pos = result.find('\"', pos)) >= 0) {
+ result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);
+ pos += 4;
+ }
+ return result;
+}
+
+static UString valueToSourceString(ExecState* exec, JSValuePtr val)
+{
+ if (val.isString()) {
+ UString result("\"");
+ result += escapeQuotes(val.toString(exec)) + "\"";
+ return result;
+ }
+
+ return val.toString(exec);
+}
+
+static CString registerName(int r)
+{
+ if (r == missingThisObjectMarker())
+ return "<null>";
+
+ return (UString("r") + UString::from(r)).UTF8String();
+}
+
+static CString constantName(ExecState* exec, int k, JSValuePtr value)
+{
+ return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
+}
+
+static CString idName(int id0, const Identifier& ident)
+{
+ return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();
+}
+
+static UString regexpToSourceString(RegExp* regExp)
+{
+ UString pattern = UString("/") + regExp->pattern() + "/";
+ if (regExp->global())
+ pattern += "g";
+ if (regExp->ignoreCase())
+ pattern += "i";
+ if (regExp->multiline())
+ pattern += "m";
+
+ return pattern;
+}
+
+static CString regexpName(int re, RegExp* regexp)
+{
+ return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();
+}
+
+static UString pointerToSourceString(void* p)
+{
+ char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
+ snprintf(buffer, sizeof(buffer), "%p", p);
+ return buffer;
+}
+
+NEVER_INLINE static const char* debugHookName(int debugHookID)
+{
+ switch (static_cast<DebugHookID>(debugHookID)) {
+ case DidEnterCallFrame:
+ return "didEnterCallFrame";
+ case WillLeaveCallFrame:
+ return "willLeaveCallFrame";
+ case WillExecuteStatement:
+ return "willExecuteStatement";
+ case WillExecuteProgram:
+ return "willExecuteProgram";
+ case DidExecuteProgram:
+ return "didExecuteProgram";
+ case DidReachBreakpoint:
+ return "didReachBreakpoint";
+ }
+
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)
+{
+ return it - begin + offset;
+}
+
+static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
+{
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+
+ printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());
+}
+
+static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
+{
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+}
+
+static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)
+{
+ int r0 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));
+}
+
+static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
+{
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ it += 4;
+}
+
+static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
+{
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+ it += 4;
+}
+
+#if ENABLE(JIT)
+static bool isGlobalResolve(OpcodeID opcodeID)
+{
+ return opcodeID == op_resolve_global;
+}
+
+static bool isPropertyAccess(OpcodeID opcodeID)
+{
+ switch (opcodeID) {
+ case op_get_by_id_self:
+ case op_get_by_id_proto:
+ case op_get_by_id_chain:
+ case op_get_by_id_self_list:
+ case op_get_by_id_proto_list:
+ case op_put_by_id_transition:
+ case op_put_by_id_replace:
+ case op_get_by_id:
+ case op_put_by_id:
+ case op_get_by_id_generic:
+ case op_put_by_id_generic:
+ case op_get_array_length:
+ case op_get_string_length:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
+{
+ size_t i = 0;
+ while (i < instructions.size()) {
+ OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
+ if (predicate(currentOpcode)) {
+ if (!--nth)
+ return i;
+ }
+ i += opcodeLengths[currentOpcode];
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
+{
+ printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str());
+}
+
+static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
+{
+ switch (stubInfo.opcodeID) {
+ case op_get_by_id_self:
+ printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id_proto:
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id_chain:
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
+ return;
+ case op_get_by_id_self_list:
+ printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
+ return;
+ case op_get_by_id_proto_list:
+ printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
+ return;
+ case op_put_by_id_transition:
+ printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
+ return;
+ case op_put_by_id_replace:
+ printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id:
+ printf(" [%4d] %s\n", instructionOffset, "get_by_id");
+ return;
+ case op_put_by_id:
+ printf(" [%4d] %s\n", instructionOffset, "put_by_id");
+ return;
+ case op_get_by_id_generic:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
+ return;
+ case op_put_by_id_generic:
+ printf(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
+ return;
+ case op_get_array_length:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_array_length");
+ return;
+ case op_get_string_length:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_string_length");
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
+void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
+{
+ unsigned instructionOffset = vPC - m_instructions.begin();
+ printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());
+}
+
+void CodeBlock::printStructures(const Instruction* vPC) const
+{
+ Interpreter* interpreter = m_globalData->interpreter;
+ unsigned instructionOffset = vPC - m_instructions.begin();
+
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
+ printStructure("get_by_id", vPC, 4);
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
+ printStructure("get_by_id_self", vPC, 4);
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
+ printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
+ printStructure("put_by_id", vPC, 4);
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
+ printStructure("put_by_id_replace", vPC, 4);
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
+ printStructure("resolve_global", vPC, 4);
+ return;
+ }
+
+ // These m_instructions doesn't ref Structures.
+ ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));
+}
+
+void CodeBlock::dump(ExecState* exec) const
+{
+ if (m_instructions.isEmpty()) {
+ printf("No instructions available.\n");
+ return;
+ }
+
+ size_t instructionCount = 0;
+
+ for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
+ ++instructionCount;
+
+ printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
+ static_cast<unsigned long>(instructionCount),
+ static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
+ this, m_numParameters, m_numCalleeRegisters);
+
+ Vector<Instruction>::const_iterator begin = m_instructions.begin();
+ Vector<Instruction>::const_iterator end = m_instructions.end();
+ for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
+ dump(exec, begin, it);
+
+ if (!m_identifiers.isEmpty()) {
+ printf("\nIdentifiers:\n");
+ size_t i = 0;
+ do {
+ printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
+ ++i;
+ } while (i != m_identifiers.size());
+ }
+
+ if (!m_constantRegisters.isEmpty()) {
+ printf("\nConstants:\n");
+ unsigned registerIndex = m_numVars;
+ size_t i = 0;
+ do {
+ printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());
+ ++i;
+ ++registerIndex;
+ } while (i < m_constantRegisters.size());
+ }
+
+ if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) {
+ printf("\nUnexpected Constants:\n");
+ size_t i = 0;
+ do {
+ printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii());
+ ++i;
+ } while (i < m_rareData->m_unexpectedConstants.size());
+ }
+
+ if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
+ printf("\nm_regexps:\n");
+ size_t i = 0;
+ do {
+ printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
+ ++i;
+ } while (i < m_rareData->m_regexps.size());
+ }
+
+#if ENABLE(JIT)
+ if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
+ printf("\nStructures:\n");
+
+ if (!m_globalResolveInfos.isEmpty()) {
+ size_t i = 0;
+ do {
+ printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
+ ++i;
+ } while (i < m_globalResolveInfos.size());
+ }
+ if (!m_structureStubInfos.isEmpty()) {
+ size_t i = 0;
+ do {
+ printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
+ ++i;
+ } while (i < m_structureStubInfos.size());
+ }
+#else
+ if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
+ printf("\nStructures:\n");
+
+ if (!m_globalResolveInstructions.isEmpty()) {
+ size_t i = 0;
+ do {
+ printStructures(&m_instructions[m_globalResolveInstructions[i]]);
+ ++i;
+ } while (i < m_globalResolveInstructions.size());
+ }
+ if (!m_propertyAccessInstructions.isEmpty()) {
+ size_t i = 0;
+ do {
+ printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
+ ++i;
+ } while (i < m_propertyAccessInstructions.size());
+ }
+#endif
+
+ if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
+ printf("\nException Handlers:\n");
+ unsigned i = 0;
+ do {
+ printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
+ ++i;
+ } while (i < m_rareData->m_exceptionHandlers.size());
+ }
+
+ if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
+ printf("Immediate Switch Jump Tables:\n");
+ unsigned i = 0;
+ do {
+ printf(" %1d = {\n", i);
+ int entry = 0;
+ Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
+ for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
+ if (!*iter)
+ continue;
+ printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
+ }
+ printf(" }\n");
+ ++i;
+ } while (i < m_rareData->m_immediateSwitchJumpTables.size());
+ }
+
+ if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
+ printf("\nCharacter Switch Jump Tables:\n");
+ unsigned i = 0;
+ do {
+ printf(" %1d = {\n", i);
+ int entry = 0;
+ Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
+ for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
+ if (!*iter)
+ continue;
+ ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
+ UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
+ printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
+ }
+ printf(" }\n");
+ ++i;
+ } while (i < m_rareData->m_characterSwitchJumpTables.size());
+ }
+
+ if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
+ printf("\nString Switch Jump Tables:\n");
+ unsigned i = 0;
+ do {
+ printf(" %1d = {\n", i);
+ StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
+ for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
+ printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
+ printf(" }\n");
+ ++i;
+ } while (i < m_rareData->m_stringSwitchJumpTables.size());
+ }
+
+ printf("\n");
+}
+
+void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
+{
+ int location = it - begin;
+ switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
+ case op_enter: {
+ printf("[%4d] enter\n", location);
+ break;
+ }
+ case op_enter_with_activation: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_create_arguments: {
+ printf("[%4d] create_arguments\n", location);
+ break;
+ }
+ case op_convert_this: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_unexpected_load: {
+ int r0 = (++it)->u.operand;
+ int k0 = (++it)->u.operand;
+ printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str());
+ break;
+ }
+ case op_new_object: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_new_array: {
+ int dst = (++it)->u.operand;
+ int argv = (++it)->u.operand;
+ int argc = (++it)->u.operand;
+ printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);
+ break;
+ }
+ case op_new_regexp: {
+ int r0 = (++it)->u.operand;
+ int re0 = (++it)->u.operand;
+ printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str());
+ break;
+ }
+ case op_mov: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_not: {
+ printUnaryOp(location, it, "not");
+ break;
+ }
+ case op_eq: {
+ printBinaryOp(location, it, "eq");
+ break;
+ }
+ case op_eq_null: {
+ printUnaryOp(location, it, "eq_null");
+ break;
+ }
+ case op_neq: {
+ printBinaryOp(location, it, "neq");
+ break;
+ }
+ case op_neq_null: {
+ printUnaryOp(location, it, "neq_null");
+ break;
+ }
+ case op_stricteq: {
+ printBinaryOp(location, it, "stricteq");
+ break;
+ }
+ case op_nstricteq: {
+ printBinaryOp(location, it, "nstricteq");
+ break;
+ }
+ case op_less: {
+ printBinaryOp(location, it, "less");
+ break;
+ }
+ case op_lesseq: {
+ printBinaryOp(location, it, "lesseq");
+ break;
+ }
+ case op_pre_inc: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_pre_dec: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_post_inc: {
+ printUnaryOp(location, it, "post_inc");
+ break;
+ }
+ case op_post_dec: {
+ printUnaryOp(location, it, "post_dec");
+ break;
+ }
+ case op_to_jsnumber: {
+ printUnaryOp(location, it, "to_jsnumber");
+ break;
+ }
+ case op_negate: {
+ printUnaryOp(location, it, "negate");
+ break;
+ }
+ case op_add: {
+ printBinaryOp(location, it, "add");
+ ++it;
+ break;
+ }
+ case op_mul: {
+ printBinaryOp(location, it, "mul");
+ ++it;
+ break;
+ }
+ case op_div: {
+ printBinaryOp(location, it, "div");
+ break;
+ }
+ case op_mod: {
+ printBinaryOp(location, it, "mod");
+ break;
+ }
+ case op_sub: {
+ printBinaryOp(location, it, "sub");
+ ++it;
+ break;
+ }
+ case op_lshift: {
+ printBinaryOp(location, it, "lshift");
+ break;
+ }
+ case op_rshift: {
+ printBinaryOp(location, it, "rshift");
+ break;
+ }
+ case op_urshift: {
+ printBinaryOp(location, it, "urshift");
+ break;
+ }
+ case op_bitand: {
+ printBinaryOp(location, it, "bitand");
+ ++it;
+ break;
+ }
+ case op_bitxor: {
+ printBinaryOp(location, it, "bitxor");
+ ++it;
+ break;
+ }
+ case op_bitor: {
+ printBinaryOp(location, it, "bitor");
+ ++it;
+ break;
+ }
+ case op_bitnot: {
+ printUnaryOp(location, it, "bitnot");
+ break;
+ }
+ case op_instanceof: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ int r3 = (++it)->u.operand;
+ printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());
+ break;
+ }
+ case op_typeof: {
+ printUnaryOp(location, it, "typeof");
+ break;
+ }
+ case op_is_undefined: {
+ printUnaryOp(location, it, "is_undefined");
+ break;
+ }
+ case op_is_boolean: {
+ printUnaryOp(location, it, "is_boolean");
+ break;
+ }
+ case op_is_number: {
+ printUnaryOp(location, it, "is_number");
+ break;
+ }
+ case op_is_string: {
+ printUnaryOp(location, it, "is_string");
+ break;
+ }
+ case op_is_object: {
+ printUnaryOp(location, it, "is_object");
+ break;
+ }
+ case op_is_function: {
+ printUnaryOp(location, it, "is_function");
+ break;
+ }
+ case op_in: {
+ printBinaryOp(location, it, "in");
+ break;
+ }
+ case op_resolve: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ break;
+ }
+ case op_resolve_skip: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ int skipLevels = (++it)->u.operand;
+ printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
+ break;
+ }
+ case op_resolve_global: {
+ int r0 = (++it)->u.operand;
+ JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
+ int id0 = (++it)->u.operand;
+ printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
+ it += 2;
+ break;
+ }
+ case op_get_scoped_var: {
+ int r0 = (++it)->u.operand;
+ int index = (++it)->u.operand;
+ int skipLevels = (++it)->u.operand;
+ printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);
+ break;
+ }
+ case op_put_scoped_var: {
+ int index = (++it)->u.operand;
+ int skipLevels = (++it)->u.operand;
+ int r0 = (++it)->u.operand;
+ printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());
+ break;
+ }
+ case op_get_global_var: {
+ int r0 = (++it)->u.operand;
+ JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
+ int index = (++it)->u.operand;
+ printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
+ break;
+ }
+ case op_put_global_var: {
+ JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
+ int index = (++it)->u.operand;
+ int r0 = (++it)->u.operand;
+ printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
+ break;
+ }
+ case op_resolve_base: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ break;
+ }
+ case op_resolve_with_base: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ break;
+ }
+ case op_resolve_func: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ break;
+ }
+ case op_get_by_id: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id");
+ break;
+ }
+ case op_get_by_id_self: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id_self");
+ break;
+ }
+ case op_get_by_id_self_list: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");
+ break;
+ }
+ case op_get_by_id_proto: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");
+ break;
+ }
+ case op_get_by_id_proto_list: {
+ printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");
+ break;
+ }
+ case op_get_by_id_chain: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");
+ break;
+ }
+ case op_get_by_id_generic: {
+ printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");
+ break;
+ }
+ case op_get_array_length: {
+ printGetByIdOp(location, it, m_identifiers, "get_array_length");
+ break;
+ }
+ case op_get_string_length: {
+ printGetByIdOp(location, it, m_identifiers, "get_string_length");
+ break;
+ }
+ case op_put_by_id: {
+ printPutByIdOp(location, it, m_identifiers, "put_by_id");
+ break;
+ }
+ case op_put_by_id_replace: {
+ printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");
+ break;
+ }
+ case op_put_by_id_transition: {
+ printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");
+ break;
+ }
+ case op_put_by_id_generic: {
+ printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");
+ break;
+ }
+ case op_put_getter: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_put_setter: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_del_by_id: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+ break;
+ }
+ case op_get_by_val: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+ break;
+ }
+ case op_put_by_val: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+ break;
+ }
+ case op_del_by_val: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+ break;
+ }
+ case op_put_by_index: {
+ int r0 = (++it)->u.operand;
+ unsigned n0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());
+ break;
+ }
+ case op_jmp: {
+ int offset = (++it)->u.operand;
+ printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_loop: {
+ int offset = (++it)->u.operand;
+ printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_jtrue: {
+ printConditionalJump(begin, it, location, "jtrue");
+ break;
+ }
+ case op_loop_if_true: {
+ printConditionalJump(begin, it, location, "loop_if_true");
+ break;
+ }
+ case op_jfalse: {
+ printConditionalJump(begin, it, location, "jfalse");
+ break;
+ }
+ case op_jeq_null: {
+ printConditionalJump(begin, it, location, "jeq_null");
+ break;
+ }
+ case op_jneq_null: {
+ printConditionalJump(begin, it, location, "jneq_null");
+ break;
+ }
+ case op_jnless: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_loop_if_less: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_loop_if_lesseq: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_switch_imm: {
+ int tableIndex = (++it)->u.operand;
+ int defaultTarget = (++it)->u.operand;
+ int scrutineeRegister = (++it)->u.operand;
+ printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+ break;
+ }
+ case op_switch_char: {
+ int tableIndex = (++it)->u.operand;
+ int defaultTarget = (++it)->u.operand;
+ int scrutineeRegister = (++it)->u.operand;
+ printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+ break;
+ }
+ case op_switch_string: {
+ int tableIndex = (++it)->u.operand;
+ int defaultTarget = (++it)->u.operand;
+ int scrutineeRegister = (++it)->u.operand;
+ printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+ break;
+ }
+ case op_new_func: {
+ int r0 = (++it)->u.operand;
+ int f0 = (++it)->u.operand;
+ printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);
+ break;
+ }
+ case op_new_func_exp: {
+ int r0 = (++it)->u.operand;
+ int f0 = (++it)->u.operand;
+ printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);
+ break;
+ }
+ case op_call: {
+ int dst = (++it)->u.operand;
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
+ break;
+ }
+ case op_call_eval: {
+ int dst = (++it)->u.operand;
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
+ break;
+ }
+ case op_tear_off_activation: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_tear_off_arguments: {
+ printf("[%4d] tear_off_arguments\n", location);
+ break;
+ }
+ case op_ret: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_construct: {
+ int dst = (++it)->u.operand;
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ int proto = (++it)->u.operand;
+ int thisRegister = (++it)->u.operand;
+ printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
+ break;
+ }
+ case op_construct_verify: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_get_pnames: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_next_pname: {
+ int dest = (++it)->u.operand;
+ int iter = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_push_scope: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_pop_scope: {
+ printf("[%4d] pop_scope\n", location);
+ break;
+ }
+ case op_push_new_scope: {
+ int r0 = (++it)->u.operand;
+ int id0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+ break;
+ }
+ case op_jmp_scopes: {
+ int scopeDelta = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_catch: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_throw: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ case op_new_error: {
+ int r0 = (++it)->u.operand;
+ int errorType = (++it)->u.operand;
+ int k0 = (++it)->u.operand;
+ printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str());
+ break;
+ }
+ case op_jsr: {
+ int retAddrDst = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
+ case op_sret: {
+ int retAddrSrc = (++it)->u.operand;
+ printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());
+ break;
+ }
+ case op_debug: {
+ int debugHookID = (++it)->u.operand;
+ int firstLine = (++it)->u.operand;
+ int lastLine = (++it)->u.operand;
+ printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
+ break;
+ }
+ case op_profile_will_call: {
+ int function = (++it)->u.operand;
+ printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());
+ break;
+ }
+ case op_profile_did_call: {
+ int function = (++it)->u.operand;
+ printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());
+ break;
+ }
+ case op_end: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());
+ break;
+ }
+ }
+}
+
+#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
+
+#if DUMP_CODE_BLOCK_STATISTICS
+static HashSet<CodeBlock*> liveCodeBlockSet;
+#endif
+
+#define FOR_EACH_MEMBER_VECTOR(macro) \
+ macro(instructions) \
+ macro(globalResolveInfos) \
+ macro(structureStubInfos) \
+ macro(callLinkInfos) \
+ macro(linkedCallerList) \
+ macro(identifiers) \
+ macro(functionExpressions) \
+ macro(constantRegisters)
+
+#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
+ macro(regexps) \
+ macro(functions) \
+ macro(unexpectedConstants) \
+ macro(exceptionHandlers) \
+ macro(immediateSwitchJumpTables) \
+ macro(characterSwitchJumpTables) \
+ macro(stringSwitchJumpTables) \
+ macro(functionRegisterInfos)
+
+#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
+ macro(expressionInfo) \
+ macro(lineInfo) \
+ macro(getByIdExceptionInfo) \
+ macro(pcVector)
+
+template<typename T>
+static size_t sizeInBytes(const Vector<T>& vector)
+{
+ return vector.capacity() * sizeof(T);
+}
+
+void CodeBlock::dumpStatistics()
+{
+#if DUMP_CODE_BLOCK_STATISTICS
+ #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
+ FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
+ FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
+ FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS)
+ #undef DEFINE_VARS
+
+ // Non-vector data members
+ size_t evalCodeCacheIsNotEmpty = 0;
+
+ size_t symbolTableIsNotEmpty = 0;
+ size_t symbolTableTotalSize = 0;
+
+ size_t hasExceptionInfo = 0;
+ size_t hasRareData = 0;
+
+ size_t isFunctionCode = 0;
+ size_t isGlobalCode = 0;
+ size_t isEvalCode = 0;
+
+ HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
+ for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
+ CodeBlock* codeBlock = *it;
+
+ #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
+ FOR_EACH_MEMBER_VECTOR(GET_STATS)
+ #undef GET_STATS
+
+ if (!codeBlock->m_symbolTable.isEmpty()) {
+ symbolTableIsNotEmpty++;
+ symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
+ }
+
+ if (codeBlock->m_exceptionInfo) {
+ hasExceptionInfo++;
+ #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); }
+ FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS)
+ #undef GET_STATS
+ }
+
+ if (codeBlock->m_rareData) {
+ hasRareData++;
+ #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
+ FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
+ #undef GET_STATS
+
+ if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
+ evalCodeCacheIsNotEmpty++;
+ }
+
+ switch (codeBlock->codeType()) {
+ case FunctionCode:
+ ++isFunctionCode;
+ break;
+ case GlobalCode:
+ ++isGlobalCode;
+ break;
+ case EvalCode:
+ ++isEvalCode;
+ break;
+ }
+ }
+
+ size_t totalSize = 0;
+
+ #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
+ FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
+ FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
+ FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE)
+ #undef GET_TOTAL_SIZE
+
+ totalSize += symbolTableTotalSize;
+ totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
+
+ printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
+ printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
+ printf("Size of all CodeBlocks: %zu\n", totalSize);
+ printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
+
+ printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
+ printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
+ printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
+
+ printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size());
+ printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
+
+ #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize);
+ FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
+ FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
+ FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS)
+ #undef PRINT_STATS
+
+ printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
+ printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
+
+ printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);
+
+#else
+ printf("Dumping CodeBlock statistics is not enabled.\n");
+#endif
+}
+
+
+CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
+ : m_numCalleeRegisters(0)
+ , m_numConstants(0)
+ , m_numVars(0)
+ , m_numParameters(0)
+ , m_ownerNode(ownerNode)
+ , m_globalData(0)
+#ifndef NDEBUG
+ , m_instructionCount(0)
+#endif
+ , m_needsFullScopeChain(ownerNode->needsActivation())
+ , m_usesEval(ownerNode->usesEval())
+ , m_isNumericCompareFunction(false)
+ , m_codeType(codeType)
+ , m_source(sourceProvider)
+ , m_sourceOffset(sourceOffset)
+ , m_exceptionInfo(new ExceptionInfo)
+{
+ ASSERT(m_source);
+
+#if DUMP_CODE_BLOCK_STATISTICS
+ liveCodeBlockSet.add(this);
+#endif
+}
+
+CodeBlock::~CodeBlock()
+{
+#if !ENABLE(JIT)
+ for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
+ derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
+
+ for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+ derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
+#else
+ for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
+ if (m_globalResolveInfos[i].structure)
+ m_globalResolveInfos[i].structure->deref();
+ }
+
+ for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
+ m_structureStubInfos[i].deref();
+
+ for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
+ CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
+ if (callLinkInfo->isLinked())
+ callLinkInfo->callee->removeCaller(callLinkInfo);
+ }
+
+ unlinkCallers();
+#endif
+
+#if DUMP_CODE_BLOCK_STATISTICS
+ liveCodeBlockSet.remove(this);
+#endif
+}
+
+#if ENABLE(JIT)
+void CodeBlock::unlinkCallers()
+{
+ size_t size = m_linkedCallerList.size();
+ for (size_t i = 0; i < size; ++i) {
+ CallLinkInfo* currentCaller = m_linkedCallerList[i];
+ JIT::unlinkCall(currentCaller);
+ currentCaller->setUnlinked();
+ }
+ m_linkedCallerList.clear();
+}
+#endif
+
+void CodeBlock::derefStructures(Instruction* vPC) const
+{
+ Interpreter* interpreter = m_globalData->interpreter;
+
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
+ vPC[4].u.structure->deref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
+ vPC[4].u.structure->deref();
+ vPC[5].u.structure->deref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
+ vPC[4].u.structure->deref();
+ vPC[5].u.structureChain->deref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
+ vPC[4].u.structure->deref();
+ vPC[5].u.structure->deref();
+ vPC[6].u.structureChain->deref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
+ vPC[4].u.structure->deref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
+ if(vPC[4].u.structure)
+ vPC[4].u.structure->deref();
+ return;
+ }
+ if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
+ || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
+ PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
+ polymorphicStructures->derefStructures(vPC[5].u.operand);
+ delete polymorphicStructures;
+ return;
+ }
+
+ // These instructions don't ref their Structures.
+ ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
+}
+
+void CodeBlock::refStructures(Instruction* vPC) const
+{
+ Interpreter* interpreter = m_globalData->interpreter;
+
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
+ vPC[4].u.structure->ref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
+ vPC[4].u.structure->ref();
+ vPC[5].u.structure->ref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
+ vPC[4].u.structure->ref();
+ vPC[5].u.structureChain->ref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
+ vPC[4].u.structure->ref();
+ vPC[5].u.structure->ref();
+ vPC[6].u.structureChain->ref();
+ return;
+ }
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
+ vPC[4].u.structure->ref();
+ return;
+ }
+
+ // These instructions don't ref their Structures.
+ ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
+}
+
+void CodeBlock::mark()
+{
+ for (size_t i = 0; i < m_constantRegisters.size(); ++i)
+ if (!m_constantRegisters[i].marked())
+ m_constantRegisters[i].mark();
+
+ for (size_t i = 0; i < m_functionExpressions.size(); ++i)
+ m_functionExpressions[i]->body()->mark();
+
+ if (m_rareData) {
+ for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)
+ m_rareData->m_functions[i]->body()->mark();
+
+ for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) {
+ if (!m_rareData->m_unexpectedConstants[i].marked())
+ m_rareData->m_unexpectedConstants[i].mark();
+ }
+ m_rareData->m_evalCodeCache.mark();
+ }
+}
+
+void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
+{
+ if (m_exceptionInfo)
+ return;
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ if (m_needsFullScopeChain) {
+ ScopeChain sc(scopeChain);
+ int scopeDelta = sc.localDepth();
+ if (m_codeType == EvalCode)
+ scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth();
+ else if (m_codeType == FunctionCode)
+ scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet.
+ ASSERT(scopeDelta >= 0);
+ while (scopeDelta--)
+ scopeChain = scopeChain->next;
+ }
+
+ switch (m_codeType) {
+ case FunctionCode: {
+ FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode);
+ RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode);
+ ASSERT(newFunctionBody);
+ newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount());
+
+ m_globalData->scopeNodeBeingReparsed = newFunctionBody.get();
+
+ CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this);
+ ASSERT(newCodeBlock.m_exceptionInfo);
+ ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
+
+#if ENABLE(JIT)
+ JIT::compile(m_globalData, &newCodeBlock);
+ ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
+#endif
+
+ m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
+
+ m_globalData->scopeNodeBeingReparsed = 0;
+
+ break;
+ }
+ case EvalCode: {
+ EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode);
+ RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode);
+
+ m_globalData->scopeNodeBeingReparsed = newEvalBody.get();
+
+ EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this);
+ ASSERT(newCodeBlock.m_exceptionInfo);
+ ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
+
+#if ENABLE(JIT)
+ JIT::compile(m_globalData, &newCodeBlock);
+ ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
+#endif
+
+ m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
+
+ m_globalData->scopeNodeBeingReparsed = 0;
+
+ break;
+ }
+ default:
+ // CodeBlocks for Global code blocks are transient and therefore to not gain from
+ // from throwing out there exception information.
+ ASSERT_NOT_REACHED();
+ }
+}
+
+HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
+{
+ ASSERT(bytecodeOffset < m_instructionCount);
+
+ if (!m_rareData)
+ return 0;
+
+ Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
+ for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
+ // Handlers are ordered innermost first, so the first handler we encounter
+ // that contains the source address is the correct handler to use.
+ if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset)
+ return &exceptionHandlers[i];
+ }
+
+ return 0;
+}
+
+int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
+{
+ ASSERT(bytecodeOffset < m_instructionCount);
+
+ reparseForExceptionInfoIfNecessary(callFrame);
+ ASSERT(m_exceptionInfo);
+
+ if (!m_exceptionInfo->m_lineInfo.size())
+ return m_ownerNode->source().firstLine(); // Empty function
+
+ int low = 0;
+ int high = m_exceptionInfo->m_lineInfo.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ if (!low)
+ return m_ownerNode->source().firstLine();
+ return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
+}
+
+int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
+{
+ ASSERT(bytecodeOffset < m_instructionCount);
+
+ reparseForExceptionInfoIfNecessary(callFrame);
+ ASSERT(m_exceptionInfo);
+
+ if (!m_exceptionInfo->m_expressionInfo.size()) {
+ // We didn't think anything could throw. Apparently we were wrong.
+ startOffset = 0;
+ endOffset = 0;
+ divot = 0;
+ return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+ }
+
+ int low = 0;
+ int high = m_exceptionInfo->m_expressionInfo.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ ASSERT(low);
+ if (!low) {
+ startOffset = 0;
+ endOffset = 0;
+ divot = 0;
+ return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+ }
+
+ startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset;
+ endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset;
+ divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
+ return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+}
+
+bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
+{
+ ASSERT(bytecodeOffset < m_instructionCount);
+
+ reparseForExceptionInfoIfNecessary(callFrame);
+ ASSERT(m_exceptionInfo);
+
+ if (!m_exceptionInfo->m_getByIdExceptionInfo.size())
+ return false;
+
+ int low = 0;
+ int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
+ return false;
+
+ opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
+ return true;
+}
+
+#if ENABLE(JIT)
+bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
+{
+ ASSERT(bytecodeOffset < m_instructionCount);
+
+ if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
+ return false;
+
+ int low = 0;
+ int high = m_rareData->m_functionRegisterInfos.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
+ return false;
+
+ functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
+ return true;
+}
+#endif
+
+#if !ENABLE(JIT)
+bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
+{
+ if (m_globalResolveInstructions.isEmpty())
+ return false;
+
+ int low = 0;
+ int high = m_globalResolveInstructions.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_globalResolveInstructions[mid] <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset)
+ return false;
+ return true;
+}
+#else
+bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
+{
+ if (m_globalResolveInfos.isEmpty())
+ return false;
+
+ int low = 0;
+ int high = m_globalResolveInfos.size();
+ while (low < high) {
+ int mid = low + (high - low) / 2;
+ if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset)
+ return false;
+ return true;
+}
+#endif
+
+#if ENABLE(JIT)
+void CodeBlock::setJITCode(JITCodeRef& jitCode)
+{
+ m_jitCode = jitCode;
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ m_instructions.clear();
+#endif
+}
+#endif
+
+void CodeBlock::shrinkToFit()
+{
+ m_instructions.shrinkToFit();
+
+#if !ENABLE(JIT)
+ m_propertyAccessInstructions.shrinkToFit();
+ m_globalResolveInstructions.shrinkToFit();
+#else
+ m_structureStubInfos.shrinkToFit();
+ m_globalResolveInfos.shrinkToFit();
+ m_callLinkInfos.shrinkToFit();
+ m_linkedCallerList.shrinkToFit();
+#endif
+
+ m_identifiers.shrinkToFit();
+ m_functionExpressions.shrinkToFit();
+ m_constantRegisters.shrinkToFit();
+
+ if (m_exceptionInfo) {
+ m_exceptionInfo->m_expressionInfo.shrinkToFit();
+ m_exceptionInfo->m_lineInfo.shrinkToFit();
+ m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
+ }
+
+ if (m_rareData) {
+ m_rareData->m_exceptionHandlers.shrinkToFit();
+ m_rareData->m_functions.shrinkToFit();
+ m_rareData->m_unexpectedConstants.shrinkToFit();
+ m_rareData->m_regexps.shrinkToFit();
+ m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
+ m_rareData->m_characterSwitchJumpTables.shrinkToFit();
+ m_rareData->m_stringSwitchJumpTables.shrinkToFit();
+#if ENABLE(JIT)
+ m_rareData->m_functionRegisterInfos.shrinkToFit();
+#endif
+ }
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CodeBlock_h
+#define CodeBlock_h
+
+#include "EvalCodeCache.h"
+#include "Instruction.h"
+#include "JSGlobalObject.h"
+#include "JumpTable.h"
+#include "Nodes.h"
+#include "RegExp.h"
+#include "UString.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(JIT)
+#include "StructureStubInfo.h"
+#endif
+
+namespace JSC {
+
+ class ExecState;
+
+ enum CodeType { GlobalCode, EvalCode, FunctionCode };
+
+ static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
+
+ struct HandlerInfo {
+ uint32_t start;
+ uint32_t end;
+ uint32_t target;
+ uint32_t scopeDepth;
+#if ENABLE(JIT)
+ void* nativeCode;
+#endif
+ };
+
+#if ENABLE(JIT)
+ // The code, and the associated pool from which it was allocated.
+ struct JITCodeRef {
+ void* code;
+#ifndef NDEBUG
+ unsigned codeSize;
+#endif
+ RefPtr<ExecutablePool> executablePool;
+
+ JITCodeRef()
+ : code(0)
+#ifndef NDEBUG
+ , codeSize(0)
+#endif
+ {
+ }
+
+ JITCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool)
+ : code(code)
+#ifndef NDEBUG
+ , codeSize(0)
+#endif
+ , executablePool(executablePool)
+ {
+ }
+ };
+#endif
+
+ struct ExpressionRangeInfo {
+ enum {
+ MaxOffset = (1 << 7) - 1,
+ MaxDivot = (1 << 25) - 1
+ };
+ uint32_t instructionOffset : 25;
+ uint32_t divotPoint : 25;
+ uint32_t startOffset : 7;
+ uint32_t endOffset : 7;
+ };
+
+ struct LineInfo {
+ uint32_t instructionOffset;
+ int32_t lineNumber;
+ };
+
+ // Both op_construct and op_instanceof require a use of op_get_by_id to get
+ // the prototype property from an object. The exception messages for exceptions
+ // thrown by these instances op_get_by_id need to reflect this.
+ struct GetByIdExceptionInfo {
+ unsigned bytecodeOffset : 31;
+ bool isOpConstruct : 1;
+ };
+
+#if ENABLE(JIT)
+ struct CallLinkInfo {
+ CallLinkInfo()
+ : callReturnLocation(0)
+ , hotPathBegin(0)
+ , hotPathOther(0)
+ , coldPathOther(0)
+ , callee(0)
+ {
+ }
+
+ unsigned bytecodeIndex;
+ void* callReturnLocation;
+ void* hotPathBegin;
+ void* hotPathOther;
+ void* coldPathOther;
+ CodeBlock* callee;
+ unsigned position;
+
+ void setUnlinked() { callee = 0; }
+ bool isLinked() { return callee; }
+ };
+
+ struct FunctionRegisterInfo {
+ FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
+ : bytecodeOffset(bytecodeOffset)
+ , functionRegisterIndex(functionRegisterIndex)
+ {
+ }
+
+ unsigned bytecodeOffset;
+ int functionRegisterIndex;
+ };
+
+ struct GlobalResolveInfo {
+ GlobalResolveInfo(unsigned bytecodeOffset)
+ : structure(0)
+ , offset(0)
+ , bytecodeOffset(bytecodeOffset)
+ {
+ }
+
+ Structure* structure;
+ unsigned offset;
+ unsigned bytecodeOffset;
+ };
+
+ struct PC {
+ PC(ptrdiff_t nativePCOffset, unsigned bytecodeIndex)
+ : nativePCOffset(nativePCOffset)
+ , bytecodeIndex(bytecodeIndex)
+ {
+ }
+
+ ptrdiff_t nativePCOffset;
+ unsigned bytecodeIndex;
+ };
+
+ // valueAtPosition helpers for the binaryChop algorithm below.
+
+ inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
+ {
+ return structureStubInfo->callReturnLocation;
+ }
+
+ inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
+ {
+ return callLinkInfo->callReturnLocation;
+ }
+
+ inline ptrdiff_t getNativePCOffset(PC* pc)
+ {
+ return pc->nativePCOffset;
+ }
+
+ // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
+ // compares result with key (KeyTypes should be comparable with '--', '<', '>').
+ // Optimized for cases where the array contains the key, checked by assertions.
+ template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
+ inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
+ {
+ // The array must contain at least one element (pre-condition, array does conatin key).
+ // If the array only contains one element, no need to do the comparison.
+ while (size > 1) {
+ // Pick an element to check, half way through the array, and read the value.
+ int pos = (size - 1) >> 1;
+ KeyType val = valueAtPosition(&array[pos]);
+
+ // If the key matches, success!
+ if (val == key)
+ return &array[pos];
+ // The item we are looking for is smaller than the item being check; reduce the value of 'size',
+ // chopping off the right hand half of the array.
+ else if (key < val)
+ size = pos;
+ // Discard all values in the left hand half of the array, up to and including the item at pos.
+ else {
+ size -= (pos + 1);
+ array += (pos + 1);
+ }
+
+ // 'size' should never reach zero.
+ ASSERT(size);
+ }
+
+ // If we reach this point we've chopped down to one element, no need to check it matches
+ ASSERT(size == 1);
+ ASSERT(key == valueAtPosition(&array[0]));
+ return &array[0];
+ }
+#endif
+
+ class CodeBlock {
+ friend class JIT;
+ public:
+ CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
+ ~CodeBlock();
+
+ void mark();
+ void refStructures(Instruction* vPC) const;
+ void derefStructures(Instruction* vPC) const;
+#if ENABLE(JIT)
+ void unlinkCallers();
+#endif
+
+ static void dumpStatistics();
+
+#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
+ void dump(ExecState*) const;
+ void printStructures(const Instruction*) const;
+ void printStructure(const char* name, const Instruction*, int operand) const;
+#endif
+
+ inline bool isKnownNotImmediate(int index)
+ {
+ if (index == m_thisRegister)
+ return true;
+
+ if (isConstantRegisterIndex(index))
+ return getConstant(index).isCell();
+
+ return false;
+ }
+
+ ALWAYS_INLINE bool isConstantRegisterIndex(int index)
+ {
+ return index >= m_numVars && index < m_numVars + m_numConstants;
+ }
+
+ ALWAYS_INLINE JSValuePtr getConstant(int index)
+ {
+ return m_constantRegisters[index - m_numVars].getJSValue();
+ }
+
+ ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)
+ {
+ return index >= m_numVars + m_numConstants;
+ }
+
+ HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
+ int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
+ int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
+ bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
+
+#if ENABLE(JIT)
+ void addCaller(CallLinkInfo* caller)
+ {
+ caller->callee = this;
+ caller->position = m_linkedCallerList.size();
+ m_linkedCallerList.append(caller);
+ }
+
+ void removeCaller(CallLinkInfo* caller)
+ {
+ unsigned pos = caller->position;
+ unsigned lastPos = m_linkedCallerList.size() - 1;
+
+ if (pos != lastPos) {
+ m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
+ m_linkedCallerList[pos]->position = pos;
+ }
+ m_linkedCallerList.shrink(lastPos);
+ }
+
+ StructureStubInfo& getStubInfo(void* returnAddress)
+ {
+ return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
+ }
+
+ CallLinkInfo& getCallLinkInfo(void* returnAddress)
+ {
+ return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
+ }
+
+ unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC)
+ {
+ reparseForExceptionInfoIfNecessary(callFrame);
+ ptrdiff_t nativePCOffset = reinterpret_cast<void**>(nativePC) - reinterpret_cast<void**>(m_jitCode.code);
+ return binaryChop<PC, ptrdiff_t, getNativePCOffset>(m_exceptionInfo->m_pcVector.begin(), m_exceptionInfo->m_pcVector.size(), nativePCOffset)->bytecodeIndex;
+ }
+
+ bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
+#endif
+
+ void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
+ bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
+
+ Vector<Instruction>& instructions() { return m_instructions; }
+#ifndef NDEBUG
+ void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
+#endif
+
+#if ENABLE(JIT)
+ void setJITCode(JITCodeRef& jitCode);
+ void* jitCode() { return m_jitCode.code; }
+ ExecutablePool* executablePool() { return m_jitCode.executablePool.get(); }
+#endif
+
+ ScopeNode* ownerNode() const { return m_ownerNode; }
+
+ void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
+
+ void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
+ int thisRegister() const { return m_thisRegister; }
+
+ void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
+ bool needsFullScopeChain() const { return m_needsFullScopeChain; }
+ void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
+ bool usesEval() const { return m_usesEval; }
+ void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
+ bool usesArguments() const { return m_usesArguments; }
+
+ CodeType codeType() const { return m_codeType; }
+
+ SourceProvider* source() const { return m_source.get(); }
+ unsigned sourceOffset() const { return m_sourceOffset; }
+
+ size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
+ void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
+ unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
+ unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
+
+#if !ENABLE(JIT)
+ void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
+ void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
+ bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
+#else
+ size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
+ void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
+ StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
+
+ void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); }
+ GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
+ bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
+
+ size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
+ void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
+ CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
+
+ void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
+#endif
+
+ // Exception handling support
+
+ size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
+ void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
+ HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
+
+ bool hasExceptionInfo() const { return m_exceptionInfo; }
+ void clearExceptionInfo() { m_exceptionInfo.clear(); }
+
+ void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
+ void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
+
+ size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
+ void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
+ LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); }
+
+#if ENABLE(JIT)
+ Vector<PC>& pcVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_pcVector; }
+#endif
+
+ // Constant Pool
+
+ size_t numberOfIdentifiers() const { return m_identifiers.size(); }
+ void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
+ Identifier& identifier(int index) { return m_identifiers[index]; }
+
+ size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
+ void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
+ Register& constantRegister(int index) { return m_constantRegisters[index]; }
+
+ unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
+ FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
+
+ unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; }
+ FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); }
+
+ bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); }
+
+ unsigned addUnexpectedConstant(JSValuePtr v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; }
+ JSValuePtr unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; }
+
+ unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
+ RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
+
+
+ // Jump Tables
+
+ size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
+ SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
+ SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
+
+ size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
+ SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
+ SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
+
+ size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
+ StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
+ StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
+
+
+ SymbolTable& symbolTable() { return m_symbolTable; }
+
+ EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
+
+ void shrinkToFit();
+
+ // FIXME: Make these remaining members private.
+
+ int m_numCalleeRegisters;
+ // NOTE: numConstants holds the number of constant registers allocated
+ // by the code generator, not the number of constant registers used.
+ // (Duplicate constants are uniqued during code generation, and spare
+ // constant registers may be allocated.)
+ int m_numConstants;
+ int m_numVars;
+ int m_numParameters;
+
+ private:
+#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
+ void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
+#endif
+
+ void reparseForExceptionInfoIfNecessary(CallFrame*);
+
+ void createRareDataIfNecessary()
+ {
+ if (!m_rareData)
+ m_rareData.set(new RareData);
+ }
+
+ ScopeNode* m_ownerNode;
+ JSGlobalData* m_globalData;
+
+ Vector<Instruction> m_instructions;
+#ifndef NDEBUG
+ unsigned m_instructionCount;
+#endif
+#if ENABLE(JIT)
+ JITCodeRef m_jitCode;
+#endif
+
+ int m_thisRegister;
+
+ bool m_needsFullScopeChain;
+ bool m_usesEval;
+ bool m_usesArguments;
+ bool m_isNumericCompareFunction;
+
+ CodeType m_codeType;
+
+ RefPtr<SourceProvider> m_source;
+ unsigned m_sourceOffset;
+
+#if !ENABLE(JIT)
+ Vector<unsigned> m_propertyAccessInstructions;
+ Vector<unsigned> m_globalResolveInstructions;
+#else
+ Vector<StructureStubInfo> m_structureStubInfos;
+ Vector<GlobalResolveInfo> m_globalResolveInfos;
+ Vector<CallLinkInfo> m_callLinkInfos;
+ Vector<CallLinkInfo*> m_linkedCallerList;
+#endif
+
+ Vector<unsigned> m_jumpTargets;
+
+ // Constant Pool
+ Vector<Identifier> m_identifiers;
+ Vector<Register> m_constantRegisters;
+ Vector<RefPtr<FuncExprNode> > m_functionExpressions;
+
+ SymbolTable m_symbolTable;
+
+ struct ExceptionInfo {
+ Vector<ExpressionRangeInfo> m_expressionInfo;
+ Vector<LineInfo> m_lineInfo;
+ Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
+
+#if ENABLE(JIT)
+ Vector<PC> m_pcVector;
+#endif
+ };
+ OwnPtr<ExceptionInfo> m_exceptionInfo;
+
+ struct RareData {
+ Vector<HandlerInfo> m_exceptionHandlers;
+
+ // Rare Constants
+ Vector<RefPtr<FuncDeclNode> > m_functions;
+ Vector<JSValuePtr> m_unexpectedConstants;
+ Vector<RefPtr<RegExp> > m_regexps;
+
+ // Jump Tables
+ Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
+ Vector<SimpleJumpTable> m_characterSwitchJumpTables;
+ Vector<StringJumpTable> m_stringSwitchJumpTables;
+
+ EvalCodeCache m_evalCodeCache;
+
+#if ENABLE(JIT)
+ Vector<FunctionRegisterInfo> m_functionRegisterInfos;
+#endif
+ };
+ OwnPtr<RareData> m_rareData;
+ };
+
+ // Program code is not marked by any function, so we make the global object
+ // responsible for marking it.
+
+ class ProgramCodeBlock : public CodeBlock {
+ public:
+ ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
+ : CodeBlock(ownerNode, codeType, sourceProvider, 0)
+ , m_globalObject(globalObject)
+ {
+ m_globalObject->codeBlocks().add(this);
+ }
+
+ ~ProgramCodeBlock()
+ {
+ if (m_globalObject)
+ m_globalObject->codeBlocks().remove(this);
+ }
+
+ void clearGlobalObject() { m_globalObject = 0; }
+
+ private:
+ JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
+ };
+
+ class EvalCodeBlock : public ProgramCodeBlock {
+ public:
+ EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
+ : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
+ , m_baseScopeDepth(baseScopeDepth)
+ {
+ }
+
+ int baseScopeDepth() const { return m_baseScopeDepth; }
+
+ private:
+ int m_baseScopeDepth;
+ };
+
+} // namespace JSC
+
+#endif // CodeBlock_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EvalCodeCache_h
+#define EvalCodeCache_h
+
+#include "JSGlobalObject.h"
+#include "Nodes.h"
+#include "Parser.h"
+#include "SourceCode.h"
+#include "UString.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class EvalCodeCache {
+ public:
+ PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValuePtr& exceptionValue)
+ {
+ RefPtr<EvalNode> evalNode;
+
+ if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
+ evalNode = m_cacheMap.get(evalSource.rep());
+
+ if (!evalNode) {
+ int errorLine;
+ UString errorMessage;
+
+ SourceCode source = makeSource(evalSource);
+ evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage);
+ if (evalNode) {
+ if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
+ m_cacheMap.set(evalSource.rep(), evalNode);
+ } else {
+ exceptionValue = Error::create(exec, SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0);
+ return 0;
+ }
+ }
+
+ return evalNode.release();
+ }
+
+ bool isEmpty() const { return m_cacheMap.isEmpty(); }
+
+ void mark()
+ {
+ EvalCacheMap::iterator end = m_cacheMap.end();
+ for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
+ ptr->second->mark();
+ }
+ private:
+ static const int maxCacheableSourceLength = 256;
+ static const int maxCacheEntries = 64;
+
+ typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > EvalCacheMap;
+ EvalCacheMap m_cacheMap;
+ };
+
+} // namespace JSC
+
+#endif // EvalCodeCache_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Instruction_h
+#define Instruction_h
+
+#include "Opcode.h"
+#include "Structure.h"
+#include <wtf/VectorTraits.h>
+
+#define POLYMORPHIC_LIST_CACHE_SIZE 4
+
+namespace JSC {
+
+ class JSCell;
+ class Structure;
+ class StructureChain;
+
+ // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
+ struct PolymorphicAccessStructureList {
+ struct PolymorphicStubInfo {
+ bool isChain;
+ void* stubRoutine;
+ Structure* base;
+ union {
+ Structure* proto;
+ StructureChain* chain;
+ } u;
+
+ void set(void* _stubRoutine, Structure* _base)
+ {
+ stubRoutine = _stubRoutine;
+ base = _base;
+ u.proto = 0;
+ isChain = false;
+ }
+
+ void set(void* _stubRoutine, Structure* _base, Structure* _proto)
+ {
+ stubRoutine = _stubRoutine;
+ base = _base;
+ u.proto = _proto;
+ isChain = false;
+ }
+
+ void set(void* _stubRoutine, Structure* _base, StructureChain* _chain)
+ {
+ stubRoutine = _stubRoutine;
+ base = _base;
+ u.chain = _chain;
+ isChain = true;
+ }
+ } list[POLYMORPHIC_LIST_CACHE_SIZE];
+
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase)
+ {
+ list[0].set(stubRoutine, firstBase);
+ }
+
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, Structure* firstProto)
+ {
+ list[0].set(stubRoutine, firstBase, firstProto);
+ }
+
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, StructureChain* firstChain)
+ {
+ list[0].set(stubRoutine, firstBase, firstChain);
+ }
+
+ void derefStructures(int count)
+ {
+ for (int i = 0; i < count; ++i) {
+ PolymorphicStubInfo& info = list[i];
+
+ ASSERT(info.base);
+ info.base->deref();
+
+ if (info.u.proto) {
+ if (info.isChain)
+ info.u.chain->deref();
+ else
+ info.u.proto->deref();
+ }
+ }
+ }
+ };
+
+ struct Instruction {
+ Instruction(Opcode opcode)
+ {
+#if !HAVE(COMPUTED_GOTO)
+ // We have to initialize one of the pointer members to ensure that
+ // the entire struct is initialized, when opcode is not a pointer.
+ u.jsCell = 0;
+#endif
+ u.opcode = opcode;
+ }
+
+ Instruction(int operand)
+ {
+ // We have to initialize one of the pointer members to ensure that
+ // the entire struct is initialized in 64-bit.
+ u.jsCell = 0;
+ u.operand = operand;
+ }
+
+ Instruction(Structure* structure) { u.structure = structure; }
+ Instruction(StructureChain* structureChain) { u.structureChain = structureChain; }
+ Instruction(JSCell* jsCell) { u.jsCell = jsCell; }
+ Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
+
+ union {
+ Opcode opcode;
+ int operand;
+ Structure* structure;
+ StructureChain* structureChain;
+ JSCell* jsCell;
+ PolymorphicAccessStructureList* polymorphicStructures;
+ } u;
+ };
+
+} // namespace JSC
+
+namespace WTF {
+
+ template<> struct VectorTraits<JSC::Instruction> : VectorTraitsBase<true, JSC::Instruction> { };
+
+} // namespace WTF
+
+#endif // Instruction_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JumpTable.h"
+
+namespace JSC {
+
+int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)
+{
+ if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) {
+ int32_t offset = branchOffsets[value - min];
+ if (offset)
+ return offset;
+ }
+ return defaultOffset;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JumpTable_h
+#define JumpTable_h
+
+#include "UString.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ struct OffsetLocation {
+ int32_t branchOffset;
+#if ENABLE(JIT)
+ void* ctiOffset;
+#endif
+ };
+
+ struct StringJumpTable {
+ typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
+ StringOffsetTable offsetTable;
+#if ENABLE(JIT)
+ void* ctiDefault; // FIXME: it should not be necessary to store this.
+#endif
+
+ inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
+ {
+ StringOffsetTable::const_iterator end = offsetTable.end();
+ StringOffsetTable::const_iterator loc = offsetTable.find(value);
+ if (loc == end)
+ return defaultOffset;
+ return loc->second.branchOffset;
+ }
+
+#if ENABLE(JIT)
+ inline void* ctiForValue(UString::Rep* value)
+ {
+ StringOffsetTable::const_iterator end = offsetTable.end();
+ StringOffsetTable::const_iterator loc = offsetTable.find(value);
+ if (loc == end)
+ return ctiDefault;
+ return loc->second.ctiOffset;
+ }
+#endif
+ };
+
+ struct SimpleJumpTable {
+ // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>
+ Vector<int32_t> branchOffsets;
+ int32_t min;
+#if ENABLE(JIT)
+ Vector<void*> ctiOffsets;
+ void* ctiDefault;
+#endif
+
+ int32_t offsetForValue(int32_t value, int32_t defaultOffset);
+ void add(int32_t key, int32_t offset)
+ {
+ if (!branchOffsets[key])
+ branchOffsets[key] = offset;
+ }
+
+#if ENABLE(JIT)
+ inline void* ctiForValue(int32_t value)
+ {
+ if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
+ return ctiOffsets[value - min];
+ return ctiDefault;
+ }
+#endif
+ };
+
+} // namespace JSC
+
+#endif // JumpTable_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Opcode.h"
+
+using namespace std;
+
+namespace JSC {
+
+#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
+
+const char* const opcodeNames[] = {
+#define OPCODE_NAME_ENTRY(opcode, size) #opcode,
+ FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
+#undef OPCODE_NAME_ENTRY
+};
+
+#endif
+
+#if ENABLE(OPCODE_STATS)
+
+long long OpcodeStats::opcodeCounts[numOpcodeIDs];
+long long OpcodeStats::opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
+int OpcodeStats::lastOpcode = -1;
+
+static OpcodeStats logger;
+
+OpcodeStats::OpcodeStats()
+{
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ opcodeCounts[i] = 0;
+
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ for (int j = 0; j < numOpcodeIDs; ++j)
+ opcodePairCounts[i][j] = 0;
+}
+
+static int compareOpcodeIndices(const void* left, const void* right)
+{
+ long long leftValue = OpcodeStats::opcodeCounts[*(int*) left];
+ long long rightValue = OpcodeStats::opcodeCounts[*(int*) right];
+
+ if (leftValue < rightValue)
+ return 1;
+ else if (leftValue > rightValue)
+ return -1;
+ else
+ return 0;
+}
+
+static int compareOpcodePairIndices(const void* left, const void* right)
+{
+ pair<int, int> leftPair = *(pair<int, int>*) left;
+ long long leftValue = OpcodeStats::opcodePairCounts[leftPair.first][leftPair.second];
+ pair<int, int> rightPair = *(pair<int, int>*) right;
+ long long rightValue = OpcodeStats::opcodePairCounts[rightPair.first][rightPair.second];
+
+ if (leftValue < rightValue)
+ return 1;
+ else if (leftValue > rightValue)
+ return -1;
+ else
+ return 0;
+}
+
+OpcodeStats::~OpcodeStats()
+{
+ long long totalInstructions = 0;
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ totalInstructions += opcodeCounts[i];
+
+ long long totalInstructionPairs = 0;
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ for (int j = 0; j < numOpcodeIDs; ++j)
+ totalInstructionPairs += opcodePairCounts[i][j];
+
+ int sortedIndices[numOpcodeIDs];
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ sortedIndices[i] = i;
+ qsort(sortedIndices, numOpcodeIDs, sizeof(int), compareOpcodeIndices);
+
+ pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs];
+ pair<int, int>* currentPairIndex = sortedPairIndices;
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ for (int j = 0; j < numOpcodeIDs; ++j)
+ *(currentPairIndex++) = make_pair(i, j);
+ qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
+
+ printf("\nExecuted opcode statistics\n");
+
+ printf("Total instructions executed: %lld\n\n", totalInstructions);
+
+ printf("All opcodes by frequency:\n\n");
+
+ for (int i = 0; i < numOpcodeIDs; ++i) {
+ int index = sortedIndices[i];
+ printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);
+ }
+
+ printf("\n");
+ printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
+
+ for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
+ pair<int, int> indexPair = sortedPairIndices[i];
+ long long count = opcodePairCounts[indexPair.first][indexPair.second];
+
+ if (!count)
+ break;
+
+ printf("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
+ }
+
+ printf("\n");
+ printf("Most common opcodes and sequences:\n");
+
+ for (int i = 0; i < numOpcodeIDs; ++i) {
+ int index = sortedIndices[i];
+ long long opcodeCount = opcodeCounts[index];
+ double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
+ if (opcodeProportion < 0.0001)
+ break;
+ printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCount, opcodeProportion * 100.0);
+
+ for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
+ pair<int, int> indexPair = sortedPairIndices[j];
+ long long pairCount = opcodePairCounts[indexPair.first][indexPair.second];
+ double pairProportion = ((double) pairCount) / ((double) totalInstructionPairs);
+
+ if (!pairCount || pairProportion < 0.0001 || pairProportion < opcodeProportion / 100)
+ break;
+
+ if (indexPair.first != index && indexPair.second != index)
+ continue;
+
+ printf(" %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), pairCount, pairProportion * 100.0);
+ }
+
+ }
+ printf("\n");
+}
+
+void OpcodeStats::recordInstruction(int opcode)
+{
+ opcodeCounts[opcode]++;
+
+ if (lastOpcode != -1)
+ opcodePairCounts[lastOpcode][opcode]++;
+
+ lastOpcode = opcode;
+}
+
+void OpcodeStats::resetLastInstruction()
+{
+ lastOpcode = -1;
+}
+
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Opcode_h
+#define Opcode_h
+
+#include <algorithm>
+#include <string.h>
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ #define FOR_EACH_OPCODE_ID(macro) \
+ macro(op_enter, 1) \
+ macro(op_enter_with_activation, 2) \
+ macro(op_create_arguments, 1) \
+ macro(op_convert_this, 2) \
+ \
+ macro(op_unexpected_load, 3) \
+ macro(op_new_object, 2) \
+ macro(op_new_array, 4) \
+ macro(op_new_regexp, 3) \
+ macro(op_mov, 3) \
+ \
+ macro(op_not, 3) \
+ macro(op_eq, 4) \
+ macro(op_eq_null, 3) \
+ macro(op_neq, 4) \
+ macro(op_neq_null, 3) \
+ macro(op_stricteq, 4) \
+ macro(op_nstricteq, 4) \
+ macro(op_less, 4) \
+ macro(op_lesseq, 4) \
+ \
+ macro(op_pre_inc, 2) \
+ macro(op_pre_dec, 2) \
+ macro(op_post_inc, 3) \
+ macro(op_post_dec, 3) \
+ macro(op_to_jsnumber, 3) \
+ macro(op_negate, 3) \
+ macro(op_add, 5) \
+ macro(op_mul, 5) \
+ macro(op_div, 4) \
+ macro(op_mod, 4) \
+ macro(op_sub, 5) \
+ \
+ macro(op_lshift, 4) \
+ macro(op_rshift, 4) \
+ macro(op_urshift, 4) \
+ macro(op_bitand, 5) \
+ macro(op_bitxor, 5) \
+ macro(op_bitor, 5) \
+ macro(op_bitnot, 3) \
+ \
+ macro(op_instanceof, 5) \
+ macro(op_typeof, 3) \
+ macro(op_is_undefined, 3) \
+ macro(op_is_boolean, 3) \
+ macro(op_is_number, 3) \
+ macro(op_is_string, 3) \
+ macro(op_is_object, 3) \
+ macro(op_is_function, 3) \
+ macro(op_in, 4) \
+ \
+ macro(op_resolve, 3) \
+ macro(op_resolve_skip, 4) \
+ macro(op_resolve_global, 6) \
+ macro(op_get_scoped_var, 4) \
+ macro(op_put_scoped_var, 4) \
+ macro(op_get_global_var, 4) \
+ macro(op_put_global_var, 4) \
+ macro(op_resolve_base, 3) \
+ macro(op_resolve_with_base, 4) \
+ macro(op_resolve_func, 4) \
+ macro(op_get_by_id, 8) \
+ macro(op_get_by_id_self, 8) \
+ macro(op_get_by_id_self_list, 8) \
+ macro(op_get_by_id_proto, 8) \
+ macro(op_get_by_id_proto_list, 8) \
+ macro(op_get_by_id_chain, 8) \
+ macro(op_get_by_id_generic, 8) \
+ macro(op_get_array_length, 8) \
+ macro(op_get_string_length, 8) \
+ macro(op_put_by_id, 8) \
+ macro(op_put_by_id_transition, 8) \
+ macro(op_put_by_id_replace, 8) \
+ macro(op_put_by_id_generic, 8) \
+ macro(op_del_by_id, 4) \
+ macro(op_get_by_val, 4) \
+ macro(op_put_by_val, 4) \
+ macro(op_del_by_val, 4) \
+ macro(op_put_by_index, 4) \
+ macro(op_put_getter, 4) \
+ macro(op_put_setter, 4) \
+ \
+ macro(op_jmp, 2) \
+ macro(op_jtrue, 3) \
+ macro(op_jfalse, 3) \
+ macro(op_jeq_null, 3) \
+ macro(op_jneq_null, 3) \
+ macro(op_jnless, 4) \
+ macro(op_jmp_scopes, 3) \
+ macro(op_loop, 2) \
+ macro(op_loop_if_true, 3) \
+ macro(op_loop_if_less, 4) \
+ macro(op_loop_if_lesseq, 4) \
+ macro(op_switch_imm, 4) \
+ macro(op_switch_char, 4) \
+ macro(op_switch_string, 4) \
+ \
+ macro(op_new_func, 3) \
+ macro(op_new_func_exp, 3) \
+ macro(op_call, 5) \
+ macro(op_call_eval, 5) \
+ macro(op_tear_off_activation, 2) \
+ macro(op_tear_off_arguments, 1) \
+ macro(op_ret, 2) \
+ \
+ macro(op_construct, 7) \
+ macro(op_construct_verify, 3) \
+ \
+ macro(op_get_pnames, 3) \
+ macro(op_next_pname, 4) \
+ \
+ macro(op_push_scope, 2) \
+ macro(op_pop_scope, 1) \
+ macro(op_push_new_scope, 4) \
+ \
+ macro(op_catch, 2) \
+ macro(op_throw, 2) \
+ macro(op_new_error, 4) \
+ \
+ macro(op_jsr, 3) \
+ macro(op_sret, 2) \
+ \
+ macro(op_debug, 4) \
+ macro(op_profile_will_call, 2) \
+ macro(op_profile_did_call, 2) \
+ \
+ macro(op_end, 2) // end must be the last opcode in the list
+
+ #define OPCODE_ID_ENUM(opcode, length) opcode,
+ typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
+ #undef OPCODE_ID_ENUM
+
+ const int numOpcodeIDs = op_end + 1;
+
+ #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
+ FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS);
+ #undef OPCODE_ID_SIZES
+
+ #define OPCODE_LENGTH(opcode) opcode##_length
+
+ #define OPCODE_ID_LENGTH_MAP(opcode, length) length,
+ const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) };
+ #undef OPCODE_ID_LENGTH_MAP
+
+ #define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= op_end, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
+ FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
+ #undef VERIFY_OPCODE_ID
+
+#if HAVE(COMPUTED_GOTO)
+ typedef void* Opcode;
+#else
+ typedef OpcodeID Opcode;
+#endif
+
+#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
+
+#define PADDING_STRING " "
+#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
+
+ extern const char* const opcodeNames[];
+
+ inline const char* padOpcodeName(OpcodeID op, unsigned width)
+ {
+ unsigned pad = width - strlen(opcodeNames[op]);
+ pad = std::min(pad, PADDING_STRING_LENGTH);
+ return PADDING_STRING + PADDING_STRING_LENGTH - pad;
+ }
+
+#undef PADDING_STRING_LENGTH
+#undef PADDING_STRING
+
+#endif
+
+#if ENABLE(OPCODE_STATS)
+
+ struct OpcodeStats {
+ OpcodeStats();
+ ~OpcodeStats();
+ static long long opcodeCounts[numOpcodeIDs];
+ static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
+ static int lastOpcode;
+
+ static void recordInstruction(int opcode);
+ static void resetLastInstruction();
+ };
+
+#endif
+
+} // namespace JSC
+
+#endif // Opcode_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SamplingTool.h"
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "Opcode.h"
+
+#if !PLATFORM(WIN_OS)
+#include <unistd.h>
+#endif
+
+namespace JSC {
+
+void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC)
+{
+ if (!m_samples) {
+ m_size = codeBlock->instructions().size();
+ m_samples = static_cast<int*>(calloc(m_size, sizeof(int)));
+ m_codeBlock = codeBlock;
+ }
+
+ ++m_sampleCount;
+
+ unsigned offest = vPC - codeBlock->instructions().begin();
+ // Since we don't read and write codeBlock and vPC atomically, this check
+ // can fail if we sample mid op_call / op_ret.
+ if (offest < m_size) {
+ m_samples[offest]++;
+ m_opcodeSampleCount++;
+ }
+}
+
+#if PLATFORM(WIN_OS)
+
+static void sleepForMicroseconds(unsigned us)
+{
+ unsigned ms = us / 1000;
+ if (us && !ms)
+ ms = 1;
+ Sleep(ms);
+}
+
+#else
+
+static void sleepForMicroseconds(unsigned us)
+{
+ usleep(us);
+}
+
+#endif
+
+static inline unsigned hertz2us(unsigned hertz)
+{
+ return 1000000 / hertz;
+}
+
+void SamplingTool::run()
+{
+ while (m_running) {
+ sleepForMicroseconds(hertz2us(m_hertz));
+
+ Sample sample(m_sample, m_codeBlock);
+ ++m_sampleCount;
+
+ if (sample.isNull())
+ continue;
+
+ if (!sample.inHostFunction()) {
+ unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode);
+
+ ++m_opcodeSampleCount;
+ ++m_opcodeSamples[opcodeID];
+
+ if (sample.inCTIFunction())
+ m_opcodeSamplesInCTIFunctions[opcodeID]++;
+ }
+
+#if ENABLE(CODEBLOCK_SAMPLING)
+ MutexLocker locker(m_scopeSampleMapMutex);
+ ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode());
+ ASSERT(record);
+ record->sample(sample.codeBlock(), sample.vPC());
+#endif
+ }
+}
+
+void* SamplingTool::threadStartFunc(void* samplingTool)
+{
+ reinterpret_cast<SamplingTool*>(samplingTool)->run();
+ return 0;
+}
+
+void SamplingTool::notifyOfScope(ScopeNode* scope)
+{
+ MutexLocker locker(m_scopeSampleMapMutex);
+ m_scopeSampleMap->set(scope, new ScopeSampleRecord(scope));
+}
+
+void SamplingTool::start(unsigned hertz)
+{
+ ASSERT(!m_running);
+ m_running = true;
+ m_hertz = hertz;
+
+ m_samplingThread = createThread(threadStartFunc, this, "JavaScriptCore::Sampler");
+}
+
+void SamplingTool::stop()
+{
+ ASSERT(m_running);
+ m_running = false;
+ waitForThreadCompletion(m_samplingThread, 0);
+}
+
+#if ENABLE(OPCODE_SAMPLING)
+
+struct OpcodeSampleInfo {
+ OpcodeID opcode;
+ long long count;
+ long long countInCTIFunctions;
+};
+
+struct LineCountInfo {
+ unsigned line;
+ unsigned count;
+};
+
+static int compareLineCountInfoSampling(const void* left, const void* right)
+{
+ const LineCountInfo* leftLineCount = reinterpret_cast<const LineCountInfo*>(left);
+ const LineCountInfo* rightLineCount = reinterpret_cast<const LineCountInfo*>(right);
+
+ return (leftLineCount->line > rightLineCount->line) ? 1 : (leftLineCount->line < rightLineCount->line) ? -1 : 0;
+}
+
+static int compareOpcodeIndicesSampling(const void* left, const void* right)
+{
+ const OpcodeSampleInfo* leftSampleInfo = reinterpret_cast<const OpcodeSampleInfo*>(left);
+ const OpcodeSampleInfo* rightSampleInfo = reinterpret_cast<const OpcodeSampleInfo*>(right);
+
+ return (leftSampleInfo->count < rightSampleInfo->count) ? 1 : (leftSampleInfo->count > rightSampleInfo->count) ? -1 : 0;
+}
+
+static int compareScopeSampleRecords(const void* left, const void* right)
+{
+ const ScopeSampleRecord* const leftValue = *static_cast<const ScopeSampleRecord* const *>(left);
+ const ScopeSampleRecord* const rightValue = *static_cast<const ScopeSampleRecord* const *>(right);
+
+ return (leftValue->m_sampleCount < rightValue->m_sampleCount) ? 1 : (leftValue->m_sampleCount > rightValue->m_sampleCount) ? -1 : 0;
+}
+
+void SamplingTool::dump(ExecState* exec)
+{
+ // Tidies up SunSpider output by removing short scripts - such a small number of samples would likely not be useful anyhow.
+ if (m_sampleCount < 10)
+ return;
+
+ // (1) Build and sort 'opcodeSampleInfo' array.
+
+ OpcodeSampleInfo opcodeSampleInfo[numOpcodeIDs];
+ for (int i = 0; i < numOpcodeIDs; ++i) {
+ opcodeSampleInfo[i].opcode = static_cast<OpcodeID>(i);
+ opcodeSampleInfo[i].count = m_opcodeSamples[i];
+ opcodeSampleInfo[i].countInCTIFunctions = m_opcodeSamplesInCTIFunctions[i];
+ }
+
+ qsort(opcodeSampleInfo, numOpcodeIDs, sizeof(OpcodeSampleInfo), compareOpcodeIndicesSampling);
+
+ // (2) Print Opcode sampling results.
+
+ printf("\nBytecode samples [*]\n");
+ printf(" sample %% of %% of | cti cti %%\n");
+ printf("opcode count VM total | count of self\n");
+ printf("------------------------------------------------------- | ----------------\n");
+
+ for (int i = 0; i < numOpcodeIDs; ++i) {
+ long long count = opcodeSampleInfo[i].count;
+ if (!count)
+ continue;
+
+ OpcodeID opcodeID = opcodeSampleInfo[i].opcode;
+
+ const char* opcodeName = opcodeNames[opcodeID];
+ const char* opcodePadding = padOpcodeName(opcodeID, 28);
+ double percentOfVM = (static_cast<double>(count) * 100) / m_opcodeSampleCount;
+ double percentOfTotal = (static_cast<double>(count) * 100) / m_sampleCount;
+ long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions;
+ double percentInCTIFunctions = (static_cast<double>(countInCTIFunctions) * 100) / count;
+ fprintf(stdout, "%s:%s%-6lld %.3f%%\t%.3f%%\t | %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions);
+ }
+
+ printf("\n[*] Samples inside host code are not charged to any Bytecode.\n\n");
+ printf("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_opcodeSampleCount) * 100) / m_sampleCount);
+ printf("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount);
+ printf("\tsample count:\tsamples inside this opcode\n");
+ printf("\t%% of VM:\tsample count / all opcode samples\n");
+ printf("\t%% of total:\tsample count / all samples\n");
+ printf("\t--------------\n");
+ printf("\tcti count:\tsamples inside a CTI function called by this opcode\n");
+ printf("\tcti %% of self:\tcti count / sample count\n");
+
+ // (3) Build and sort 'codeBlockSamples' array.
+
+ int scopeCount = m_scopeSampleMap->size();
+ Vector<ScopeSampleRecord*> codeBlockSamples(scopeCount);
+ ScopeSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
+ for (int i = 0; i < scopeCount; ++i, ++iter)
+ codeBlockSamples[i] = iter->second;
+
+ qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScopeSampleRecord*), compareScopeSampleRecords);
+
+ // (4) Print data from 'codeBlockSamples' array.
+
+ printf("\nCodeBlock samples\n\n");
+
+ for (int i = 0; i < scopeCount; ++i) {
+ ScopeSampleRecord* record = codeBlockSamples[i];
+ CodeBlock* codeBlock = record->m_codeBlock;
+
+ double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount;
+
+ if (blockPercent >= 1) {
+ //Instruction* code = codeBlock->instructions().begin();
+ printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent);
+ if (i < 10) {
+ HashMap<unsigned,unsigned> lineCounts;
+ codeBlock->dump(exec);
+
+ printf(" Opcode and line number samples [*]\n\n");
+ for (unsigned op = 0; op < record->m_size; ++op) {
+ int count = record->m_samples[op];
+ if (count) {
+ printf(" [% 4d] has sample count: % 4d\n", op, count);
+ unsigned line = codeBlock->lineNumberForBytecodeOffset(exec, op);
+ lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
+ }
+ }
+ printf("\n");
+
+ int linesCount = lineCounts.size();
+ Vector<LineCountInfo> lineCountInfo(linesCount);
+ int lineno = 0;
+ for (HashMap<unsigned,unsigned>::iterator iter = lineCounts.begin(); iter != lineCounts.end(); ++iter, ++lineno) {
+ lineCountInfo[lineno].line = iter->first;
+ lineCountInfo[lineno].count = iter->second;
+ }
+
+ qsort(lineCountInfo.begin(), linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling);
+
+ for (lineno = 0; lineno < linesCount; ++lineno) {
+ printf(" Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count);
+ }
+ printf("\n");
+ printf(" [*] Samples inside host code are charged to the calling Bytecode.\n");
+ printf(" Samples on a call / return boundary are not charged to a specific opcode or line.\n\n");
+ printf(" Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast<double>(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount);
+ }
+ }
+ }
+}
+
+#else
+
+void SamplingTool::dump(ExecState*)
+{
+}
+
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SamplingTool_h
+#define SamplingTool_h
+
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/Threading.h>
+
+#include "Nodes.h"
+#include "Opcode.h"
+
+namespace JSC {
+
+ class CodeBlock;
+ class ExecState;
+ class Interpreter;
+ class ScopeNode;
+ struct Instruction;
+
+ struct ScopeSampleRecord {
+ ScopeSampleRecord(ScopeNode* scope)
+ : m_scope(scope)
+ , m_codeBlock(0)
+ , m_sampleCount(0)
+ , m_opcodeSampleCount(0)
+ , m_samples(0)
+ , m_size(0)
+ {
+ }
+
+ ~ScopeSampleRecord()
+ {
+ if (m_samples)
+ free(m_samples);
+ }
+
+ void sample(CodeBlock*, Instruction*);
+
+ RefPtr<ScopeNode> m_scope;
+ CodeBlock* m_codeBlock;
+ int m_sampleCount;
+ int m_opcodeSampleCount;
+ int* m_samples;
+ unsigned m_size;
+ };
+
+ typedef WTF::HashMap<ScopeNode*, ScopeSampleRecord*> ScopeSampleRecordMap;
+
+ class SamplingTool {
+ public:
+ friend class CallRecord;
+ friend class HostCallRecord;
+
+#if ENABLE(OPCODE_SAMPLING)
+ class CallRecord : Noncopyable {
+ public:
+ CallRecord(SamplingTool* samplingTool)
+ : m_samplingTool(samplingTool)
+ , m_savedSample(samplingTool->m_sample)
+ , m_savedCodeBlock(samplingTool->m_codeBlock)
+ {
+ }
+
+ ~CallRecord()
+ {
+ m_samplingTool->m_sample = m_savedSample;
+ m_samplingTool->m_codeBlock = m_savedCodeBlock;
+ }
+
+ private:
+ SamplingTool* m_samplingTool;
+ intptr_t m_savedSample;
+ CodeBlock* m_savedCodeBlock;
+ };
+
+ class HostCallRecord : public CallRecord {
+ public:
+ HostCallRecord(SamplingTool* samplingTool)
+ : CallRecord(samplingTool)
+ {
+ samplingTool->m_sample |= 0x1;
+ }
+ };
+#else
+ class CallRecord : Noncopyable {
+ public:
+ CallRecord(SamplingTool*)
+ {
+ }
+ };
+
+ class HostCallRecord : public CallRecord {
+ public:
+ HostCallRecord(SamplingTool* samplingTool)
+ : CallRecord(samplingTool)
+ {
+ }
+ };
+#endif
+
+ SamplingTool(Interpreter* interpreter)
+ : m_interpreter(interpreter)
+ , m_running(false)
+ , m_codeBlock(0)
+ , m_sample(0)
+ , m_sampleCount(0)
+ , m_opcodeSampleCount(0)
+ , m_scopeSampleMap(new ScopeSampleRecordMap())
+ {
+ memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
+ memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
+ }
+
+ ~SamplingTool()
+ {
+ deleteAllValues(*m_scopeSampleMap);
+ }
+
+ void start(unsigned hertz=10000);
+ void stop();
+ void dump(ExecState*);
+
+ void notifyOfScope(ScopeNode* scope);
+
+ void sample(CodeBlock* codeBlock, Instruction* vPC)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(vPC) & 0x3));
+ m_codeBlock = codeBlock;
+ m_sample = reinterpret_cast<intptr_t>(vPC);
+ }
+
+ CodeBlock** codeBlockSlot() { return &m_codeBlock; }
+ intptr_t* sampleSlot() { return &m_sample; }
+
+ void* encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(vPC) & 0x3));
+ return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(vPC) | (static_cast<intptr_t>(inCTIFunction) << 1) | static_cast<intptr_t>(inHostFunction));
+ }
+
+ private:
+ class Sample {
+ public:
+ Sample(volatile intptr_t sample, CodeBlock* volatile codeBlock)
+ : m_sample(sample)
+ , m_codeBlock(codeBlock)
+ {
+ }
+
+ bool isNull() { return !m_sample || !m_codeBlock; }
+ CodeBlock* codeBlock() { return m_codeBlock; }
+ Instruction* vPC() { return reinterpret_cast<Instruction*>(m_sample & ~0x3); }
+ bool inHostFunction() { return m_sample & 0x1; }
+ bool inCTIFunction() { return m_sample & 0x2; }
+
+ private:
+ intptr_t m_sample;
+ CodeBlock* m_codeBlock;
+ };
+
+ static void* threadStartFunc(void*);
+ void run();
+
+ Interpreter* m_interpreter;
+
+ // Sampling thread state.
+ bool m_running;
+ unsigned m_hertz;
+ ThreadIdentifier m_samplingThread;
+
+ // State tracked by the main thread, used by the sampling thread.
+ CodeBlock* m_codeBlock;
+ intptr_t m_sample;
+
+ // Gathered sample data.
+ long long m_sampleCount;
+ long long m_opcodeSampleCount;
+ unsigned m_opcodeSamples[numOpcodeIDs];
+ unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs];
+
+ Mutex m_scopeSampleMapMutex;
+ OwnPtr<ScopeSampleRecordMap> m_scopeSampleMap;
+ };
+
+} // namespace JSC
+
+#endif // SamplingTool_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureStubInfo.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+void StructureStubInfo::deref()
+{
+ switch (opcodeID) {
+ case op_get_by_id_self:
+ u.getByIdSelf.baseObjectStructure->deref();
+ return;
+ case op_get_by_id_proto:
+ u.getByIdProto.baseObjectStructure->deref();
+ u.getByIdProto.prototypeStructure->deref();
+ return;
+ case op_get_by_id_chain:
+ u.getByIdChain.baseObjectStructure->deref();
+ u.getByIdChain.chain->deref();
+ return;
+ case op_get_by_id_self_list: {
+ PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
+ polymorphicStructures->derefStructures(u.getByIdSelfList.listSize);
+ delete polymorphicStructures;
+ return;
+ }
+ case op_get_by_id_proto_list: {
+ PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
+ polymorphicStructures->derefStructures(u.getByIdProtoList.listSize);
+ delete polymorphicStructures;
+ return;
+ }
+ case op_put_by_id_transition:
+ u.putByIdTransition.previousStructure->deref();
+ u.putByIdTransition.structure->deref();
+ u.putByIdTransition.chain->deref();
+ return;
+ case op_put_by_id_replace:
+ u.putByIdReplace.baseObjectStructure->deref();
+ return;
+ case op_get_by_id:
+ case op_put_by_id:
+ case op_get_by_id_generic:
+ case op_put_by_id_generic:
+ case op_get_array_length:
+ case op_get_string_length:
+ // These instructions don't ref their Structures.
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureStubInfo_h
+#define StructureStubInfo_h
+
+#include "Instruction.h"
+#include "Opcode.h"
+#include "Structure.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+ struct StructureStubInfo {
+ StructureStubInfo(OpcodeID opcodeID)
+ : opcodeID(opcodeID)
+ , stubRoutine(0)
+ , callReturnLocation(0)
+ , hotPathBegin(0)
+ {
+ }
+
+ void initGetByIdSelf(Structure* baseObjectStructure)
+ {
+ opcodeID = op_get_by_id_self;
+
+ u.getByIdSelf.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+ }
+
+ void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
+ {
+ opcodeID = op_get_by_id_proto;
+
+ u.getByIdProto.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+
+ u.getByIdProto.prototypeStructure = prototypeStructure;
+ prototypeStructure->ref();
+ }
+
+ void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
+ {
+ opcodeID = op_get_by_id_chain;
+
+ u.getByIdChain.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+
+ u.getByIdChain.chain = chain;
+ chain->ref();
+ }
+
+ void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
+ {
+ opcodeID = op_get_by_id_self_list;
+
+ u.getByIdProtoList.structureList = structureList;
+ u.getByIdProtoList.listSize = listSize;
+ }
+
+ void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
+ {
+ opcodeID = op_get_by_id_proto_list;
+
+ u.getByIdProtoList.structureList = structureList;
+ u.getByIdProtoList.listSize = listSize;
+ }
+
+ // PutById*
+
+ void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
+ {
+ opcodeID = op_put_by_id_transition;
+
+ u.putByIdTransition.previousStructure = previousStructure;
+ previousStructure->ref();
+
+ u.putByIdTransition.structure = structure;
+ structure->ref();
+
+ u.putByIdTransition.chain = chain;
+ chain->ref();
+ }
+
+ void initPutByIdReplace(Structure* baseObjectStructure)
+ {
+ opcodeID = op_put_by_id_replace;
+
+ u.putByIdReplace.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+ }
+
+ void deref();
+
+ OpcodeID opcodeID;
+ union {
+ struct {
+ Structure* baseObjectStructure;
+ } getByIdSelf;
+ struct {
+ Structure* baseObjectStructure;
+ Structure* prototypeStructure;
+ } getByIdProto;
+ struct {
+ Structure* baseObjectStructure;
+ StructureChain* chain;
+ } getByIdChain;
+ struct {
+ PolymorphicAccessStructureList* structureList;
+ int listSize;
+ } getByIdSelfList;
+ struct {
+ PolymorphicAccessStructureList* structureList;
+ int listSize;
+ } getByIdProtoList;
+ struct {
+ Structure* previousStructure;
+ Structure* structure;
+ StructureChain* chain;
+ } putByIdTransition;
+ struct {
+ Structure* baseObjectStructure;
+ } putByIdReplace;
+ } u;
+
+ void* stubRoutine;
+ void* callReturnLocation;
+ void* hotPathBegin;
+ };
+#endif
+
+} // namespace JSC
+
+#endif // StructureStubInfo_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BytecodeGenerator.h"
+
+#include "BatchedTransitionOptimizer.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "UString.h"
+
+using namespace std;
+
+namespace JSC {
+
+/*
+ The layout of a register frame looks like this:
+
+ For
+
+ function f(x, y) {
+ var v1;
+ function g() { }
+ var v2;
+ return (x) * (y);
+ }
+
+ assuming (x) and (y) generated temporaries t1 and t2, you would have
+
+ ------------------------------------
+ | x | y | g | v2 | v1 | t1 | t2 | <-- value held
+ ------------------------------------
+ | -5 | -4 | -3 | -2 | -1 | +0 | +1 | <-- register index
+ ------------------------------------
+ | params->|<-locals | temps->
+
+ Because temporary registers are allocated in a stack-like fashion, we
+ can reclaim them with a simple popping algorithm. The same goes for labels.
+ (We never reclaim parameter or local registers, because parameters and
+ locals are DontDelete.)
+
+ The register layout before a function call looks like this:
+
+ For
+
+ function f(x, y)
+ {
+ }
+
+ f(1);
+
+ > <------------------------------
+ < > reserved: call frame | 1 | <-- value held
+ > >snip< <------------------------------
+ < > +0 | +1 | +2 | +3 | +4 | +5 | <-- register index
+ > <------------------------------
+ | params->|<-locals | temps->
+
+ The call instruction fills in the "call frame" registers. It also pads
+ missing arguments at the end of the call:
+
+ > <-----------------------------------
+ < > reserved: call frame | 1 | ? | <-- value held ("?" stands for "undefined")
+ > >snip< <-----------------------------------
+ < > +0 | +1 | +2 | +3 | +4 | +5 | +6 | <-- register index
+ > <-----------------------------------
+ | params->|<-locals | temps->
+
+ After filling in missing arguments, the call instruction sets up the new
+ stack frame to overlap the end of the old stack frame:
+
+ |----------------------------------> <
+ | reserved: call frame | 1 | ? < > <-- value held ("?" stands for "undefined")
+ |----------------------------------> >snip< <
+ | -7 | -6 | -5 | -4 | -3 | -2 | -1 < > <-- register index
+ |----------------------------------> <
+ | | params->|<-locals | temps->
+
+ That way, arguments are "copied" into the callee's stack frame for free.
+
+ If the caller supplies too many arguments, this trick doesn't work. The
+ extra arguments protrude into space reserved for locals and temporaries.
+ In that case, the call instruction makes a real copy of the call frame header,
+ along with just the arguments expected by the callee, leaving the original
+ call frame header and arguments behind. (The call instruction can't just discard
+ extra arguments, because the "arguments" object may access them later.)
+ This copying strategy ensures that all named values will be at the indices
+ expected by the callee.
+*/
+
+#ifndef NDEBUG
+static bool s_dumpsGeneratedCode = false;
+#endif
+
+void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
+{
+#ifndef NDEBUG
+ s_dumpsGeneratedCode = dumpsGeneratedCode;
+#else
+ UNUSED_PARAM(dumpsGeneratedCode);
+#endif
+}
+
+bool BytecodeGenerator::dumpsGeneratedCode()
+{
+#ifndef NDEBUG
+ return s_dumpsGeneratedCode;
+#else
+ return false;
+#endif
+}
+
+void BytecodeGenerator::generate()
+{
+ m_codeBlock->setThisRegister(m_thisRegister.index());
+
+ m_scopeNode->emitBytecode(*this);
+
+#ifndef NDEBUG
+ m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
+
+ if (s_dumpsGeneratedCode)
+ m_codeBlock->dump(m_scopeChain->globalObject()->globalExec());
+#endif
+
+ if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
+ symbolTable().clear();
+
+ m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec()));
+
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!m_regeneratingForExceptionInfo && (m_codeType == FunctionCode || m_codeType == EvalCode))
+ m_codeBlock->clearExceptionInfo();
+#endif
+
+ m_codeBlock->shrinkToFit();
+}
+
+bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
+{
+ int index = m_calleeRegisters.size();
+ SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
+ pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
+
+ if (!result.second) {
+ r0 = ®isterFor(result.first->second.getIndex());
+ return false;
+ }
+
+ ++m_codeBlock->m_numVars;
+ r0 = newRegister();
+ return true;
+}
+
+bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
+{
+ int index = m_nextGlobalIndex;
+ SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
+ pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
+
+ if (!result.second)
+ index = result.first->second.getIndex();
+ else {
+ --m_nextGlobalIndex;
+ m_globals.append(index + m_globalVarStorageOffset);
+ }
+
+ r0 = ®isterFor(index);
+ return result.second;
+}
+
+void BytecodeGenerator::allocateConstants(size_t count)
+{
+ m_codeBlock->m_numConstants = count;
+ if (!count)
+ return;
+
+ m_nextConstantIndex = m_calleeRegisters.size();
+
+ for (size_t i = 0; i < count; ++i)
+ newRegister();
+ m_lastConstant = &m_calleeRegisters.last();
+}
+
+BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
+ : m_shouldEmitDebugHooks(!!debugger)
+ , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
+ , m_scopeChain(&scopeChain)
+ , m_symbolTable(symbolTable)
+ , m_scopeNode(programNode)
+ , m_codeBlock(codeBlock)
+ , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
+ , m_finallyDepth(0)
+ , m_dynamicScopeDepth(0)
+ , m_baseScopeDepth(0)
+ , m_codeType(GlobalCode)
+ , m_nextGlobalIndex(-1)
+ , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+ , m_lastOpcodeID(op_end)
+ , m_emitNodeDepth(0)
+ , m_regeneratingForExceptionInfo(false)
+ , m_codeBlockBeingRegeneratedFrom(0)
+{
+ if (m_shouldEmitDebugHooks)
+ m_codeBlock->setNeedsFullScopeChain(true);
+
+ emitOpcode(op_enter);
+ codeBlock->setGlobalData(m_globalData);
+
+ // FIXME: Move code that modifies the global object to Interpreter::execute.
+
+ m_codeBlock->m_numParameters = 1; // Allocate space for "this"
+
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+ ExecState* exec = globalObject->globalExec();
+ RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
+
+ // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
+ m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size();
+
+ // Add previously defined symbols to bookkeeping.
+ m_globals.grow(symbolTable->size());
+ SymbolTable::iterator end = symbolTable->end();
+ for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
+ registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
+
+ BatchedTransitionOptimizer optimizer(globalObject);
+
+ const VarStack& varStack = programNode->varStack();
+ const FunctionStack& functionStack = programNode->functionStack();
+ bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
+ if (canOptimizeNewGlobals) {
+ // Shift new symbols so they get stored prior to existing symbols.
+ m_nextGlobalIndex -= symbolTable->size();
+
+ for (size_t i = 0; i < functionStack.size(); ++i) {
+ FuncDeclNode* funcDecl = functionStack[i].get();
+ globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
+ emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
+ }
+
+ Vector<RegisterID*, 32> newVars;
+ for (size_t i = 0; i < varStack.size(); ++i)
+ if (!globalObject->hasProperty(exec, varStack[i].first))
+ newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
+
+ allocateConstants(programNode->neededConstants());
+
+ for (size_t i = 0; i < newVars.size(); ++i)
+ emitLoad(newVars[i], jsUndefined());
+ } else {
+ for (size_t i = 0; i < functionStack.size(); ++i) {
+ FuncDeclNode* funcDecl = functionStack[i].get();
+ globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
+ }
+ for (size_t i = 0; i < varStack.size(); ++i) {
+ if (globalObject->hasProperty(exec, varStack[i].first))
+ continue;
+ int attributes = DontDelete;
+ if (varStack[i].second & DeclarationStacks::IsConstant)
+ attributes |= ReadOnly;
+ globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
+ }
+
+ allocateConstants(programNode->neededConstants());
+ }
+}
+
+BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
+ : m_shouldEmitDebugHooks(!!debugger)
+ , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
+ , m_scopeChain(&scopeChain)
+ , m_symbolTable(symbolTable)
+ , m_scopeNode(functionBody)
+ , m_codeBlock(codeBlock)
+ , m_finallyDepth(0)
+ , m_dynamicScopeDepth(0)
+ , m_baseScopeDepth(0)
+ , m_codeType(FunctionCode)
+ , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+ , m_lastOpcodeID(op_end)
+ , m_emitNodeDepth(0)
+ , m_regeneratingForExceptionInfo(false)
+ , m_codeBlockBeingRegeneratedFrom(0)
+{
+ if (m_shouldEmitDebugHooks)
+ m_codeBlock->setNeedsFullScopeChain(true);
+
+ codeBlock->setGlobalData(m_globalData);
+
+ bool usesArguments = functionBody->usesArguments();
+ codeBlock->setUsesArguments(usesArguments);
+ if (usesArguments) {
+ m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments);
+ addVar(propertyNames().arguments, false);
+ }
+
+ if (m_codeBlock->needsFullScopeChain()) {
+ ++m_codeBlock->m_numVars;
+ m_activationRegisterIndex = newRegister()->index();
+ emitOpcode(op_enter_with_activation);
+ instructions().append(m_activationRegisterIndex);
+ } else
+ emitOpcode(op_enter);
+
+ if (usesArguments)
+ emitOpcode(op_create_arguments);
+
+ const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
+ for (size_t i = 0; i < functionStack.size(); ++i) {
+ FuncDeclNode* funcDecl = functionStack[i].get();
+ const Identifier& ident = funcDecl->m_ident;
+ m_functions.add(ident.ustring().rep());
+ emitNewFunction(addVar(ident, false), funcDecl);
+ }
+
+ const DeclarationStacks::VarStack& varStack = functionBody->varStack();
+ for (size_t i = 0; i < varStack.size(); ++i)
+ addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+
+ const Identifier* parameters = functionBody->parameters();
+ size_t parameterCount = functionBody->parameterCount();
+ m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
+ m_parameters.grow(1 + parameterCount); // reserve space for "this"
+
+ // Add "this" as a parameter
+ m_thisRegister.setIndex(m_nextParameterIndex);
+ ++m_nextParameterIndex;
+ ++m_codeBlock->m_numParameters;
+
+ if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
+ emitOpcode(op_convert_this);
+ instructions().append(m_thisRegister.index());
+ }
+
+ for (size_t i = 0; i < parameterCount; ++i)
+ addParameter(parameters[i]);
+
+ allocateConstants(functionBody->neededConstants());
+}
+
+BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
+ : m_shouldEmitDebugHooks(!!debugger)
+ , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
+ , m_scopeChain(&scopeChain)
+ , m_symbolTable(symbolTable)
+ , m_scopeNode(evalNode)
+ , m_codeBlock(codeBlock)
+ , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
+ , m_finallyDepth(0)
+ , m_dynamicScopeDepth(0)
+ , m_baseScopeDepth(codeBlock->baseScopeDepth())
+ , m_codeType(EvalCode)
+ , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+ , m_lastOpcodeID(op_end)
+ , m_emitNodeDepth(0)
+ , m_regeneratingForExceptionInfo(false)
+ , m_codeBlockBeingRegeneratedFrom(0)
+{
+ if (m_shouldEmitDebugHooks || m_baseScopeDepth)
+ m_codeBlock->setNeedsFullScopeChain(true);
+
+ emitOpcode(op_enter);
+ codeBlock->setGlobalData(m_globalData);
+ m_codeBlock->m_numParameters = 1; // Allocate space for "this"
+
+ allocateConstants(evalNode->neededConstants());
+}
+
+RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
+{
+ // Parameters overwrite var declarations, but not function declarations.
+ RegisterID* result = 0;
+ UString::Rep* rep = ident.ustring().rep();
+ if (!m_functions.contains(rep)) {
+ symbolTable().set(rep, m_nextParameterIndex);
+ RegisterID& parameter = registerFor(m_nextParameterIndex);
+ parameter.setIndex(m_nextParameterIndex);
+ result = ¶meter;
+ }
+
+ // To maintain the calling convention, we have to allocate unique space for
+ // each parameter, even if the parameter doesn't make it into the symbol table.
+ ++m_nextParameterIndex;
+ ++m_codeBlock->m_numParameters;
+ return result;
+}
+
+RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
+{
+ if (ident == propertyNames().thisIdentifier)
+ return &m_thisRegister;
+
+ if (!shouldOptimizeLocals())
+ return 0;
+
+ SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+ if (entry.isNull())
+ return 0;
+
+ return ®isterFor(entry.getIndex());
+}
+
+RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
+{
+ if (m_codeType == EvalCode)
+ return 0;
+
+ SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+ ASSERT(!entry.isNull());
+
+ return ®isterFor(entry.getIndex());
+}
+
+bool BytecodeGenerator::isLocal(const Identifier& ident)
+{
+ if (ident == propertyNames().thisIdentifier)
+ return true;
+
+ return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
+}
+
+bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
+{
+ return symbolTable().get(ident.ustring().rep()).isReadOnly();
+}
+
+RegisterID* BytecodeGenerator::newRegister()
+{
+ m_calleeRegisters.append(m_calleeRegisters.size());
+ m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
+ return &m_calleeRegisters.last();
+}
+
+RegisterID* BytecodeGenerator::newTemporary()
+{
+ // Reclaim free register IDs.
+ while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
+ m_calleeRegisters.removeLast();
+
+ RegisterID* result = newRegister();
+ result->setTemporary();
+ return result;
+}
+
+RegisterID* BytecodeGenerator::highestUsedRegister()
+{
+ size_t count = m_codeBlock->m_numCalleeRegisters;
+ while (m_calleeRegisters.size() < count)
+ newRegister();
+ return &m_calleeRegisters.last();
+}
+
+PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
+{
+ // Reclaim free label scopes.
+ while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+ m_labelScopes.removeLast();
+
+ // Allocate new label scope.
+ LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets.
+ m_labelScopes.append(scope);
+ return &m_labelScopes.last();
+}
+
+PassRefPtr<Label> BytecodeGenerator::newLabel()
+{
+ // Reclaim free label IDs.
+ while (m_labels.size() && !m_labels.last().refCount())
+ m_labels.removeLast();
+
+ // Allocate new label ID.
+ m_labels.append(m_codeBlock);
+ return &m_labels.last();
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
+{
+ unsigned newLabelIndex = instructions().size();
+ l0->setLocation(newLabelIndex);
+
+ if (m_codeBlock->numberOfJumpTargets()) {
+ unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
+ ASSERT(lastLabelIndex <= newLabelIndex);
+ if (newLabelIndex == lastLabelIndex) {
+ // Peephole optimizations have already been disabled by emitting the last label
+ return l0;
+ }
+ }
+
+ m_codeBlock->addJumpTarget(newLabelIndex);
+
+ // This disables peephole optimizations when an instruction is a jump target
+ m_lastOpcodeID = op_end;
+ return l0;
+}
+
+void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
+{
+ instructions().append(globalData()->interpreter->getOpcode(opcodeID));
+ m_lastOpcodeID = opcodeID;
+}
+
+void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
+{
+ ASSERT(instructions().size() >= 4);
+ size_t size = instructions().size();
+ dstIndex = instructions().at(size - 3).u.operand;
+ src1Index = instructions().at(size - 2).u.operand;
+ src2Index = instructions().at(size - 1).u.operand;
+}
+
+void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
+{
+ ASSERT(instructions().size() >= 3);
+ size_t size = instructions().size();
+ dstIndex = instructions().at(size - 2).u.operand;
+ srcIndex = instructions().at(size - 1).u.operand;
+}
+
+void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
+{
+ ASSERT(instructions().size() >= 4);
+ instructions().shrink(instructions().size() - 4);
+}
+
+void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
+{
+ ASSERT(instructions().size() >= 3);
+ instructions().shrink(instructions().size() - 3);
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
+{
+ emitOpcode(target->isForward() ? op_jmp : op_loop);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
+{
+ if (m_lastOpcodeID == op_less && !target->isForward()) {
+ int dstIndex;
+ int src1Index;
+ int src2Index;
+
+ retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindBinaryOp();
+ emitOpcode(op_loop_if_less);
+ instructions().append(src1Index);
+ instructions().append(src2Index);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
+ int dstIndex;
+ int src1Index;
+ int src2Index;
+
+ retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindBinaryOp();
+ emitOpcode(op_loop_if_lesseq);
+ instructions().append(src1Index);
+ instructions().append(src2Index);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindUnaryOp();
+ emitOpcode(op_jeq_null);
+ instructions().append(srcIndex);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindUnaryOp();
+ emitOpcode(op_jneq_null);
+ instructions().append(srcIndex);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ }
+
+ emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
+ instructions().append(cond->index());
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
+{
+ ASSERT(target->isForward());
+
+ if (m_lastOpcodeID == op_less) {
+ int dstIndex;
+ int src1Index;
+ int src2Index;
+
+ retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindBinaryOp();
+ emitOpcode(op_jnless);
+ instructions().append(src1Index);
+ instructions().append(src2Index);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_not) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindUnaryOp();
+ emitOpcode(op_jtrue);
+ instructions().append(srcIndex);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_eq_null) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindUnaryOp();
+ emitOpcode(op_jneq_null);
+ instructions().append(srcIndex);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ } else if (m_lastOpcodeID == op_neq_null) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindUnaryOp();
+ emitOpcode(op_jeq_null);
+ instructions().append(srcIndex);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+ }
+
+ emitOpcode(op_jfalse);
+ instructions().append(cond->index());
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+}
+
+unsigned BytecodeGenerator::addConstant(FuncDeclNode* n)
+{
+ // No need to explicitly unique function body nodes -- they're unique already.
+ return m_codeBlock->addFunction(n);
+}
+
+unsigned BytecodeGenerator::addConstant(FuncExprNode* n)
+{
+ // No need to explicitly unique function expression nodes -- they're unique already.
+ return m_codeBlock->addFunctionExpression(n);
+}
+
+unsigned BytecodeGenerator::addConstant(const Identifier& ident)
+{
+ UString::Rep* rep = ident.ustring().rep();
+ pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
+ if (result.second) // new entry
+ m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
+
+ return result.first->second;
+}
+
+RegisterID* BytecodeGenerator::addConstant(JSValuePtr v)
+{
+ pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValuePtr::encode(v), m_nextConstantIndex);
+ if (result.second) {
+ RegisterID& constant = m_calleeRegisters[m_nextConstantIndex];
+
+ ++m_nextConstantIndex;
+
+ m_codeBlock->addConstantRegister(JSValuePtr(v));
+ return &constant;
+ }
+
+ return ®isterFor(result.first->second);
+}
+
+unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v)
+{
+ return m_codeBlock->addUnexpectedConstant(v);
+}
+
+unsigned BytecodeGenerator::addRegExp(RegExp* r)
+{
+ return m_codeBlock->addRegExp(r);
+}
+
+RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
+{
+ emitOpcode(op_mov);
+ instructions().append(dst->index());
+ instructions().append(src->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
+{
+ emitOpcode(opcodeID);
+ instructions().append(dst->index());
+ instructions().append(src->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst)
+{
+ emitOpcode(op_pre_inc);
+ instructions().append(srcDst->index());
+ return srcDst;
+}
+
+RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst)
+{
+ emitOpcode(op_pre_dec);
+ instructions().append(srcDst->index());
+ return srcDst;
+}
+
+RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
+{
+ emitOpcode(op_post_inc);
+ instructions().append(dst->index());
+ instructions().append(srcDst->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
+{
+ emitOpcode(op_post_dec);
+ instructions().append(dst->index());
+ instructions().append(srcDst->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
+{
+ emitOpcode(opcodeID);
+ instructions().append(dst->index());
+ instructions().append(src1->index());
+ instructions().append(src2->index());
+
+ if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
+ opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) {
+ instructions().append(types.toInt());
+ }
+
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
+{
+ if (m_lastOpcodeID == op_typeof) {
+ int dstIndex;
+ int srcIndex;
+
+ retrieveLastUnaryOp(dstIndex, srcIndex);
+
+ if (src1->index() == dstIndex
+ && src1->isTemporary()
+ && m_codeBlock->isConstantRegisterIndex(src2->index())
+ && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()).isString()) {
+ const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()))->value();
+ if (value == "undefined") {
+ rewindUnaryOp();
+ emitOpcode(op_is_undefined);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ if (value == "boolean") {
+ rewindUnaryOp();
+ emitOpcode(op_is_boolean);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ if (value == "number") {
+ rewindUnaryOp();
+ emitOpcode(op_is_number);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ if (value == "string") {
+ rewindUnaryOp();
+ emitOpcode(op_is_string);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ if (value == "object") {
+ rewindUnaryOp();
+ emitOpcode(op_is_object);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ if (value == "function") {
+ rewindUnaryOp();
+ emitOpcode(op_is_function);
+ instructions().append(dst->index());
+ instructions().append(srcIndex);
+ return dst;
+ }
+ }
+ }
+
+ emitOpcode(opcodeID);
+ instructions().append(dst->index());
+ instructions().append(src1->index());
+ instructions().append(src2->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
+{
+ return emitLoad(dst, jsBoolean(b));
+}
+
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
+{
+ // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time.
+ // Later we can do the extra work to handle that like the other cases.
+ if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
+ return emitLoad(dst, jsNumber(globalData(), number));
+ JSValuePtr& valueInMap = m_numberMap.add(number, noValue()).first->second;
+ if (!valueInMap)
+ valueInMap = jsNumber(globalData(), number);
+ return emitLoad(dst, valueInMap);
+}
+
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
+{
+ JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
+ if (!stringInMap)
+ stringInMap = jsOwnedString(globalData(), identifier.ustring());
+ return emitLoad(dst, JSValuePtr(stringInMap));
+}
+
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v)
+{
+ RegisterID* constantID = addConstant(v);
+ if (dst)
+ return emitMove(dst, constantID);
+ return constantID;
+}
+
+RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
+{
+ emitOpcode(op_unexpected_load);
+ instructions().append(dst->index());
+ instructions().append(addUnexpectedConstant(jsBoolean(b)));
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
+{
+ emitOpcode(op_unexpected_load);
+ instructions().append(dst->index());
+ instructions().append(addUnexpectedConstant(jsNumber(globalData(), d)));
+ return dst;
+}
+
+bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
+{
+ // Cases where we cannot statically optimize the lookup.
+ if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
+ stackDepth = 0;
+ index = missingSymbolMarker();
+
+ if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
+ ScopeChainIterator iter = m_scopeChain->begin();
+ globalObject = *iter;
+ ASSERT((++iter) == m_scopeChain->end());
+ }
+ return false;
+ }
+
+ size_t depth = 0;
+
+ ScopeChainIterator iter = m_scopeChain->begin();
+ ScopeChainIterator end = m_scopeChain->end();
+ for (; iter != end; ++iter, ++depth) {
+ JSObject* currentScope = *iter;
+ if (!currentScope->isVariableObject())
+ break;
+ JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
+ SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
+
+ // Found the property
+ if (!entry.isNull()) {
+ if (entry.isReadOnly() && forWriting) {
+ stackDepth = 0;
+ index = missingSymbolMarker();
+ if (++iter == end)
+ globalObject = currentVariableObject;
+ return false;
+ }
+ stackDepth = depth;
+ index = entry.getIndex();
+ if (++iter == end)
+ globalObject = currentVariableObject;
+ return true;
+ }
+ if (currentVariableObject->isDynamicScope())
+ break;
+ }
+
+ // Can't locate the property but we're able to avoid a few lookups.
+ stackDepth = depth;
+ index = missingSymbolMarker();
+ JSObject* scope = *iter;
+ if (++iter == end)
+ globalObject = scope;
+ return true;
+}
+
+RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
+{
+ emitOpcode(op_instanceof);
+ instructions().append(dst->index());
+ instructions().append(value->index());
+ instructions().append(base->index());
+ instructions().append(basePrototype->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
+{
+ size_t depth = 0;
+ int index = 0;
+ JSObject* globalObject = 0;
+ if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) {
+ // We can't optimise at all :-(
+ emitOpcode(op_resolve);
+ instructions().append(dst->index());
+ instructions().append(addConstant(property));
+ return dst;
+ }
+
+ if (globalObject) {
+ bool forceGlobalResolve = false;
+ if (m_regeneratingForExceptionInfo) {
+#if ENABLE(JIT)
+ forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
+#else
+ forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
+#endif
+ }
+
+ if (index != missingSymbolMarker() && !forceGlobalResolve) {
+ // Directly index the property lookup across multiple scopes.
+ return emitGetScopedVar(dst, depth, index, globalObject);
+ }
+
+#if ENABLE(JIT)
+ m_codeBlock->addGlobalResolveInfo(instructions().size());
+#else
+ m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
+ emitOpcode(op_resolve_global);
+ instructions().append(dst->index());
+ instructions().append(globalObject);
+ instructions().append(addConstant(property));
+ instructions().append(0);
+ instructions().append(0);
+ return dst;
+ }
+
+ if (index != missingSymbolMarker()) {
+ // Directly index the property lookup across multiple scopes.
+ return emitGetScopedVar(dst, depth, index, globalObject);
+ }
+
+ // In this case we are at least able to drop a few scope chains from the
+ // lookup chain, although we still need to hash from then on.
+ emitOpcode(op_resolve_skip);
+ instructions().append(dst->index());
+ instructions().append(addConstant(property));
+ instructions().append(depth);
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject)
+{
+ if (globalObject) {
+ emitOpcode(op_get_global_var);
+ instructions().append(dst->index());
+ instructions().append(asCell(globalObject));
+ instructions().append(index);
+ return dst;
+ }
+
+ emitOpcode(op_get_scoped_var);
+ instructions().append(dst->index());
+ instructions().append(index);
+ instructions().append(depth);
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject)
+{
+ if (globalObject) {
+ emitOpcode(op_put_global_var);
+ instructions().append(asCell(globalObject));
+ instructions().append(index);
+ instructions().append(value->index());
+ return value;
+ }
+ emitOpcode(op_put_scoped_var);
+ instructions().append(index);
+ instructions().append(depth);
+ instructions().append(value->index());
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
+{
+ emitOpcode(op_resolve_base);
+ instructions().append(dst->index());
+ instructions().append(addConstant(property));
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
+{
+ emitOpcode(op_resolve_with_base);
+ instructions().append(baseDst->index());
+ instructions().append(propDst->index());
+ instructions().append(addConstant(property));
+ return baseDst;
+}
+
+RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
+{
+ emitOpcode(op_resolve_func);
+ instructions().append(baseDst->index());
+ instructions().append(funcDst->index());
+ instructions().append(addConstant(property));
+ return baseDst;
+}
+
+RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
+{
+#if ENABLE(JIT)
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id));
+#else
+ m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
+
+ emitOpcode(op_get_by_id);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
+{
+#if ENABLE(JIT)
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id));
+#else
+ m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
+
+ emitOpcode(op_put_by_id);
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ instructions().append(value->index());
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
+{
+ emitOpcode(op_put_getter);
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ instructions().append(value->index());
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
+{
+ emitOpcode(op_put_setter);
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ instructions().append(value->index());
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
+{
+ emitOpcode(op_del_by_id);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
+{
+ emitOpcode(op_get_by_val);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(property->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
+{
+ emitOpcode(op_put_by_val);
+ instructions().append(base->index());
+ instructions().append(property->index());
+ instructions().append(value->index());
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
+{
+ emitOpcode(op_del_by_val);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(property->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
+{
+ emitOpcode(op_put_by_index);
+ instructions().append(base->index());
+ instructions().append(index);
+ instructions().append(value->index());
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
+{
+ emitOpcode(op_new_object);
+ instructions().append(dst->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
+{
+ Vector<RefPtr<RegisterID>, 16> argv;
+ for (ElementNode* n = elements; n; n = n->next()) {
+ if (n->elision())
+ break;
+ argv.append(newTemporary());
+ // op_new_array requires the initial values to be a sequential range of registers
+ ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
+ emitNode(argv.last().get(), n->value());
+ }
+ emitOpcode(op_new_array);
+ instructions().append(dst->index());
+ instructions().append(argv.size() ? argv[0]->index() : 0); // argv
+ instructions().append(argv.size()); // argc
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
+{
+ emitOpcode(op_new_func);
+ instructions().append(dst->index());
+ instructions().append(addConstant(n));
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
+{
+ emitOpcode(op_new_regexp);
+ instructions().append(dst->index());
+ instructions().append(addRegExp(regExp));
+ return dst;
+}
+
+
+RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
+{
+ emitOpcode(op_new_func_exp);
+ instructions().append(r0->index());
+ instructions().append(addConstant(n));
+ return r0;
+}
+
+RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+ return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
+}
+
+RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+ return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
+}
+
+RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+ ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
+ ASSERT(func->refCount());
+ ASSERT(thisRegister->refCount());
+
+ RegisterID* originalFunc = func;
+ if (m_shouldEmitProfileHooks) {
+ // If codegen decided to recycle func as this call's destination register,
+ // we need to undo that optimization here so that func will still be around
+ // for the sake of op_profile_did_call.
+ if (dst == func) {
+ RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister);
+ RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func);
+
+ thisRegister = movedThisRegister.release().releaseRef();
+ func = movedFunc.release().releaseRef();
+ }
+ }
+
+ // Generate code for arguments.
+ Vector<RefPtr<RegisterID>, 16> argv;
+ argv.append(thisRegister);
+ for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
+ argv.append(newTemporary());
+ // op_call requires the arguments to be a sequential range of registers
+ ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
+ emitNode(argv.last().get(), n);
+ }
+
+ // Reserve space for call frame.
+ Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
+ for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
+ callFrame.append(newTemporary());
+
+ if (m_shouldEmitProfileHooks) {
+ emitOpcode(op_profile_will_call);
+ instructions().append(func->index());
+
+#if ENABLE(JIT)
+ m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
+#endif
+ }
+
+ emitExpressionInfo(divot, startOffset, endOffset);
+
+#if ENABLE(JIT)
+ m_codeBlock->addCallLinkInfo();
+#endif
+
+ // Emit call.
+ emitOpcode(opcodeID);
+ instructions().append(dst->index()); // dst
+ instructions().append(func->index()); // func
+ instructions().append(argv.size()); // argCount
+ instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
+
+ if (m_shouldEmitProfileHooks) {
+ emitOpcode(op_profile_did_call);
+ instructions().append(func->index());
+
+ if (dst == originalFunc) {
+ thisRegister->deref();
+ func->deref();
+ }
+ }
+
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
+{
+ if (m_codeBlock->needsFullScopeChain()) {
+ emitOpcode(op_tear_off_activation);
+ instructions().append(m_activationRegisterIndex);
+ } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1)
+ emitOpcode(op_tear_off_arguments);
+
+ return emitUnaryNoDstOp(op_ret, src);
+}
+
+RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
+{
+ emitOpcode(opcodeID);
+ instructions().append(src->index());
+ return src;
+}
+
+RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+ ASSERT(func->refCount());
+
+ RegisterID* originalFunc = func;
+ if (m_shouldEmitProfileHooks) {
+ // If codegen decided to recycle func as this call's destination register,
+ // we need to undo that optimization here so that func will still be around
+ // for the sake of op_profile_did_call.
+ if (dst == func) {
+ RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func);
+ func = movedFunc.release().releaseRef();
+ }
+ }
+
+ RefPtr<RegisterID> funcProto = newTemporary();
+
+ // Generate code for arguments.
+ Vector<RefPtr<RegisterID>, 16> argv;
+ argv.append(newTemporary()); // reserve space for "this"
+ for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) {
+ argv.append(newTemporary());
+ // op_construct requires the arguments to be a sequential range of registers
+ ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
+ emitNode(argv.last().get(), n);
+ }
+
+ if (m_shouldEmitProfileHooks) {
+ emitOpcode(op_profile_will_call);
+ instructions().append(func->index());
+ }
+
+ // Load prototype.
+ emitExpressionInfo(divot, startOffset, endOffset);
+ emitGetByIdExceptionInfo(op_construct);
+ emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype);
+
+ // Reserve space for call frame.
+ Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
+ for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
+ callFrame.append(newTemporary());
+
+ emitExpressionInfo(divot, startOffset, endOffset);
+
+#if ENABLE(JIT)
+ m_codeBlock->addCallLinkInfo();
+#endif
+
+ emitOpcode(op_construct);
+ instructions().append(dst->index()); // dst
+ instructions().append(func->index()); // func
+ instructions().append(argv.size()); // argCount
+ instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
+ instructions().append(funcProto->index()); // proto
+ instructions().append(argv[0]->index()); // thisRegister
+
+ emitOpcode(op_construct_verify);
+ instructions().append(dst->index());
+ instructions().append(argv[0]->index());
+
+ if (m_shouldEmitProfileHooks) {
+ emitOpcode(op_profile_did_call);
+ instructions().append(func->index());
+
+ if (dst == originalFunc)
+ func->deref();
+ }
+
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
+{
+ ASSERT(scope->isTemporary());
+ ControlFlowContext context;
+ context.isFinallyBlock = false;
+ m_scopeContextStack.append(context);
+ m_dynamicScopeDepth++;
+
+ return emitUnaryNoDstOp(op_push_scope, scope);
+}
+
+void BytecodeGenerator::emitPopScope()
+{
+ ASSERT(m_scopeContextStack.size());
+ ASSERT(!m_scopeContextStack.last().isFinallyBlock);
+
+ emitOpcode(op_pop_scope);
+
+ m_scopeContextStack.removeLast();
+ m_dynamicScopeDepth--;
+}
+
+void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
+{
+ if (!m_shouldEmitDebugHooks)
+ return;
+ emitOpcode(op_debug);
+ instructions().append(debugHookID);
+ instructions().append(firstLine);
+ instructions().append(lastLine);
+}
+
+void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
+{
+ ControlFlowContext scope;
+ scope.isFinallyBlock = true;
+ FinallyContext context = { target, retAddrDst };
+ scope.finallyContext = context;
+ m_scopeContextStack.append(scope);
+ m_finallyDepth++;
+}
+
+void BytecodeGenerator::popFinallyContext()
+{
+ ASSERT(m_scopeContextStack.size());
+ ASSERT(m_scopeContextStack.last().isFinallyBlock);
+ ASSERT(m_finallyDepth > 0);
+ m_scopeContextStack.removeLast();
+ m_finallyDepth--;
+}
+
+LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
+{
+ // Reclaim free label scopes.
+ while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+ m_labelScopes.removeLast();
+
+ if (!m_labelScopes.size())
+ return 0;
+
+ // We special-case the following, which is a syntax error in Firefox:
+ // label:
+ // break;
+ if (name.isEmpty()) {
+ for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
+ LabelScope* scope = &m_labelScopes[i];
+ if (scope->type() != LabelScope::NamedLabel) {
+ ASSERT(scope->breakTarget());
+ return scope;
+ }
+ }
+ return 0;
+ }
+
+ for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
+ LabelScope* scope = &m_labelScopes[i];
+ if (scope->name() && *scope->name() == name) {
+ ASSERT(scope->breakTarget());
+ return scope;
+ }
+ }
+ return 0;
+}
+
+LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
+{
+ // Reclaim free label scopes.
+ while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+ m_labelScopes.removeLast();
+
+ if (!m_labelScopes.size())
+ return 0;
+
+ if (name.isEmpty()) {
+ for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
+ LabelScope* scope = &m_labelScopes[i];
+ if (scope->type() == LabelScope::Loop) {
+ ASSERT(scope->continueTarget());
+ return scope;
+ }
+ }
+ return 0;
+ }
+
+ // Continue to the loop nested nearest to the label scope that matches
+ // 'name'.
+ LabelScope* result = 0;
+ for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
+ LabelScope* scope = &m_labelScopes[i];
+ if (scope->type() == LabelScope::Loop) {
+ ASSERT(scope->continueTarget());
+ result = scope;
+ }
+ if (scope->name() && *scope->name() == name)
+ return result; // may be 0
+ }
+ return 0;
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
+{
+ while (topScope > bottomScope) {
+ // First we count the number of dynamic scopes we need to remove to get
+ // to a finally block.
+ int nNormalScopes = 0;
+ while (topScope > bottomScope) {
+ if (topScope->isFinallyBlock)
+ break;
+ ++nNormalScopes;
+ --topScope;
+ }
+
+ if (nNormalScopes) {
+ // We need to remove a number of dynamic scopes to get to the next
+ // finally block
+ emitOpcode(op_jmp_scopes);
+ instructions().append(nNormalScopes);
+
+ // If topScope == bottomScope then there isn't actually a finally block
+ // left to emit, so make the jmp_scopes jump directly to the target label
+ if (topScope == bottomScope) {
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
+
+ // Otherwise we just use jmp_scopes to pop a group of scopes and go
+ // to the next instruction
+ RefPtr<Label> nextInsn = newLabel();
+ instructions().append(nextInsn->offsetFrom(instructions().size()));
+ emitLabel(nextInsn.get());
+ }
+
+ // To get here there must be at least one finally block present
+ do {
+ ASSERT(topScope->isFinallyBlock);
+ emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
+ --topScope;
+ if (!topScope->isFinallyBlock)
+ break;
+ } while (topScope > bottomScope);
+ }
+ return emitJump(target);
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth)
+{
+ ASSERT(scopeDepth() - targetScopeDepth >= 0);
+ ASSERT(target->isForward());
+
+ size_t scopeDelta = scopeDepth() - targetScopeDepth;
+ ASSERT(scopeDelta <= m_scopeContextStack.size());
+ if (!scopeDelta)
+ return emitJump(target);
+
+ if (m_finallyDepth)
+ return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
+
+ emitOpcode(op_jmp_scopes);
+ instructions().append(scopeDelta);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+}
+
+RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target)
+{
+ emitOpcode(op_next_pname);
+ instructions().append(dst->index());
+ instructions().append(iter->index());
+ instructions().append(target->offsetFrom(instructions().size()));
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
+{
+#if ENABLE(JIT)
+ HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, 0 };
+#else
+ HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
+#endif
+
+ m_codeBlock->addExceptionHandler(info);
+ emitOpcode(op_catch);
+ instructions().append(targetRegister->index());
+ return targetRegister;
+}
+
+RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message)
+{
+ emitOpcode(op_new_error);
+ instructions().append(dst->index());
+ instructions().append(static_cast<int>(type));
+ instructions().append(addUnexpectedConstant(message));
+ return dst;
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
+{
+ emitOpcode(op_jsr);
+ instructions().append(retAddrDst->index());
+ instructions().append(finally->offsetFrom(instructions().size()));
+ return finally;
+}
+
+void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
+{
+ emitOpcode(op_sret);
+ instructions().append(retAddrSrc->index());
+}
+
+void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
+{
+ ControlFlowContext context;
+ context.isFinallyBlock = false;
+ m_scopeContextStack.append(context);
+ m_dynamicScopeDepth++;
+
+ emitOpcode(op_push_new_scope);
+ instructions().append(dst->index());
+ instructions().append(addConstant(property));
+ instructions().append(value->index());
+}
+
+void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
+{
+ SwitchInfo info = { instructions().size(), type };
+ switch (type) {
+ case SwitchInfo::SwitchImmediate:
+ emitOpcode(op_switch_imm);
+ break;
+ case SwitchInfo::SwitchCharacter:
+ emitOpcode(op_switch_char);
+ break;
+ case SwitchInfo::SwitchString:
+ emitOpcode(op_switch_string);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ instructions().append(0); // place holder for table index
+ instructions().append(0); // place holder for default target
+ instructions().append(scrutineeRegister->index());
+ m_switchContextStack.append(info);
+}
+
+static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
+{
+ UNUSED_PARAM(max);
+ ASSERT(node->isNumber());
+ double value = static_cast<NumberNode*>(node)->value();
+ int32_t key = static_cast<int32_t>(value);
+ ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value));
+ ASSERT(key == value);
+ ASSERT(key >= min);
+ ASSERT(key <= max);
+ return key - min;
+}
+
+static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
+{
+ jumpTable.min = min;
+ jumpTable.branchOffsets.resize(max - min + 1);
+ jumpTable.branchOffsets.fill(0);
+ for (uint32_t i = 0; i < clauseCount; ++i) {
+ // We're emitting this after the clause labels should have been fixed, so
+ // the labels should not be "forward" references
+ ASSERT(!labels[i]->isForward());
+ jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));
+ }
+}
+
+static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
+{
+ UNUSED_PARAM(max);
+ ASSERT(node->isString());
+ UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
+ ASSERT(clause->size() == 1);
+
+ int32_t key = clause->data()[0];
+ ASSERT(key >= min);
+ ASSERT(key <= max);
+ return key - min;
+}
+
+static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
+{
+ jumpTable.min = min;
+ jumpTable.branchOffsets.resize(max - min + 1);
+ jumpTable.branchOffsets.fill(0);
+ for (uint32_t i = 0; i < clauseCount; ++i) {
+ // We're emitting this after the clause labels should have been fixed, so
+ // the labels should not be "forward" references
+ ASSERT(!labels[i]->isForward());
+ jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));
+ }
+}
+
+static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
+{
+ for (uint32_t i = 0; i < clauseCount; ++i) {
+ // We're emitting this after the clause labels should have been fixed, so
+ // the labels should not be "forward" references
+ ASSERT(!labels[i]->isForward());
+
+ ASSERT(nodes[i]->isString());
+ UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
+ OffsetLocation location;
+ location.branchOffset = labels[i]->offsetFrom(switchAddress);
+#if ENABLE(JIT)
+ location.ctiOffset = 0;
+#endif
+ jumpTable.offsetTable.add(clause, location);
+ }
+}
+
+void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
+{
+ SwitchInfo switchInfo = m_switchContextStack.last();
+ m_switchContextStack.removeLast();
+ if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
+ instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
+ instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+
+ SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
+ prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+ } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
+ instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
+ instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+
+ SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
+ prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+ } else {
+ ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
+ instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
+ instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+
+ StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
+ prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes);
+ }
+}
+
+RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
+{
+ // It would be nice to do an even better job of identifying exactly where the expression is.
+ // And we could make the caller pass the node pointer in, if there was some way of getting
+ // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
+ // is still good enough to get us an accurate line number.
+ emitExpressionInfo(0, 0, 0);
+ RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep"));
+ emitThrow(exception);
+ return exception;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BytecodeGenerator_h
+#define BytecodeGenerator_h
+
+#include "CodeBlock.h"
+#include "HashTraits.h"
+#include "Instruction.h"
+#include "Label.h"
+#include "LabelScope.h"
+#include "Interpreter.h"
+#include "RegisterID.h"
+#include "SegmentedVector.h"
+#include "SymbolTable.h"
+#include "Debugger.h"
+#include "Nodes.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class Identifier;
+ class ScopeChain;
+ class ScopeNode;
+
+ struct FinallyContext {
+ Label* finallyAddr;
+ RegisterID* retAddrDst;
+ };
+
+ struct ControlFlowContext {
+ bool isFinallyBlock;
+ FinallyContext finallyContext;
+ };
+
+ class BytecodeGenerator {
+ public:
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
+ static bool dumpsGeneratedCode();
+
+ BytecodeGenerator(ProgramNode*, const Debugger*, const ScopeChain&, SymbolTable*, ProgramCodeBlock*);
+ BytecodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*);
+ BytecodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*);
+
+ JSGlobalData* globalData() const { return m_globalData; }
+ const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
+
+ void generate();
+
+ // Returns the register corresponding to a local variable, or 0 if no
+ // such register exists. Registers returned by registerFor do not
+ // require explicit reference counting.
+ RegisterID* registerFor(const Identifier&);
+
+ // Behaves as registerFor does, but ignores dynamic scope as
+ // dynamic scope should not interfere with const initialisation
+ RegisterID* constRegisterFor(const Identifier&);
+
+ // Searches the scope chain in an attempt to statically locate the requested
+ // property. Returns false if for any reason the property cannot be safely
+ // optimised at all. Otherwise it will return the index and depth of the
+ // VariableObject that defines the property. If the property cannot be found
+ // statically, depth will contain the depth of the scope chain where dynamic
+ // lookup must begin.
+ //
+ // NB: depth does _not_ include the local scope. eg. a depth of 0 refers
+ // to the scope containing this codeblock.
+ bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, JSObject*& globalObject);
+
+ // Returns the register storing "this"
+ RegisterID* thisRegister() { return &m_thisRegister; }
+
+ bool isLocal(const Identifier&);
+ bool isLocalConstant(const Identifier&);
+
+ // Returns the next available temporary register. Registers returned by
+ // newTemporary require a modified form of reference counting: any
+ // register with a refcount of 0 is considered "available", meaning that
+ // the next instruction may overwrite it.
+ RegisterID* newTemporary();
+
+ RegisterID* highestUsedRegister();
+
+ // The same as newTemporary(), but this function returns "suggestion" if
+ // "suggestion" is a temporary. This function is helpful in situations
+ // where you've put "suggestion" in a RefPtr, but you'd like to allow
+ // the next instruction to overwrite it anyway.
+ RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
+
+ // Functions for handling of dst register
+
+ RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
+
+ // Returns a place to write intermediate values of an operation
+ // which reuses dst if it is safe to do so.
+ RegisterID* tempDestination(RegisterID* dst)
+ {
+ return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
+ }
+
+ // Returns the place to write the final output of an operation.
+ RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
+ {
+ if (originalDst && originalDst != ignoredResult())
+ return originalDst;
+ ASSERT(tempDst != ignoredResult());
+ if (tempDst && tempDst->isTemporary())
+ return tempDst;
+ return newTemporary();
+ }
+
+ RegisterID* destinationForAssignResult(RegisterID* dst)
+ {
+ if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
+ return dst->isTemporary() ? dst : newTemporary();
+ return 0;
+ }
+
+ // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
+ RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
+ {
+ return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
+ }
+
+ PassRefPtr<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0);
+ PassRefPtr<Label> newLabel();
+
+ // The emitNode functions are just syntactic sugar for calling
+ // Node::emitCode. These functions accept a 0 for the register,
+ // meaning that the node should allocate a register, or ignoredResult(),
+ // meaning that the node need not put the result in a register.
+ // Other emit functions do not accept 0 or ignoredResult().
+ RegisterID* emitNode(RegisterID* dst, Node* n)
+ {
+ // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
+ ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
+ if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {
+ LineInfo info = { instructions().size(), n->lineNo() };
+ m_codeBlock->addLineInfo(info);
+ }
+ if (m_emitNodeDepth >= s_maxEmitNodeDepth)
+ return emitThrowExpressionTooDeepException();
+ ++m_emitNodeDepth;
+ RegisterID* r = n->emitBytecode(*this, dst);
+ --m_emitNodeDepth;
+ return r;
+ }
+
+ RegisterID* emitNode(Node* n)
+ {
+ return emitNode(0, n);
+ }
+
+ void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
+ {
+ divot -= m_codeBlock->sourceOffset();
+ if (divot > ExpressionRangeInfo::MaxDivot) {
+ // Overflow has occurred, we can only give line number info for errors for this region
+ divot = 0;
+ startOffset = 0;
+ endOffset = 0;
+ } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
+ // If the start offset is out of bounds we clear both offsets
+ // so we only get the divot marker. Error message will have to be reduced
+ // to line and column number.
+ startOffset = 0;
+ endOffset = 0;
+ } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
+ // The end offset is only used for additional context, and is much more likely
+ // to overflow (eg. function call arguments) so we are willing to drop it without
+ // dropping the rest of the range.
+ endOffset = 0;
+ }
+
+ ExpressionRangeInfo info;
+ info.instructionOffset = instructions().size();
+ info.divotPoint = divot;
+ info.startOffset = startOffset;
+ info.endOffset = endOffset;
+ m_codeBlock->addExpressionInfo(info);
+ }
+
+ void emitGetByIdExceptionInfo(OpcodeID opcodeID)
+ {
+ // Only op_construct and op_instanceof need exception info for
+ // a preceding op_get_by_id.
+ ASSERT(opcodeID == op_construct || opcodeID == op_instanceof);
+ GetByIdExceptionInfo info;
+ info.bytecodeOffset = instructions().size();
+ info.isOpConstruct = (opcodeID == op_construct);
+ m_codeBlock->addGetByIdExceptionInfo(info);
+ }
+
+ ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
+ {
+ return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
+ }
+
+ ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
+ {
+ if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
+ PassRefPtr<RegisterID> dst = newTemporary();
+ emitNode(dst.get(), n);
+ return dst;
+ }
+
+ return PassRefPtr<RegisterID>(emitNode(n));
+ }
+
+ RegisterID* emitLoad(RegisterID* dst, bool);
+ RegisterID* emitLoad(RegisterID* dst, double);
+ RegisterID* emitLoad(RegisterID* dst, const Identifier&);
+ RegisterID* emitLoad(RegisterID* dst, JSValuePtr);
+ RegisterID* emitUnexpectedLoad(RegisterID* dst, bool);
+ RegisterID* emitUnexpectedLoad(RegisterID* dst, double);
+
+ RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
+ RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
+ RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
+ RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
+
+ RegisterID* emitNewObject(RegisterID* dst);
+ RegisterID* emitNewArray(RegisterID* dst, ElementNode*); // stops at first elision
+
+ RegisterID* emitNewFunction(RegisterID* dst, FuncDeclNode* func);
+ RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
+ RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp);
+
+ RegisterID* emitMove(RegisterID* dst, RegisterID* src);
+
+ RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src); }
+ RegisterID* emitPreInc(RegisterID* srcDst);
+ RegisterID* emitPreDec(RegisterID* srcDst);
+ RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
+ RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
+
+ RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
+ RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
+ RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
+
+ RegisterID* emitResolve(RegisterID* dst, const Identifier& property);
+ RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValuePtr globalObject);
+ RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValuePtr globalObject);
+
+ RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
+ RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
+ RegisterID* emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property);
+
+ RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
+ RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
+ RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
+ RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
+ RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
+ RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
+ RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
+ RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value);
+ RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value);
+
+ RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+ RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ RegisterID* emitReturn(RegisterID* src);
+ RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
+
+ RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ PassRefPtr<Label> emitLabel(Label*);
+ PassRefPtr<Label> emitJump(Label* target);
+ PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
+ PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
+ PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
+
+ PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
+ void emitSubroutineReturn(RegisterID* retAddrSrc);
+
+ RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base); }
+ RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target);
+
+ RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
+ void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
+ RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message);
+ void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value);
+
+ RegisterID* emitPushScope(RegisterID* scope);
+ void emitPopScope();
+
+ void emitDebugHook(DebugHookID, int firstLine, int lastLine);
+
+ int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
+ bool hasFinaliser() { return m_finallyDepth != 0; }
+
+ void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
+ void popFinallyContext();
+
+ LabelScope* breakTarget(const Identifier&);
+ LabelScope* continueTarget(const Identifier&);
+
+ void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
+ void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
+
+ CodeType codeType() const { return m_codeType; }
+
+ void setRegeneratingForExceptionInfo(CodeBlock* originalCodeBlock)
+ {
+ m_regeneratingForExceptionInfo = true;
+ m_codeBlockBeingRegeneratedFrom = originalCodeBlock;
+ }
+
+ private:
+ void emitOpcode(OpcodeID);
+ void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
+ void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
+ void rewindBinaryOp();
+ void rewindUnaryOp();
+
+ PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
+
+ struct JSValueHashTraits : HashTraits<JSValueEncodedAsPointer*> {
+ static void constructDeletedValue(JSValueEncodedAsPointer*& slot) { slot = JSValuePtr::encode(jsImpossibleValue()); }
+ static bool isDeletedValue(JSValueEncodedAsPointer* value) { return value == JSValuePtr::encode(jsImpossibleValue()); }
+ };
+
+ typedef HashMap<JSValueEncodedAsPointer*, unsigned, PtrHash<JSValueEncodedAsPointer*>, JSValueHashTraits> JSValueMap;
+
+ struct IdentifierMapIndexHashTraits {
+ typedef int TraitType;
+ typedef IdentifierMapIndexHashTraits StorageTraits;
+ static int emptyValue() { return std::numeric_limits<int>::max(); }
+ static const bool emptyValueIsZero = false;
+ static const bool needsDestruction = false;
+ static const bool needsRef = false;
+ };
+
+ typedef HashMap<RefPtr<UString::Rep>, int, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, IdentifierMapIndexHashTraits> IdentifierMap;
+ typedef HashMap<double, JSValuePtr> NumberMap;
+ typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap;
+
+ RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ RegisterID* newRegister();
+
+ // Returns the RegisterID corresponding to ident.
+ RegisterID* addVar(const Identifier& ident, bool isConstant)
+ {
+ RegisterID* local;
+ addVar(ident, isConstant, local);
+ return local;
+ }
+ // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
+ bool addVar(const Identifier&, bool isConstant, RegisterID*&);
+
+ // Returns the RegisterID corresponding to ident.
+ RegisterID* addGlobalVar(const Identifier& ident, bool isConstant)
+ {
+ RegisterID* local;
+ addGlobalVar(ident, isConstant, local);
+ return local;
+ }
+ // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
+ bool addGlobalVar(const Identifier&, bool isConstant, RegisterID*&);
+
+ RegisterID* addParameter(const Identifier&);
+
+ void allocateConstants(size_t);
+
+ RegisterID& registerFor(int index)
+ {
+ if (index >= 0)
+ return m_calleeRegisters[index];
+
+ if (index == RegisterFile::OptionalCalleeArguments)
+ return m_argumentsRegister;
+
+ if (m_parameters.size()) {
+ ASSERT(!m_globals.size());
+ return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
+ }
+
+ return m_globals[-index - 1];
+ }
+
+ unsigned addConstant(FuncDeclNode*);
+ unsigned addConstant(FuncExprNode*);
+ unsigned addConstant(const Identifier&);
+ RegisterID* addConstant(JSValuePtr);
+ unsigned addUnexpectedConstant(JSValuePtr);
+ unsigned addRegExp(RegExp*);
+
+ Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
+ SymbolTable& symbolTable() { return *m_symbolTable; }
+
+ bool shouldOptimizeLocals() { return (m_codeType != EvalCode) && !m_dynamicScopeDepth; }
+ bool canOptimizeNonLocals() { return (m_codeType == FunctionCode) && !m_dynamicScopeDepth && !m_codeBlock->usesEval(); }
+
+ RegisterID* emitThrowExpressionTooDeepException();
+
+ bool m_shouldEmitDebugHooks;
+ bool m_shouldEmitProfileHooks;
+
+ const ScopeChain* m_scopeChain;
+ SymbolTable* m_symbolTable;
+
+ ScopeNode* m_scopeNode;
+ CodeBlock* m_codeBlock;
+
+ HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions;
+ RegisterID m_ignoredResultRegister;
+ RegisterID m_thisRegister;
+ RegisterID m_argumentsRegister;
+ int m_activationRegisterIndex;
+ SegmentedVector<RegisterID, 512> m_calleeRegisters;
+ SegmentedVector<RegisterID, 512> m_parameters;
+ SegmentedVector<RegisterID, 512> m_globals;
+ SegmentedVector<LabelScope, 256> m_labelScopes;
+ SegmentedVector<Label, 256> m_labels;
+ RefPtr<RegisterID> m_lastConstant;
+ int m_finallyDepth;
+ int m_dynamicScopeDepth;
+ int m_baseScopeDepth;
+ CodeType m_codeType;
+
+ Vector<ControlFlowContext> m_scopeContextStack;
+ Vector<SwitchInfo> m_switchContextStack;
+
+ int m_nextGlobalIndex;
+ int m_nextParameterIndex;
+ int m_nextConstantIndex;
+
+ int m_globalVarStorageOffset;
+
+ // Constant pool
+ IdentifierMap m_identifierMap;
+ JSValueMap m_jsValueMap;
+ NumberMap m_numberMap;
+ IdentifierStringMap m_stringMap;
+
+ JSGlobalData* m_globalData;
+
+ OpcodeID m_lastOpcodeID;
+
+ unsigned m_emitNodeDepth;
+
+ bool m_regeneratingForExceptionInfo;
+ CodeBlock* m_codeBlockBeingRegeneratedFrom;
+
+ static const unsigned s_maxEmitNodeDepth = 10000;
+ };
+
+}
+
+#endif // BytecodeGenerator_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Label_h
+#define Label_h
+
+#include "CodeBlock.h"
+#include "Instruction.h"
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+#include <limits.h>
+
+namespace JSC {
+
+ class Label {
+ public:
+ explicit Label(CodeBlock* codeBlock)
+ : m_refCount(0)
+ , m_location(invalidLocation)
+ , m_codeBlock(codeBlock)
+ {
+ }
+
+ void setLocation(unsigned location)
+ {
+ m_location = location;
+
+ unsigned size = m_unresolvedJumps.size();
+ for (unsigned i = 0; i < size; ++i) {
+ unsigned j = m_unresolvedJumps[i];
+ m_codeBlock->instructions()[j].u.operand = m_location - j;
+ }
+ }
+
+ int offsetFrom(int location) const
+ {
+ if (m_location == invalidLocation) {
+ m_unresolvedJumps.append(location);
+ return 0;
+ }
+ return m_location - location;
+ }
+
+ void ref() { ++m_refCount; }
+ void deref()
+ {
+ --m_refCount;
+ ASSERT(m_refCount >= 0);
+ }
+ int refCount() const { return m_refCount; }
+
+ bool isForward() const { return m_location == invalidLocation; }
+
+ private:
+ typedef Vector<int, 8> JumpVector;
+
+ static const unsigned invalidLocation = UINT_MAX;
+
+ int m_refCount;
+ unsigned m_location;
+ CodeBlock* m_codeBlock;
+ mutable JumpVector m_unresolvedJumps;
+ };
+
+} // namespace JSC
+
+#endif // Label_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LabelScope_h
+#define LabelScope_h
+
+#include <wtf/PassRefPtr.h>
+#include "Label.h"
+
+namespace JSC {
+
+ class Identifier;
+
+ class LabelScope {
+ public:
+ enum Type { Loop, Switch, NamedLabel };
+
+ LabelScope(Type type, const Identifier* name, int scopeDepth, PassRefPtr<Label> breakTarget, PassRefPtr<Label> continueTarget)
+ : m_refCount(0)
+ , m_type(type)
+ , m_name(name)
+ , m_scopeDepth(scopeDepth)
+ , m_breakTarget(breakTarget)
+ , m_continueTarget(continueTarget)
+ {
+ }
+
+ void ref() { ++m_refCount; }
+ void deref()
+ {
+ --m_refCount;
+ ASSERT(m_refCount >= 0);
+ }
+ int refCount() const { return m_refCount; }
+
+ Label* breakTarget() const { return m_breakTarget.get(); }
+ Label* continueTarget() const { return m_continueTarget.get(); }
+
+ Type type() const { return m_type; }
+ const Identifier* name() const { return m_name; }
+ int scopeDepth() const { return m_scopeDepth; }
+
+ private:
+ int m_refCount;
+ Type m_type;
+ const Identifier* m_name;
+ int m_scopeDepth;
+ RefPtr<Label> m_breakTarget;
+ RefPtr<Label> m_continueTarget;
+ };
+
+} // namespace JSC
+
+#endif // LabelScope_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RegisterID_h
+#define RegisterID_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/VectorTraits.h>
+
+namespace JSC {
+
+ class RegisterID : Noncopyable {
+ public:
+ RegisterID()
+ : m_refCount(0)
+ , m_isTemporary(false)
+#ifndef NDEBUG
+ , m_didSetIndex(false)
+#endif
+ {
+ }
+
+ explicit RegisterID(int index)
+ : m_refCount(0)
+ , m_index(index)
+ , m_isTemporary(false)
+#ifndef NDEBUG
+ , m_didSetIndex(true)
+#endif
+ {
+ }
+
+ void setIndex(int index)
+ {
+ ASSERT(!m_refCount);
+#ifndef NDEBUG
+ m_didSetIndex = true;
+#endif
+ m_index = index;
+ }
+
+ void setTemporary()
+ {
+ m_isTemporary = true;
+ }
+
+ int index() const
+ {
+ ASSERT(m_didSetIndex);
+ return m_index;
+ }
+
+ bool isTemporary()
+ {
+ return m_isTemporary;
+ }
+
+ void ref()
+ {
+ ++m_refCount;
+ }
+
+ void deref()
+ {
+ --m_refCount;
+ ASSERT(m_refCount >= 0);
+ }
+
+ int refCount() const
+ {
+ return m_refCount;
+ }
+
+ private:
+
+ int m_refCount;
+ int m_index;
+ bool m_isTemporary;
+#ifndef NDEBUG
+ bool m_didSetIndex;
+#endif
+ };
+
+} // namespace JSC
+
+namespace WTF {
+
+ template<> struct VectorTraits<JSC::RegisterID> : VectorTraitsBase<true, JSC::RegisterID> {
+ static const bool needsInitialization = true;
+ static const bool canInitializeWithMemset = true; // Default initialization just sets everything to 0 or false, so this is safe.
+ };
+
+} // namespace WTF
+
+#endif // RegisterID_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SegmentedVector_h
+#define SegmentedVector_h
+
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ // SegmentedVector is just like Vector, but it doesn't move the values
+ // stored in its buffer when it grows. Therefore, it is safe to keep
+ // pointers into a SegmentedVector.
+ template <typename T, size_t SegmentSize> class SegmentedVector {
+ public:
+ SegmentedVector()
+ : m_size(0)
+ {
+ m_segments.append(&m_inlineSegment);
+ }
+
+ ~SegmentedVector()
+ {
+ deleteAllSegments();
+ }
+
+ size_t size() const { return m_size; }
+
+ T& at(size_t index)
+ {
+ if (index < SegmentSize)
+ return m_inlineSegment[index];
+ return segmentFor(index)->at(subscriptFor(index));
+ }
+
+ T& operator[](size_t index)
+ {
+ return at(index);
+ }
+
+ T& last()
+ {
+ return at(size() - 1);
+ }
+
+ template <typename U> void append(const U& value)
+ {
+ ++m_size;
+
+ if (m_size <= SegmentSize) {
+ m_inlineSegment.uncheckedAppend(value);
+ return;
+ }
+
+ if (!segmentExistsFor(m_size - 1))
+ m_segments.append(new Segment);
+ segmentFor(m_size - 1)->uncheckedAppend(value);
+ }
+
+ void removeLast()
+ {
+ if (m_size <= SegmentSize)
+ m_inlineSegment.removeLast();
+ else
+ segmentFor(m_size - 1)->removeLast();
+ --m_size;
+ }
+
+ void grow(size_t size)
+ {
+ ASSERT(size > m_size);
+ ensureSegmentsFor(size);
+ m_size = size;
+ }
+
+ void clear()
+ {
+ deleteAllSegments();
+ m_segments.resize(1);
+ m_inlineSegment.clear();
+ m_size = 0;
+ }
+
+ private:
+ typedef Vector<T, SegmentSize> Segment;
+
+ void deleteAllSegments()
+ {
+ // Skip the first segment, because it's our inline segment, which was
+ // not created by new.
+ for (size_t i = 1; i < m_segments.size(); i++)
+ delete m_segments[i];
+ }
+
+ bool segmentExistsFor(size_t index)
+ {
+ return index / SegmentSize < m_segments.size();
+ }
+
+ Segment* segmentFor(size_t index)
+ {
+ return m_segments[index / SegmentSize];
+ }
+
+ size_t subscriptFor(size_t index)
+ {
+ return index % SegmentSize;
+ }
+
+ void ensureSegmentsFor(size_t size)
+ {
+ size_t segmentCount = m_size / SegmentSize;
+ if (m_size % SegmentSize)
+ ++segmentCount;
+ segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment.
+
+ size_t neededSegmentCount = size / SegmentSize;
+ if (size % SegmentSize)
+ ++neededSegmentCount;
+
+ // Fill up to N - 1 segments.
+ size_t end = neededSegmentCount - 1;
+ for (size_t i = segmentCount - 1; i < end; ++i)
+ ensureSegment(i, SegmentSize);
+
+ // Grow segment N to accomodate the remainder.
+ ensureSegment(end, subscriptFor(size - 1) + 1);
+ }
+
+ void ensureSegment(size_t segmentIndex, size_t size)
+ {
+ ASSERT(segmentIndex <= m_segments.size());
+ if (segmentIndex == m_segments.size())
+ m_segments.append(new Segment);
+ m_segments[segmentIndex]->grow(size);
+ }
+
+ size_t m_size;
+ Segment m_inlineSegment;
+ Vector<Segment*, 32> m_segments;
+ };
+
+} // namespace JSC
+
+#endif // SegmentedVector_h
--- /dev/null
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
+#include "autotoolsconfig.h"
+#endif
+
+#include <wtf/Platform.h>
+
+#if PLATFORM(WIN_OS)
+
+// If we don't define these, they get defined in windef.h.
+// We want to use std::min and std::max
+#define max max
+#define min min
+
+#if !COMPILER(MSVC7) && !PLATFORM(WIN_CE)
+// We need to define this before the first #include of stdlib.h or it won't contain rand_s.
+#ifndef _CRT_RAND_S
+#define _CRT_RAND_S
+#endif
+#endif
+
+#endif
+
+#if PLATFORM(FREEBSD) || PLATFORM(OPENBSD)
+#define HAVE_PTHREAD_NP_H 1
+#endif
+
+/* FIXME: if all platforms have these, do they really need #defines? */
+#define HAVE_STDINT_H 1
+#define HAVE_STRING_H 1
+
+#define WTF_CHANGES 1
+
+#ifdef __cplusplus
+#undef new
+#undef delete
+#include <wtf/FastMalloc.h>
+#endif
+
+// this breaks compilation of <QFontDatabase>, at least, so turn it off for now
+// Also generates errors on wx on Windows, because these functions
+// are used from wx headers.
+#if !PLATFORM(QT) && !PLATFORM(WX)
+#include <wtf/DisallowCType.h>
+#endif
+
--- /dev/null
+#! /usr/bin/perl -w
+#
+# Static Hashtable Generator
+#
+# (c) 2000-2002 by Harri Porten <porten@kde.org> and
+# David Faure <faure@kde.org>
+# Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org>
+# Copyright (C) 2007, 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
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+use strict;
+
+my $file = $ARGV[0];
+shift;
+my $includelookup = 0;
+
+# Use -i as second argument to make it include "Lookup.h"
+$includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i");
+
+# Use -n as second argument to make it use the third argument as namespace parameter ie. -n KDOM
+my $useNameSpace = $ARGV[1] if (defined($ARGV[0]) && $ARGV[0] eq "-n");
+
+print STDERR "Creating hashtable for $file\n";
+open(IN, $file) or die "No such file $file";
+
+my @keys = ();
+my @attrs = ();
+my @values = ();
+my @hashes = ();
+
+my $inside = 0;
+my $name;
+my $pefectHashSize;
+my $compactSize;
+my $compactHashSizeMask;
+my $banner = 0;
+sub calcPerfectHashSize();
+sub calcCompactHashSize();
+sub output();
+sub jsc_ucfirst($);
+sub hashValue($);
+
+while (<IN>) {
+ chomp;
+ s/^\s+//;
+ next if /^\#|^$/; # Comment or blank line. Do nothing.
+ if (/^\@begin/ && !$inside) {
+ if (/^\@begin\s*([:_\w]+)\s*\d*\s*$/) {
+ $inside = 1;
+ $name = $1;
+ } else {
+ print STDERR "WARNING: \@begin without table name, skipping $_\n";
+ }
+ } elsif (/^\@end\s*$/ && $inside) {
+ calcPerfectHashSize();
+ calcCompactHashSize();
+ output();
+
+ @keys = ();
+ @attrs = ();
+ @values = ();
+ @hashes = ();
+
+ $inside = 0;
+ } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) {
+ my $key = $1;
+ my $val = $2;
+ my $att = $3;
+ my $param = $4;
+
+ push(@keys, $key);
+ push(@attrs, length($att) > 0 ? $att : "0");
+
+ if ($att =~ m/Function/) {
+ push(@values, { "type" => "Function", "function" => $val, "params" => (length($param) ? $param : "") });
+ #printf STDERR "WARNING: Number of arguments missing for $key/$val\n" if (length($param) == 0);
+ } elsif (length($att)) {
+ my $get = $val;
+ my $put = !($att =~ m/ReadOnly/) ? "set" . jsc_ucfirst($val) : "0";
+ push(@values, { "type" => "Property", "get" => $get, "put" => $put });
+ } else {
+ push(@values, { "type" => "Lexer", "value" => $val });
+ }
+ push(@hashes, hashValue($key));
+ } elsif ($inside) {
+ die "invalid data {" . $_ . "}";
+ }
+}
+
+die "missing closing \@end" if ($inside);
+
+sub jsc_ucfirst($)
+{
+ my ($value) = @_;
+
+ if ($value =~ /js/) {
+ $value =~ s/js/JS/;
+ return $value;
+ }
+
+ return ucfirst($value);
+}
+
+
+sub ceilingToPowerOf2
+{
+ my ($pefectHashSize) = @_;
+
+ my $powerOf2 = 1;
+ while ($pefectHashSize > $powerOf2) {
+ $powerOf2 <<= 1;
+ }
+
+ return $powerOf2;
+}
+
+sub calcPerfectHashSize()
+{
+tableSizeLoop:
+ for ($pefectHashSize = ceilingToPowerOf2(scalar @keys); ; $pefectHashSize += $pefectHashSize) {
+ my @table = ();
+ foreach my $key (@keys) {
+ my $h = hashValue($key) % $pefectHashSize;
+ next tableSizeLoop if $table[$h];
+ $table[$h] = 1;
+ }
+ last;
+ }
+}
+
+sub leftShift($$) {
+ my ($value, $distance) = @_;
+ return (($value << $distance) & 0xFFFFFFFF);
+}
+
+sub calcCompactHashSize()
+{
+ my @table = ();
+ my @links = ();
+ my $compactHashSize = ceilingToPowerOf2(2 * @keys);
+ $compactHashSizeMask = $compactHashSize - 1;
+ $compactSize = $compactHashSize;
+ my $collisions = 0;
+ my $maxdepth = 0;
+ my $i = 0;
+ foreach my $key (@keys) {
+ my $depth = 0;
+ my $h = hashValue($key) % $compactHashSize;
+ while (defined($table[$h])) {
+ if (defined($links[$h])) {
+ $h = $links[$h];
+ $depth++;
+ } else {
+ $collisions++;
+ $links[$h] = $compactSize;
+ $h = $compactSize;
+ $compactSize++;
+ }
+ }
+ $table[$h] = $i;
+ $i++;
+ $maxdepth = $depth if ( $depth > $maxdepth);
+ }
+}
+
+# Paul Hsieh's SuperFastHash
+# http://www.azillionmonkeys.com/qed/hash.html
+# Ported from UString..
+sub hashValue($) {
+ my @chars = split(/ */, $_[0]);
+
+ # This hash is designed to work on 16-bit chunks at a time. But since the normal case
+ # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
+ # were 16-bit chunks, which should give matching results
+
+ my $EXP2_32 = 4294967296;
+
+ my $hash = 0x9e3779b9;
+ my $l = scalar @chars; #I wish this was in Ruby --- Maks
+ my $rem = $l & 1;
+ $l = $l >> 1;
+
+ my $s = 0;
+
+ # Main loop
+ for (; $l > 0; $l--) {
+ $hash += ord($chars[$s]);
+ my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
+ $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
+ $s += 2;
+ $hash += $hash >> 11;
+ $hash %= $EXP2_32;
+ }
+
+ # Handle end case
+ if ($rem !=0) {
+ $hash += ord($chars[$s]);
+ $hash ^= (leftShift($hash, 11)% $EXP2_32);
+ $hash += $hash >> 17;
+ }
+
+ # Force "avalanching" of final 127 bits
+ $hash ^= leftShift($hash, 3);
+ $hash += ($hash >> 5);
+ $hash = ($hash% $EXP2_32);
+ $hash ^= (leftShift($hash, 2)% $EXP2_32);
+ $hash += ($hash >> 15);
+ $hash = $hash% $EXP2_32;
+ $hash ^= (leftShift($hash, 10)% $EXP2_32);
+
+ # this avoids ever returning a hash code of 0, since that is used to
+ # signal "hash not computed yet", using a value that is likely to be
+ # effectively the same as 0 when the low bits are masked
+ $hash = 0x80000000 if ($hash == 0);
+
+ return $hash;
+}
+
+sub output() {
+ if (!$banner) {
+ $banner = 1;
+ print "// Automatically generated from $file using $0. DO NOT EDIT!\n";
+ }
+
+ my $nameEntries = "${name}Values";
+ $nameEntries =~ s/:/_/g;
+
+ print "\n#include \"Lookup.h\"\n" if ($includelookup);
+ if ($useNameSpace) {
+ print "\nnamespace ${useNameSpace} {\n";
+ print "\nusing namespace JSC;\n";
+ } else {
+ print "\nnamespace JSC {\n";
+ }
+ my $count = scalar @keys + 1;
+ print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n";
+ my $i = 0;
+ foreach my $key (@keys) {
+ my $firstValue = "";
+ my $secondValue = "";
+
+ if ($values[$i]{"type"} eq "Function") {
+ $firstValue = $values[$i]{"function"};
+ $secondValue = $values[$i]{"params"};
+ } elsif ($values[$i]{"type"} eq "Property") {
+ $firstValue = $values[$i]{"get"};
+ $secondValue = $values[$i]{"put"};
+ } elsif ($values[$i]{"type"} eq "Lexer") {
+ $firstValue = $values[$i]{"value"};
+ $secondValue = "0";
+ }
+ print " { \"$key\", $attrs[$i], (intptr_t)$firstValue, (intptr_t)$secondValue },\n";
+ $i++;
+ }
+ print " { 0, 0, 0, 0 }\n";
+ print "};\n\n";
+ print "extern const struct HashTable $name =\n";
+ print "#if ENABLE(PERFECT_HASH_SIZE)\n";
+ print " \{ ", $pefectHashSize - 1, ", $nameEntries, 0 \};\n";
+ print "#else\n";
+ print " \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n";
+ print "#endif\n\n";
+ print "} // namespace\n";
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "Debugger.h"
+
+#include "JSGlobalObject.h"
+#include "Interpreter.h"
+#include "Parser.h"
+
+namespace JSC {
+
+Debugger::Debugger()
+{
+}
+
+Debugger::~Debugger()
+{
+ HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
+ for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it)
+ (*it)->setDebugger(0);
+}
+
+void Debugger::attach(JSGlobalObject* globalObject)
+{
+ ASSERT(!globalObject->debugger());
+ globalObject->setDebugger(this);
+ m_globalObjects.add(globalObject);
+}
+
+void Debugger::detach(JSGlobalObject* globalObject)
+{
+ ASSERT(m_globalObjects.contains(globalObject));
+ m_globalObjects.remove(globalObject);
+ globalObject->setDebugger(0);
+}
+
+JSValuePtr evaluateInGlobalCallFrame(const UString& script, JSValuePtr& exception, JSGlobalObject* globalObject)
+{
+ CallFrame* globalCallFrame = globalObject->globalExec();
+
+ int errLine;
+ UString errMsg;
+ SourceCode source = makeSource(script);
+ RefPtr<EvalNode> evalNode = globalObject->globalData()->parser->parse<EvalNode>(globalCallFrame, globalObject->debugger(), source, &errLine, &errMsg);
+ if (!evalNode)
+ return Error::create(globalCallFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+
+ return globalObject->globalData()->interpreter->execute(evalNode.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * 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.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef Debugger_h
+#define Debugger_h
+
+#include "Protect.h"
+
+namespace JSC {
+
+ class DebuggerCallFrame;
+ class ExecState;
+ class JSGlobalObject;
+ class SourceCode;
+ class UString;
+
+ class Debugger {
+ public:
+ Debugger();
+ virtual ~Debugger();
+
+ void attach(JSGlobalObject*);
+ 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 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;
+
+ private:
+ HashSet<JSGlobalObject*> m_globalObjects;
+ };
+
+ // This method exists only for backwards compatibility with existing
+ // WebScriptDebugger clients
+ JSValuePtr evaluateInGlobalCallFrame(const UString&, JSValuePtr& exception, JSGlobalObject*);
+
+} // namespace JSC
+
+#endif // Debugger_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DebuggerActivation.h"
+
+#include "JSActivation.h"
+
+namespace JSC {
+
+DebuggerActivation::DebuggerActivation(JSObject* activation)
+ : JSObject(DebuggerActivation::createStructure(jsNull()))
+{
+ ASSERT(activation);
+ ASSERT(activation->isActivationObject());
+ m_activation = static_cast<JSActivation*>(activation);
+}
+
+void DebuggerActivation::mark()
+{
+ JSObject::mark();
+ if (m_activation && !m_activation->marked())
+ m_activation->mark();
+}
+
+UString DebuggerActivation::className() const
+{
+ return m_activation->className();
+}
+
+bool DebuggerActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return m_activation->getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void DebuggerActivation::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ m_activation->put(exec, propertyName, value, slot);
+}
+
+void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ m_activation->putWithAttributes(exec, propertyName, value, attributes);
+}
+
+bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ return m_activation->deleteProperty(exec, propertyName);
+}
+
+void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ m_activation->getPropertyNames(exec, propertyNames);
+}
+
+bool DebuggerActivation::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+{
+ return m_activation->getPropertyAttributes(exec, propertyName, attributes);
+}
+
+void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+{
+ m_activation->defineGetter(exec, propertyName, getterFunction);
+}
+
+void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+{
+ m_activation->defineSetter(exec, propertyName, setterFunction);
+}
+
+JSValuePtr DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
+{
+ return m_activation->lookupGetter(exec, propertyName);
+}
+
+JSValuePtr DebuggerActivation::lookupSetter(ExecState* exec, const Identifier& propertyName)
+{
+ return m_activation->lookupSetter(exec, propertyName);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DebuggerActivation_h
+#define DebuggerActivation_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class JSActivation;
+
+ class DebuggerActivation : public JSObject {
+ public:
+ DebuggerActivation(JSObject*);
+
+ virtual void mark();
+ virtual UString className() const;
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr, unsigned attributes);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+ virtual JSValuePtr lookupGetter(ExecState*, const Identifier& propertyName);
+ virtual JSValuePtr lookupSetter(ExecState*, const Identifier& propertyName);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ JSActivation* m_activation;
+ };
+
+} // namespace JSC
+
+#endif // DebuggerActivation_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DebuggerCallFrame.h"
+
+#include "JSFunction.h"
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "Parser.h"
+
+namespace JSC {
+
+const UString* DebuggerCallFrame::functionName() const
+{
+ if (!m_callFrame->codeBlock())
+ return 0;
+
+ JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
+ if (!function)
+ return 0;
+ return &function->name(&m_callFrame->globalData());
+}
+
+DebuggerCallFrame::Type DebuggerCallFrame::type() const
+{
+ if (m_callFrame->callee())
+ return FunctionType;
+
+ return ProgramType;
+}
+
+JSObject* DebuggerCallFrame::thisObject() const
+{
+ if (!m_callFrame->codeBlock())
+ return 0;
+
+ return asObject(m_callFrame->thisValue());
+}
+
+JSValuePtr DebuggerCallFrame::evaluate(const UString& script, JSValuePtr& exception) const
+{
+ if (!m_callFrame->codeBlock())
+ return noValue();
+
+ int errLine;
+ UString errMsg;
+ SourceCode source = makeSource(script);
+ RefPtr<EvalNode> evalNode = m_callFrame->scopeChain()->globalData->parser->parse<EvalNode>(m_callFrame, m_callFrame->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+ if (!evalNode)
+ return Error::create(m_callFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+
+ return m_callFrame->scopeChain()->globalData->interpreter->execute(evalNode.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DebuggerCallFrame_h
+#define DebuggerCallFrame_h
+
+#include "CallFrame.h"
+
+namespace JSC {
+
+ class DebuggerCallFrame {
+ public:
+ enum Type { ProgramType, FunctionType };
+
+ DebuggerCallFrame(CallFrame* callFrame)
+ : m_callFrame(callFrame)
+ , m_exception(noValue())
+ {
+ }
+
+ DebuggerCallFrame(CallFrame* callFrame, JSValuePtr exception)
+ : m_callFrame(callFrame)
+ , m_exception(exception)
+ {
+ }
+
+ JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
+ const ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
+ const UString* functionName() const;
+ Type type() const;
+ JSObject* thisObject() const;
+ JSValuePtr evaluate(const UString&, JSValuePtr& exception) const;
+ JSValuePtr exception() const { return m_exception; }
+
+ private:
+ CallFrame* m_callFrame;
+ JSValuePtr m_exception;
+ };
+
+} // namespace JSC
+
+#endif // DebuggerCallFrame_h
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+
+open MACHINE, "<" . $ARGV[0];
+open OUTPUT, ">" . $ARGV[1];
+
+my @undocumented = ();
+
+print OUTPUT "<style>p code \{ font-size: 14px; \}</style>\n";
+
+while (<MACHINE>) {
+ if (/^ *DEFINE_OPCODE/) {
+ chomp;
+ s/^ *DEFINE_OPCODE\(op_//;
+ s/\).*$//;
+ my $opcode = $_;
+ $_ = <MACHINE>;
+ chomp;
+ if (m|/\* |) {
+ my $format = $_;
+ $format =~ s|.* /\* ||;
+ my $doc = "";
+ while (<MACHINE>) {
+ if (m|\*/|) {
+ last;
+ }
+ $doc .= $_ . " ";
+ }
+
+ print OUTPUT "<h2><code>${opcode}</code></h2>\n<p><b>Format: </b><code>\n${format}\n</code></p>\n<p>\n${doc}\n</p>\n";
+ } else {
+ push @undocumented, $opcode;
+ }
+ }
+}
+
+close OUTPUT;
+
+for my $undoc (@undocumented) {
+ print "UNDOCUMENTED: ${undoc}\n";
+}
--- /dev/null
+/*
+**********************************************************************
+* Copyright (C) 1999-2004, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+* Date Name Description
+* 03/14/00 aliu Creation.
+* 06/27/00 aliu Change from C++ class to C struct
+**********************************************************************
+*/
+#ifndef PARSEERR_H
+#define PARSEERR_H
+
+#include "unicode/utypes.h"
+
+
+/**
+ * The capacity of the context strings in UParseError.
+ * @stable ICU 2.0
+ */
+enum { U_PARSE_CONTEXT_LEN = 16 };
+
+/**
+ * A UParseError struct is used to returned detailed information about
+ * parsing errors. It is used by ICU parsing engines that parse long
+ * rules, patterns, or programs, where the text being parsed is long
+ * enough that more information than a UErrorCode is needed to
+ * localize the error.
+ *
+ * <p>The line, offset, and context fields are optional; parsing
+ * engines may choose not to use to use them.
+ *
+ * <p>The preContext and postContext strings include some part of the
+ * context surrounding the error. If the source text is "let for=7"
+ * and "for" is the error (e.g., because it is a reserved word), then
+ * some examples of what a parser might produce are the following:
+ *
+ * <pre>
+ * preContext postContext
+ * "" "" The parser does not support context
+ * "let " "=7" Pre- and post-context only
+ * "let " "for=7" Pre- and post-context and error text
+ * "" "for" Error text only
+ * </pre>
+ *
+ * <p>Examples of engines which use UParseError (or may use it in the
+ * future) are Transliterator, RuleBasedBreakIterator, and
+ * RegexPattern.
+ *
+ * @stable ICU 2.0
+ */
+typedef struct UParseError {
+
+ /**
+ * The line on which the error occured. If the parser uses this
+ * field, it sets it to the line number of the source text line on
+ * which the error appears, which will be be a value >= 1. If the
+ * parse does not support line numbers, the value will be <= 0.
+ * @stable ICU 2.0
+ */
+ int32_t line;
+
+ /**
+ * The character offset to the error. If the line field is >= 1,
+ * then this is the offset from the start of the line. Otherwise,
+ * this is the offset from the start of the text. If the parser
+ * does not support this field, it will have a value < 0.
+ * @stable ICU 2.0
+ */
+ int32_t offset;
+
+ /**
+ * Textual context before the error. Null-terminated. The empty
+ * string if not supported by parser.
+ * @stable ICU 2.0
+ */
+ UChar preContext[U_PARSE_CONTEXT_LEN];
+
+ /**
+ * The error itself and/or textual context after the error.
+ * Null-terminated. The empty string if not supported by parser.
+ * @stable ICU 2.0
+ */
+ UChar postContext[U_PARSE_CONTEXT_LEN];
+
+} UParseError;
+
+#endif
--- /dev/null
+/*
+*******************************************************************************
+* Copyright (c) 1996-2005, International Business Machines Corporation and others.
+* All Rights Reserved.
+*******************************************************************************
+*/
+
+#ifndef UCOL_H
+#define UCOL_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/unorm.h"
+#include "unicode/parseerr.h"
+#include "unicode/uloc.h"
+#include "unicode/uset.h"
+
+/**
+ * \file
+ * \brief C API: Collator
+ *
+ * <h2> Collator C API </h2>
+ *
+ * The C API for Collator performs locale-sensitive
+ * string comparison. You use this service to build
+ * searching and sorting routines for natural language text.
+ * <em>Important: </em>The ICU collation service has been reimplemented
+ * in order to achieve better performance and UCA compliance.
+ * For details, see the
+ * <a href="http://icu.sourceforge.net/cvs/icu/~checkout~/icuhtml/design/collation/ICU_collation_design.htm">
+ * collation design document</a>.
+ * <p>
+ * For more information about the collation service see
+ * <a href="http://icu.sourceforge.net/icu/userguide/Collate_Intro.html">the users guide</a>.
+ * <p>
+ * Collation service provides correct sorting orders for most locales supported in ICU.
+ * If specific data for a locale is not available, the orders eventually falls back
+ * to the <a href="http://www.unicode.org/unicode/reports/tr10/">UCA sort order</a>.
+ * <p>
+ * Sort ordering may be customized by providing your own set of rules. For more on
+ * this subject see the
+ * <a href="http://icu.sourceforge.net/icu/userguide/Collate_Customization.html">
+ * Collation customization</a> section of the users guide.
+ * <p>
+ * @see UCollationResult
+ * @see UNormalizationMode
+ * @see UCollationStrength
+ * @see UCollationElements
+ */
+
+/** A collation element iterator.
+* For usage in C programs.
+*/
+struct collIterate;
+/** structure representing collation element iterator instance
+ * @stable ICU 2.0
+ */
+typedef struct collIterate collIterate;
+
+/** A collator.
+* For usage in C programs.
+*/
+struct UCollator;
+/** structure representing a collator object instance
+ * @stable ICU 2.0
+ */
+typedef struct UCollator UCollator;
+
+
+/**
+ * UCOL_LESS is returned if source string is compared to be less than target
+ * string in the u_strcoll() method.
+ * UCOL_EQUAL is returned if source string is compared to be equal to target
+ * string in the u_strcoll() method.
+ * UCOL_GREATER is returned if source string is compared to be greater than
+ * target string in the u_strcoll() method.
+ * @see u_strcoll()
+ * <p>
+ * Possible values for a comparison result
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** string a == string b */
+ UCOL_EQUAL = 0,
+ /** string a > string b */
+ UCOL_GREATER = 1,
+ /** string a < string b */
+ UCOL_LESS = -1
+} UCollationResult ;
+
+
+/** Enum containing attribute values for controling collation behavior.
+ * Here are all the allowable values. Not every attribute can take every value. The only
+ * universal value is UCOL_DEFAULT, which resets the attribute value to the predefined
+ * value for that locale
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** accepted by most attributes */
+ UCOL_DEFAULT = -1,
+
+ /** Primary collation strength */
+ UCOL_PRIMARY = 0,
+ /** Secondary collation strength */
+ UCOL_SECONDARY = 1,
+ /** Tertiary collation strength */
+ UCOL_TERTIARY = 2,
+ /** Default collation strength */
+ UCOL_DEFAULT_STRENGTH = UCOL_TERTIARY,
+ UCOL_CE_STRENGTH_LIMIT,
+ /** Quaternary collation strength */
+ UCOL_QUATERNARY=3,
+ /** Identical collation strength */
+ UCOL_IDENTICAL=15,
+ UCOL_STRENGTH_LIMIT,
+
+ /** Turn the feature off - works for UCOL_FRENCH_COLLATION,
+ UCOL_CASE_LEVEL, UCOL_HIRAGANA_QUATERNARY_MODE
+ & UCOL_DECOMPOSITION_MODE*/
+ UCOL_OFF = 16,
+ /** Turn the feature on - works for UCOL_FRENCH_COLLATION,
+ UCOL_CASE_LEVEL, UCOL_HIRAGANA_QUATERNARY_MODE
+ & UCOL_DECOMPOSITION_MODE*/
+ UCOL_ON = 17,
+
+ /** Valid for UCOL_ALTERNATE_HANDLING. Alternate handling will be shifted */
+ UCOL_SHIFTED = 20,
+ /** Valid for UCOL_ALTERNATE_HANDLING. Alternate handling will be non ignorable */
+ UCOL_NON_IGNORABLE = 21,
+
+ /** Valid for UCOL_CASE_FIRST -
+ lower case sorts before upper case */
+ UCOL_LOWER_FIRST = 24,
+ /** upper case sorts before lower case */
+ UCOL_UPPER_FIRST = 25,
+
+ UCOL_ATTRIBUTE_VALUE_COUNT
+
+} UColAttributeValue;
+
+/**
+ * Base letter represents a primary difference. Set comparison
+ * level to UCOL_PRIMARY to ignore secondary and tertiary differences.
+ * Use this to set the strength of a Collator object.
+ * Example of primary difference, "abc" < "abd"
+ *
+ * Diacritical differences on the same base letter represent a secondary
+ * difference. Set comparison level to UCOL_SECONDARY to ignore tertiary
+ * differences. Use this to set the strength of a Collator object.
+ * Example of secondary difference, "ä" >> "a".
+ *
+ * Uppercase and lowercase versions of the same character represents a
+ * tertiary difference. Set comparison level to UCOL_TERTIARY to include
+ * all comparison differences. Use this to set the strength of a Collator
+ * object.
+ * Example of tertiary difference, "abc" <<< "ABC".
+ *
+ * Two characters are considered "identical" when they have the same
+ * unicode spellings. UCOL_IDENTICAL.
+ * For example, "ä" == "ä".
+ *
+ * UCollationStrength is also used to determine the strength of sort keys
+ * generated from UCollator objects
+ * These values can be now found in the UColAttributeValue enum.
+ * @stable ICU 2.0
+ **/
+typedef UColAttributeValue UCollationStrength;
+
+/** Attributes that collation service understands. All the attributes can take UCOL_DEFAULT
+ * value, as well as the values specific to each one.
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** Attribute for direction of secondary weights - used in French.\
+ * Acceptable values are UCOL_ON, which results in secondary weights
+ * being considered backwards and UCOL_OFF which treats secondary
+ * weights in the order they appear.*/
+ UCOL_FRENCH_COLLATION,
+ /** Attribute for handling variable elements.\
+ * Acceptable values are UCOL_NON_IGNORABLE (default)
+ * which treats all the codepoints with non-ignorable
+ * primary weights in the same way,
+ * and UCOL_SHIFTED which causes codepoints with primary
+ * weights that are equal or below the variable top value
+ * to be ignored on primary level and moved to the quaternary
+ * level.*/
+ UCOL_ALTERNATE_HANDLING,
+ /** Controls the ordering of upper and lower case letters.\
+ * Acceptable values are UCOL_OFF (default), which orders
+ * upper and lower case letters in accordance to their tertiary
+ * weights, UCOL_UPPER_FIRST which forces upper case letters to
+ * sort before lower case letters, and UCOL_LOWER_FIRST which does
+ * the opposite. */
+ UCOL_CASE_FIRST,
+ /** Controls whether an extra case level (positioned before the third
+ * level) is generated or not.\ Acceptable values are UCOL_OFF (default),
+ * when case level is not generated, and UCOL_ON which causes the case
+ * level to be generated.\ Contents of the case level are affected by
+ * the value of UCOL_CASE_FIRST attribute.\ A simple way to ignore
+ * accent differences in a string is to set the strength to UCOL_PRIMARY
+ * and enable case level. */
+ UCOL_CASE_LEVEL,
+ /** Controls whether the normalization check and necessary normalizations
+ * are performed.\ When set to UCOL_OFF (default) no normalization check
+ * is performed.\ The correctness of the result is guaranteed only if the
+ * input data is in so-called FCD form (see users manual for more info).\
+ * When set to UCOL_ON, an incremental check is performed to see whether the input data
+ * is in the FCD form.\ If the data is not in the FCD form, incremental
+ * NFD normalization is performed. */
+ UCOL_NORMALIZATION_MODE,
+ /** An alias for UCOL_NORMALIZATION_MODE attribute */
+ UCOL_DECOMPOSITION_MODE = UCOL_NORMALIZATION_MODE,
+ /** The strength attribute.\ Can be either UCOL_PRIMARY, UCOL_SECONDARY,
+ * UCOL_TERTIARY, UCOL_QUATERNARY or UCOL_IDENTICAL.\ The usual strength
+ * for most locales (except Japanese) is tertiary.\ Quaternary strength
+ * is useful when combined with shifted setting for alternate handling
+ * attribute and for JIS x 4061 collation, when it is used to distinguish
+ * between Katakana and Hiragana (this is achieved by setting the
+ * UCOL_HIRAGANA_QUATERNARY mode to on.\ Otherwise, quaternary level
+ * is affected only by the number of non ignorable code points in
+ * the string.\ Identical strength is rarely useful, as it amounts
+ * to codepoints of the NFD form of the string. */
+ UCOL_STRENGTH,
+ /** when turned on, this attribute
+ * positions Hiragana before all
+ * non-ignorables on quaternary level
+ * This is a sneaky way to produce JIS
+ * sort order */
+ UCOL_HIRAGANA_QUATERNARY_MODE,
+ /** when turned on, this attribute
+ * generates a collation key
+ * for the numeric value of substrings
+ * of digits. This is a way to get '100'
+ * to sort AFTER '2'.*/
+ UCOL_NUMERIC_COLLATION,
+ UCOL_ATTRIBUTE_COUNT
+} UColAttribute;
+
+/** Options for retrieving the rule string
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** Retrieve tailoring only */
+ UCOL_TAILORING_ONLY,
+ /** Retrieve UCA rules and tailoring */
+ UCOL_FULL_RULES
+} UColRuleOption ;
+
+/**
+ * Open a UCollator for comparing strings.
+ * The UCollator pointer is used in all the calls to the Collation
+ * service. After finished, collator must be disposed of by calling
+ * {@link #ucol_close }.
+ * @param loc The locale containing the required collation rules.
+ * Special values for locales can be passed in -
+ * if NULL is passed for the locale, the default locale
+ * collation rules will be used. If empty string ("") or
+ * "root" are passed, UCA rules will be used.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UCollator, or 0 if an error occurred.
+ * @see ucol_openRules
+ * @see ucol_safeClone
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2
+ucol_open(const char *loc, UErrorCode *status);
+
+/**
+ * Produce an UCollator instance according to the rules supplied.
+ * The rules are used to change the default ordering, defined in the
+ * UCA in a process called tailoring. The resulting UCollator pointer
+ * can be used in the same way as the one obtained by {@link #ucol_strcoll }.
+ * @param rules A string describing the collation rules. For the syntax
+ * of the rules please see users guide.
+ * @param rulesLength The length of rules, or -1 if null-terminated.
+ * @param normalizationMode The normalization mode: One of
+ * UCOL_OFF (expect the text to not need normalization),
+ * UCOL_ON (normalize), or
+ * UCOL_DEFAULT (set the mode according to the rules)
+ * @param strength The default collation strength; one of UCOL_PRIMARY, UCOL_SECONDARY,
+ * UCOL_TERTIARY, UCOL_IDENTICAL,UCOL_DEFAULT_STRENGTH - can be also set in the rules.
+ * @param parseError A pointer to UParseError to recieve information about errors
+ * occurred during parsing. This argument can currently be set
+ * to NULL, but at users own risk. Please provide a real structure.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return A pointer to a UCollator.\ It is not guaranteed that NULL be returned in case
+ * of error - please use status argument to check for errors.
+ * @see ucol_open
+ * @see ucol_safeClone
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2
+ucol_openRules( const UChar *rules,
+ int32_t rulesLength,
+ UColAttributeValue normalizationMode,
+ UCollationStrength strength,
+ UParseError *parseError,
+ UErrorCode *status);
+
+/**
+ * Open a collator defined by a short form string.
+ * The structure and the syntax of the string is defined in the "Naming collators"
+ * section of the users guide:
+ * http://icu.sourceforge.net/icu/userguide/Collate_Concepts.html#Naming_Collators
+ * Attributes are overriden by the subsequent attributes. So, for "S2_S3", final
+ * strength will be 3. 3066bis locale overrides individual locale parts.
+ * The call to this function is equivalent to a call to ucol_open, followed by a
+ * series of calls to ucol_setAttribute and ucol_setVariableTop.
+ * @param definition A short string containing a locale and a set of attributes.
+ * Attributes not explicitly mentioned are left at the default
+ * state for a locale.
+ * @param parseError if not NULL, structure that will get filled with error's pre
+ * and post context in case of error.
+ * @param forceDefaults if FALSE, the settings that are the same as the collator
+ * default settings will not be applied (for example, setting
+ * French secondary on a French collator would not be executed).
+ * If TRUE, all the settings will be applied regardless of the
+ * collator default value. If the definition
+ * strings are to be cached, should be set to FALSE.
+ * @param status Error code. Apart from regular error conditions connected to
+ * instantiating collators (like out of memory or similar), this
+ * API will return an error if an invalid attribute or attribute/value
+ * combination is specified.
+ * @return A pointer to a UCollator or 0 if an error occured (including an
+ * invalid attribute).
+ * @see ucol_open
+ * @see ucol_setAttribute
+ * @see ucol_setVariableTop
+ * @see ucol_getShortDefinitionString
+ * @see ucol_normalizeShortDefinitionString
+ * @draft ICU 3.0
+ *
+ */
+U_CAPI UCollator* U_EXPORT2
+ucol_openFromShortString( const char *definition,
+ UBool forceDefaults,
+ UParseError *parseError,
+ UErrorCode *status);
+
+/**
+ * Get a set containing the contractions defined by the collator. The set includes
+ * both the UCA contractions and the contractions defined by the collator. This set
+ * will contain only strings. If a tailoring explicitly suppresses contractions from
+ * the UCA (like Russian), removed contractions will not be in the resulting set.
+ * @param coll collator
+ * @param conts the set to hold the result. It gets emptied before
+ * contractions are added.
+ * @param status to hold the error code
+ * @return the size of the contraction set
+ *
+ * @draft ICU 3.0
+ */
+U_CAPI int32_t U_EXPORT2
+ucol_getContractions( const UCollator *coll,
+ USet *conts,
+ UErrorCode *status);
+
+
+/**
+ * Close a UCollator.
+ * Once closed, a UCollator should not be used.\ Every open collator should
+ * be closed.\ Otherwise, a memory leak will result.
+ * @param coll The UCollator to close.
+ * @see ucol_open
+ * @see ucol_openRules
+ * @see ucol_safeClone
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_close(UCollator *coll);
+
+/**
+ * Compare two strings.
+ * The strings will be compared using the options already specified.
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return The result of comparing the strings; one of UCOL_EQUAL,
+ * UCOL_GREATER, UCOL_LESS
+ * @see ucol_greater
+ * @see ucol_greaterOrEqual
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UCollationResult U_EXPORT2
+ucol_strcoll( const UCollator *coll,
+ const UChar *source,
+ int32_t sourceLength,
+ const UChar *target,
+ int32_t targetLength);
+
+/**
+ * Determine if one string is greater than another.
+ * This function is equivalent to {@link #ucol_strcoll } == UCOL_GREATER
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is greater than target, FALSE otherwise.
+ * @see ucol_strcoll
+ * @see ucol_greaterOrEqual
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2
+ucol_greater(const UCollator *coll,
+ const UChar *source, int32_t sourceLength,
+ const UChar *target, int32_t targetLength);
+
+/**
+ * Determine if one string is greater than or equal to another.
+ * This function is equivalent to {@link #ucol_strcoll } != UCOL_LESS
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is greater than or equal to target, FALSE otherwise.
+ * @see ucol_strcoll
+ * @see ucol_greater
+ * @see ucol_equal
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2
+ucol_greaterOrEqual(const UCollator *coll,
+ const UChar *source, int32_t sourceLength,
+ const UChar *target, int32_t targetLength);
+
+/**
+ * Compare two strings for equality.
+ * This function is equivalent to {@link #ucol_strcoll } == UCOL_EQUAL
+ * @param coll The UCollator containing the comparison rules.
+ * @param source The source string.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param target The target string.
+ * @param targetLength The length of target, or -1 if null-terminated.
+ * @return TRUE if source is equal to target, FALSE otherwise
+ * @see ucol_strcoll
+ * @see ucol_greater
+ * @see ucol_greaterOrEqual
+ * @stable ICU 2.0
+ */
+U_STABLE UBool U_EXPORT2
+ucol_equal(const UCollator *coll,
+ const UChar *source, int32_t sourceLength,
+ const UChar *target, int32_t targetLength);
+
+/**
+ * Compare two UTF-8 encoded trings.
+ * The strings will be compared using the options already specified.
+ * @param coll The UCollator containing the comparison rules.
+ * @param sIter The source string iterator.
+ * @param tIter The target string iterator.
+ * @return The result of comparing the strings; one of UCOL_EQUAL,
+ * UCOL_GREATER, UCOL_LESS
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @see ucol_strcoll
+ * @stable ICU 2.6
+ */
+U_STABLE UCollationResult U_EXPORT2
+ucol_strcollIter( const UCollator *coll,
+ UCharIterator *sIter,
+ UCharIterator *tIter,
+ UErrorCode *status);
+
+/**
+ * Get the collation strength used in a UCollator.
+ * The strength influences how strings are compared.
+ * @param coll The UCollator to query.
+ * @return The collation strength; one of UCOL_PRIMARY, UCOL_SECONDARY,
+ * UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL
+ * @see ucol_setStrength
+ * @stable ICU 2.0
+ */
+U_STABLE UCollationStrength U_EXPORT2
+ucol_getStrength(const UCollator *coll);
+
+/**
+ * Set the collation strength used in a UCollator.
+ * The strength influences how strings are compared.
+ * @param coll The UCollator to set.
+ * @param strength The desired collation strength; one of UCOL_PRIMARY,
+ * UCOL_SECONDARY, UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL, UCOL_DEFAULT
+ * @see ucol_getStrength
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_setStrength(UCollator *coll,
+ UCollationStrength strength);
+
+/**
+ * Get the display name for a UCollator.
+ * The display name is suitable for presentation to a user.
+ * @param objLoc The locale of the collator in question.
+ * @param dispLoc The locale for display.
+ * @param result A pointer to a buffer to receive the attribute.
+ * @param resultLength The maximum size of result.
+ * @param status A pointer to an UErrorCode to receive any errors
+ * @return The total buffer size needed; if greater than resultLength,
+ * the output was truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_getDisplayName( const char *objLoc,
+ const char *dispLoc,
+ UChar *result,
+ int32_t resultLength,
+ UErrorCode *status);
+
+/**
+ * Get a locale for which collation rules are available.
+ * A UCollator in a locale returned by this function will perform the correct
+ * collation for the locale.
+ * @param index The index of the desired locale.
+ * @return A locale for which collation rules are available, or 0 if none.
+ * @see ucol_countAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2
+ucol_getAvailable(int32_t index);
+
+/**
+ * Determine how many locales have collation rules available.
+ * This function is most useful as determining the loop ending condition for
+ * calls to {@link #ucol_getAvailable }.
+ * @return The number of locales for which collation rules are available.
+ * @see ucol_getAvailable
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_countAvailable(void);
+
+#if !UCONFIG_NO_SERVICE
+/**
+ * Create a string enumerator of all locales for which a valid
+ * collator may be opened.
+ * @param status input-output error code
+ * @return a string enumeration over locale strings. The caller is
+ * responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_openAvailableLocales(UErrorCode *status);
+#endif
+
+/**
+ * Create a string enumerator of all possible keywords that are relevant to
+ * collation. At this point, the only recognized keyword for this
+ * service is "collation".
+ * @param status input-output error code
+ * @return a string enumeration over locale strings. The caller is
+ * responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_getKeywords(UErrorCode *status);
+
+/**
+ * Given a keyword, create a string enumeration of all values
+ * for that keyword that are currently in use.
+ * @param keyword a particular keyword as enumerated by
+ * ucol_getKeywords. If any other keyword is passed in, *status is set
+ * to U_ILLEGAL_ARGUMENT_ERROR.
+ * @param status input-output error code
+ * @return a string enumeration over collation keyword values, or NULL
+ * upon error. The caller is responsible for closing the result.
+ * @draft ICU 3.0
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+ucol_getKeywordValues(const char *keyword, UErrorCode *status);
+
+/**
+ * Return the functionally equivalent locale for the given
+ * requested locale, with respect to given keyword, for the
+ * collation service. If two locales return the same result, then
+ * collators instantiated for these locales will behave
+ * equivalently. The converse is not always true; two collators
+ * may in fact be equivalent, but return different results, due to
+ * internal details. The return result has no other meaning than
+ * that stated above, and implies nothing as to the relationship
+ * between the two locales. This is intended for use by
+ * applications who wish to cache collators, or otherwise reuse
+ * collators when possible. The functional equivalent may change
+ * over time. For more information, please see the <a
+ * href="http://icu.sourceforge.net/icu/userguide/locale.html#services">
+ * Locales and Services</a> section of the ICU User Guide.
+ * @param result fillin for the functionally equivalent locale
+ * @param resultCapacity capacity of the fillin buffer
+ * @param keyword a particular keyword as enumerated by
+ * ucol_getKeywords.
+ * @param locale the requested locale
+ * @param isAvailable if non-NULL, pointer to a fillin parameter that
+ * indicates whether the requested locale was 'available' to the
+ * collation service. A locale is defined as 'available' if it
+ * physically exists within the collation locale data.
+ * @param status pointer to input-output error code
+ * @return the actual buffer size needed for the locale. If greater
+ * than resultCapacity, the returned full name will be truncated and
+ * an error code will be returned.
+ * @draft ICU 3.0
+ */
+U_DRAFT int32_t U_EXPORT2
+ucol_getFunctionalEquivalent(char* result, int32_t resultCapacity,
+ const char* keyword, const char* locale,
+ UBool* isAvailable, UErrorCode* status);
+
+/**
+ * Get the collation rules from a UCollator.
+ * The rules will follow the rule syntax.
+ * @param coll The UCollator to query.
+ * @param length
+ * @return The collation rules.
+ * @stable ICU 2.0
+ */
+U_STABLE const UChar* U_EXPORT2
+ucol_getRules( const UCollator *coll,
+ int32_t *length);
+
+/** Get the short definition string for a collator. This API harvests the collator's
+ * locale and the attribute set and produces a string that can be used for opening
+ * a collator with the same properties using the ucol_openFromShortString API.
+ * This string will be normalized.
+ * The structure and the syntax of the string is defined in the "Naming collators"
+ * section of the users guide:
+ * http://icu.sourceforge.net/icu/userguide/Collate_Concepts.html#Naming_Collators
+ * This API supports preflighting.
+ * @param coll a collator
+ * @param locale a locale that will appear as a collators locale in the resulting
+ * short string definition. If NULL, the locale will be harvested
+ * from the collator.
+ * @param buffer space to hold the resulting string
+ * @param capacity capacity of the buffer
+ * @param status for returning errors. All the preflighting errors are featured
+ * @return length of the resulting string
+ * @see ucol_openFromShortString
+ * @see ucol_normalizeShortDefinitionString
+ * @draft ICU 3.0
+ */
+U_CAPI int32_t U_EXPORT2
+ucol_getShortDefinitionString(const UCollator *coll,
+ const char *locale,
+ char *buffer,
+ int32_t capacity,
+ UErrorCode *status);
+
+/** Verifies and normalizes short definition string.
+ * Normalized short definition string has all the option sorted by the argument name,
+ * so that equivalent definition strings are the same.
+ * This API supports preflighting.
+ * @param source definition string
+ * @param destination space to hold the resulting string
+ * @param capacity capacity of the buffer
+ * @param parseError if not NULL, structure that will get filled with error's pre
+ * and post context in case of error.
+ * @param status Error code. This API will return an error if an invalid attribute
+ * or attribute/value combination is specified. All the preflighting
+ * errors are also featured
+ * @return length of the resulting normalized string.
+ *
+ * @see ucol_openFromShortString
+ * @see ucol_getShortDefinitionString
+ *
+ * @draft ICU 3.0
+ */
+
+U_CAPI int32_t U_EXPORT2
+ucol_normalizeShortDefinitionString(const char *source,
+ char *destination,
+ int32_t capacity,
+ UParseError *parseError,
+ UErrorCode *status);
+
+
+/**
+ * Get a sort key for a string from a UCollator.
+ * Sort keys may be compared using <TT>strcmp</TT>.
+ * @param coll The UCollator containing the collation rules.
+ * @param source The string to transform.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * @param result A pointer to a buffer to receive the attribute.
+ * @param resultLength The maximum size of result.
+ * @return The size needed to fully store the sort key..
+ * @see ucol_keyHashCode
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_getSortKey(const UCollator *coll,
+ const UChar *source,
+ int32_t sourceLength,
+ uint8_t *result,
+ int32_t resultLength);
+
+
+/** Gets the next count bytes of a sort key. Caller needs
+ * to preserve state array between calls and to provide
+ * the same type of UCharIterator set with the same string.
+ * The destination buffer provided must be big enough to store
+ * the number of requested bytes. Generated sortkey is not
+ * compatible with sortkeys generated using ucol_getSortKey
+ * API, since we don't do any compression. If uncompressed
+ * sortkeys are required, this API can be used.
+ * @param coll The UCollator containing the collation rules.
+ * @param iter UCharIterator containing the string we need
+ * the sort key to be calculated for.
+ * @param state Opaque state of sortkey iteration.
+ * @param dest Buffer to hold the resulting sortkey part
+ * @param count number of sort key bytes required.
+ * @param status error code indicator.
+ * @return the actual number of bytes of a sortkey. It can be
+ * smaller than count if we have reached the end of
+ * the sort key.
+ * @stable ICU 2.6
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_nextSortKeyPart(const UCollator *coll,
+ UCharIterator *iter,
+ uint32_t state[2],
+ uint8_t *dest, int32_t count,
+ UErrorCode *status);
+
+/** enum that is taken by ucol_getBound API
+ * See below for explanation
+ * do not change the values assigned to the
+ * members of this enum. Underlying code
+ * depends on them having these numbers
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** lower bound */
+ UCOL_BOUND_LOWER = 0,
+ /** upper bound that will match strings of exact size */
+ UCOL_BOUND_UPPER = 1,
+ /** upper bound that will match all the strings that have the same initial substring as the given string */
+ UCOL_BOUND_UPPER_LONG = 2,
+ UCOL_BOUND_VALUE_COUNT
+} UColBoundMode;
+
+/**
+ * Produce a bound for a given sortkey and a number of levels.
+ * Return value is always the number of bytes needed, regardless of
+ * whether the result buffer was big enough or even valid.<br>
+ * Resulting bounds can be used to produce a range of strings that are
+ * between upper and lower bounds. For example, if bounds are produced
+ * for a sortkey of string "smith", strings between upper and lower
+ * bounds with one level would include "Smith", "SMITH", "sMiTh".<br>
+ * There are two upper bounds that can be produced. If UCOL_BOUND_UPPER
+ * is produced, strings matched would be as above. However, if bound
+ * produced using UCOL_BOUND_UPPER_LONG is used, the above example will
+ * also match "Smithsonian" and similar.<br>
+ * For more on usage, see example in cintltst/capitst.c in procedure
+ * TestBounds.
+ * Sort keys may be compared using <TT>strcmp</TT>.
+ * @param source The source sortkey.
+ * @param sourceLength The length of source, or -1 if null-terminated.
+ * (If an unmodified sortkey is passed, it is always null
+ * terminated).
+ * @param boundType Type of bound required. It can be UCOL_BOUND_LOWER, which
+ * produces a lower inclusive bound, UCOL_BOUND_UPPER, that
+ * produces upper bound that matches strings of the same length
+ * or UCOL_BOUND_UPPER_LONG that matches strings that have the
+ * same starting substring as the source string.
+ * @param noOfLevels Number of levels required in the resulting bound (for most
+ * uses, the recommended value is 1). See users guide for
+ * explanation on number of levels a sortkey can have.
+ * @param result A pointer to a buffer to receive the resulting sortkey.
+ * @param resultLength The maximum size of result.
+ * @param status Used for returning error code if something went wrong. If the
+ * number of levels requested is higher than the number of levels
+ * in the source key, a warning (U_SORT_KEY_TOO_SHORT_WARNING) is
+ * issued.
+ * @return The size needed to fully store the bound.
+ * @see ucol_keyHashCode
+ * @stable ICU 2.1
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_getBound(const uint8_t *source,
+ int32_t sourceLength,
+ UColBoundMode boundType,
+ uint32_t noOfLevels,
+ uint8_t *result,
+ int32_t resultLength,
+ UErrorCode *status);
+
+/**
+ * Gets the version information for a Collator. Version is currently
+ * an opaque 32-bit number which depends, among other things, on major
+ * versions of the collator tailoring and UCA.
+ * @param coll The UCollator to query.
+ * @param info the version # information, the result will be filled in
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_getVersion(const UCollator* coll, UVersionInfo info);
+
+/**
+ * Gets the UCA version information for a Collator. Version is the
+ * UCA version number (3.1.1, 4.0).
+ * @param coll The UCollator to query.
+ * @param info the version # information, the result will be filled in
+ * @draft ICU 2.8
+ */
+U_DRAFT void U_EXPORT2
+ucol_getUCAVersion(const UCollator* coll, UVersionInfo info);
+
+/**
+ * Merge two sort keys. The levels are merged with their corresponding counterparts
+ * (primaries with primaries, secondaries with secondaries etc.). Between the values
+ * from the same level a separator is inserted.
+ * example (uncompressed):
+ * 191B1D 01 050505 01 910505 00 and 1F2123 01 050505 01 910505 00
+ * will be merged as
+ * 191B1D 02 1F212301 050505 02 050505 01 910505 02 910505 00
+ * This allows for concatenating of first and last names for sorting, among other things.
+ * If the destination buffer is not big enough, the results are undefined.
+ * If any of source lengths are zero or any of source pointers are NULL/undefined,
+ * result is of size zero.
+ * @param src1 pointer to the first sortkey
+ * @param src1Length length of the first sortkey
+ * @param src2 pointer to the second sortkey
+ * @param src2Length length of the second sortkey
+ * @param dest buffer to hold the result
+ * @param destCapacity size of the buffer for the result
+ * @return size of the result. If the buffer is big enough size is always
+ * src1Length+src2Length-1
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_mergeSortkeys(const uint8_t *src1, int32_t src1Length,
+ const uint8_t *src2, int32_t src2Length,
+ uint8_t *dest, int32_t destCapacity);
+
+/**
+ * Universal attribute setter
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type
+ * @param value attribute value
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_getAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_setAttribute(UCollator *coll, UColAttribute attr, UColAttributeValue value, UErrorCode *status);
+
+/**
+ * Universal attribute getter
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type
+ * @return attribute value
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_setAttribute
+ * @stable ICU 2.0
+ */
+U_STABLE UColAttributeValue U_EXPORT2
+ucol_getAttribute(const UCollator *coll, UColAttribute attr, UErrorCode *status);
+
+/** Variable top
+ * is a two byte primary value which causes all the codepoints with primary values that
+ * are less or equal than the variable top to be shifted when alternate handling is set
+ * to UCOL_SHIFTED.
+ * Sets the variable top to a collation element value of a string supplied.
+ * @param coll collator which variable top needs to be changed
+ * @param varTop one or more (if contraction) UChars to which the variable top should be set
+ * @param len length of variable top string. If -1 it is considered to be zero terminated.
+ * @param status error code. If error code is set, the return value is undefined.
+ * Errors set by this function are: <br>
+ * U_CE_NOT_FOUND_ERROR if more than one character was passed and there is no such
+ * a contraction<br>
+ * U_PRIMARY_TOO_LONG_ERROR if the primary for the variable top has more than two bytes
+ * @return a 32 bit value containing the value of the variable top in upper 16 bits.
+ * Lower 16 bits are undefined
+ * @see ucol_getVariableTop
+ * @see ucol_restoreVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE uint32_t U_EXPORT2
+ucol_setVariableTop(UCollator *coll,
+ const UChar *varTop, int32_t len,
+ UErrorCode *status);
+
+/**
+ * Gets the variable top value of a Collator.
+ * Lower 16 bits are undefined and should be ignored.
+ * @param coll collator which variable top needs to be retrieved
+ * @param status error code (not changed by function). If error code is set,
+ * the return value is undefined.
+ * @return the variable top value of a Collator.
+ * @see ucol_setVariableTop
+ * @see ucol_restoreVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCode *status);
+
+/**
+ * Sets the variable top to a collation element value supplied. Variable top is
+ * set to the upper 16 bits.
+ * Lower 16 bits are ignored.
+ * @param coll collator which variable top needs to be changed
+ * @param varTop CE value, as returned by ucol_setVariableTop or ucol)getVariableTop
+ * @param status error code (not changed by function)
+ * @see ucol_getVariableTop
+ * @see ucol_setVariableTop
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *status);
+
+/**
+ * Thread safe cloning operation. The result is a clone of a given collator.
+ * @param coll collator to be cloned
+ * @param stackBuffer user allocated space for the new clone.
+ * If NULL new memory will be allocated.
+ * If buffer is not large enough, new memory will be allocated.
+ * Clients can use the U_COL_SAFECLONE_BUFFERSIZE.
+ * This will probably be enough to avoid memory allocations.
+ * @param pBufferSize pointer to size of allocated space.
+ * If *pBufferSize == 0, a sufficient size for use in cloning will
+ * be returned ('pre-flighting')
+ * If *pBufferSize is not enough for a stack-based safe clone,
+ * new memory will be allocated.
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any
+ * allocations were necessary.
+ * @return pointer to the new clone
+ * @see ucol_open
+ * @see ucol_openRules
+ * @see ucol_close
+ * @stable ICU 2.0
+ */
+U_STABLE UCollator* U_EXPORT2
+ucol_safeClone(const UCollator *coll,
+ void *stackBuffer,
+ int32_t *pBufferSize,
+ UErrorCode *status);
+
+/** default memory size for the new clone. It needs to be this large for os/400 large pointers
+ * @stable ICU 2.0
+ */
+#define U_COL_SAFECLONE_BUFFERSIZE 512
+
+/**
+ * Returns current rules. Delta defines whether full rules are returned or just the tailoring.
+ * Returns number of UChars needed to store rules. If buffer is NULL or bufferLen is not enough
+ * to store rules, will store up to available space.
+ * @param coll collator to get the rules from
+ * @param delta one of UCOL_TAILORING_ONLY, UCOL_FULL_RULES.
+ * @param buffer buffer to store the result in. If NULL, you'll get no rules.
+ * @param bufferLen lenght of buffer to store rules in. If less then needed you'll get only the part that fits in.
+ * @return current rules
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+ucol_getRulesEx(const UCollator *coll, UColRuleOption delta, UChar *buffer, int32_t bufferLen);
+
+/**
+ * gets the locale name of the collator. If the collator
+ * is instantiated from the rules, then this function returns
+ * NULL.
+ * @param coll The UCollator for which the locale is needed
+ * @param type You can choose between requested, valid and actual
+ * locale. For description see the definition of
+ * ULocDataLocaleType in uloc.h
+ * @param status error code of the operation
+ * @return real locale name from which the collation data comes.
+ * If the collator was instantiated from rules, returns
+ * NULL.
+ * @deprecated ICU 2.8 Use ucol_getLocaleByType instead
+ */
+U_DEPRECATED const char * U_EXPORT2
+ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status);
+
+
+/**
+ * gets the locale name of the collator. If the collator
+ * is instantiated from the rules, then this function returns
+ * NULL.
+ * @param coll The UCollator for which the locale is needed
+ * @param type You can choose between requested, valid and actual
+ * locale. For description see the definition of
+ * ULocDataLocaleType in uloc.h
+ * @param status error code of the operation
+ * @return real locale name from which the collation data comes.
+ * If the collator was instantiated from rules, returns
+ * NULL.
+ * @draft ICU 2.8 likely to change in ICU 3.0, based on feedback
+ */
+U_DRAFT const char * U_EXPORT2
+ucol_getLocaleByType(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status);
+
+/**
+ * Get an Unicode set that contains all the characters and sequences tailored in
+ * this collator. The result must be disposed of by using uset_close.
+ * @param coll The UCollator for which we want to get tailored chars
+ * @param status error code of the operation
+ * @return a pointer to newly created USet. Must be be disposed by using uset_close
+ * @see ucol_openRules
+ * @see uset_close
+ * @stable ICU 2.4
+ */
+U_STABLE USet * U_EXPORT2
+ucol_getTailoredSet(const UCollator *coll, UErrorCode *status);
+
+/**
+ * Returned by ucol_collatorToIdentifier to signify that collator is
+ * not encodable as an identifier.
+ * @internal ICU 3.0
+ */
+#define UCOL_SIT_COLLATOR_NOT_ENCODABLE 0x80000000
+
+/**
+ * Get a 31-bit identifier given a collator.
+ * @param coll UCollator
+ * @param locale a locale that will appear as a collators locale in the resulting
+ * short string definition. If NULL, the locale will be harvested
+ * from the collator.
+ * @param status holds error messages
+ * @return 31-bit identifier. MSB is used if the collator cannot be encoded. In that
+ * case UCOL_SIT_COLLATOR_NOT_ENCODABLE is returned
+ * @see ucol_openFromIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL uint32_t U_EXPORT2
+ucol_collatorToIdentifier(const UCollator *coll,
+ const char *locale,
+ UErrorCode *status);
+
+/**
+ * Open a collator given a 31-bit identifier
+ * @param identifier 31-bit identifier, encoded by calling ucol_collatorToIdentifier
+ * @param forceDefaults if FALSE, the settings that are the same as the collator
+ * default settings will not be applied (for example, setting
+ * French secondary on a French collator would not be executed).
+ * If TRUE, all the settings will be applied regardless of the
+ * collator default value. If the definition
+ * strings that can be produced from a collator instantiated by
+ * calling this API are to be cached, should be set to FALSE.
+ * @param status for returning errors
+ * @return UCollator object
+ * @see ucol_collatorToIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL UCollator* U_EXPORT2
+ucol_openFromIdentifier(uint32_t identifier,
+ UBool forceDefaults,
+ UErrorCode *status);
+
+
+/**
+ * Calculate the short definition string given an identifier. Supports preflighting.
+ * @param identifier 31-bit identifier, encoded by calling ucol_collatorToIdentifier
+ * @param buffer buffer to store the result
+ * @param capacity buffer capacity
+ * @param forceDefaults whether the settings that are the same as the default setting
+ * should be forced anyway. Setting this argument to FALSE reduces
+ * the number of different configurations, but decreases performace
+ * as a collator has to be instantiated.
+ * @param status for returning errors
+ * @return length of the short definition string
+ * @see ucol_collatorToIdentifier
+ * @see ucol_openFromIdentifier
+ * @see ucol_shortStringToIdentifier
+ * @internal ICU 3.0
+ */
+U_INTERNAL int32_t U_EXPORT2
+ucol_identifierToShortString(uint32_t identifier,
+ char *buffer,
+ int32_t capacity,
+ UBool forceDefaults,
+ UErrorCode *status);
+
+/**
+ * Calculate the identifier given a short definition string. Supports preflighting.
+ * @param definition short string definition
+ * @param forceDefaults whether the settings that are the same as the default setting
+ * should be forced anyway. Setting this argument to FALSE reduces
+ * the number of different configurations, but decreases performace
+ * as a collator has to be instantiated.
+ * @param status for returning errors
+ * @return identifier
+ * @see ucol_collatorToIdentifier
+ * @see ucol_openFromIdentifier
+ * @see ucol_identifierToShortString
+ * @internal ICU 3.0
+ */
+U_INTERNAL uint32_t U_EXPORT2
+ucol_shortStringToIdentifier(const char *definition,
+ UBool forceDefaults,
+ UErrorCode *status);
+
+
+
+/**
+ * Universal attribute getter that returns UCOL_DEFAULT if the value is default
+ * @param coll collator which attributes are to be changed
+ * @param attr attribute type
+ * @return attribute value or UCOL_DEFAULT if the value is default
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @see UColAttribute
+ * @see UColAttributeValue
+ * @see ucol_setAttribute
+ * @internal ICU 3.0
+ */
+U_INTERNAL UColAttributeValue U_EXPORT2
+ucol_getAttributeOrDefault(const UCollator *coll, UColAttribute attr, UErrorCode *status);
+
+/** Check whether two collators are equal. Collators are considered equal if they
+ * will sort strings the same. This means that both the current attributes and the
+ * rules must be equivalent. Currently used for RuleBasedCollator::operator==.
+ * @param source first collator
+ * @param target second collator
+ * @return TRUE or FALSE
+ * @internal ICU 3.0
+ */
+U_INTERNAL UBool U_EXPORT2
+ucol_equals(const UCollator *source, const UCollator *target);
+
+/** Calculates the set of unsafe code points, given a collator.
+ * A character is unsafe if you could append any character and cause the ordering to alter significantly.
+ * Collation sorts in normalized order, so anything that rearranges in normalization can cause this.
+ * Thus if you have a character like a_umlaut, and you add a lower_dot to it,
+ * then it normalizes to a_lower_dot + umlaut, and sorts differently.
+ * @param coll Collator
+ * @param unsafe a fill-in set to receive the unsafe points
+ * @param status for catching errors
+ * @return number of elements in the set
+ * @internal ICU 3.0
+ */
+U_INTERNAL int32_t U_EXPORT2
+ucol_getUnsafeSet( const UCollator *coll,
+ USet *unsafe,
+ UErrorCode *status);
+
+/** Reset UCA's static pointers. You don't want to use this, unless your static memory can go away.
+ * @internal ICU 3.2.1
+ */
+U_INTERNAL void U_EXPORT2
+ucol_forgetUCA(void);
+
+/** Touches all resources needed for instantiating a collator from a short string definition,
+ * thus filling up the cache.
+ * @param definition A short string containing a locale and a set of attributes.
+ * Attributes not explicitly mentioned are left at the default
+ * state for a locale.
+ * @param parseError if not NULL, structure that will get filled with error's pre
+ * and post context in case of error.
+ * @param forceDefaults if FALSE, the settings that are the same as the collator
+ * default settings will not be applied (for example, setting
+ * French secondary on a French collator would not be executed).
+ * If TRUE, all the settings will be applied regardless of the
+ * collator default value. If the definition
+ * strings are to be cached, should be set to FALSE.
+ * @param status Error code. Apart from regular error conditions connected to
+ * instantiating collators (like out of memory or similar), this
+ * API will return an error if an invalid attribute or attribute/value
+ * combination is specified.
+ * @see ucol_openFromShortString
+ * @internal ICU 3.2.1
+ */
+U_INTERNAL void U_EXPORT2
+ucol_prepareShortStringOpen( const char *definition,
+ UBool forceDefaults,
+ UParseError *parseError,
+ UErrorCode *status);
+
+/** Creates a binary image of a collator. This binary image can be stored and
+ * later used to instantiate a collator using ucol_openBinary.
+ * This API supports preflighting.
+ * @param coll Collator
+ * @param buffer a fill-in buffer to receive the binary image
+ * @param capacity capacity of the destination buffer
+ * @param status for catching errors
+ * @return size of the image
+ * @see ucol_openBinary
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+ucol_cloneBinary(const UCollator *coll,
+ uint8_t *buffer, int32_t capacity,
+ UErrorCode *status);
+
+/** Opens a collator from a collator binary image created using
+ * ucol_cloneBinary. Binary image used in instantiation of the
+ * collator remains owned by the user and should stay around for
+ * the lifetime of the collator. The API also takes a base collator
+ * which usualy should be UCA.
+ * @param bin binary image owned by the user and required through the
+ * lifetime of the collator
+ * @param length size of the image. If negative, the API will try to
+ * figure out the length of the image
+ * @param base fallback collator, usually UCA. Base is required to be
+ * present through the lifetime of the collator. Currently
+ * it cannot be NULL.
+ * @param status for catching errors
+ * @return newly created collator
+ * @see ucol_cloneBinary
+ * @draft ICU 3.2
+ */
+U_DRAFT UCollator* U_EXPORT2
+ucol_openBinary(const uint8_t *bin, int32_t length,
+ const UCollator *base,
+ UErrorCode *status);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
+
--- /dev/null
+/*
+**********************************************************************
+* Copyright (C) 1997-2004, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*
+* File ULOC.H
+*
+* Modification History:
+*
+* Date Name Description
+* 04/01/97 aliu Creation.
+* 08/22/98 stephen JDK 1.2 sync.
+* 12/08/98 rtg New C API for Locale
+* 03/30/99 damiba overhaul
+* 03/31/99 helena Javadoc for uloc functions.
+* 04/15/99 Madhu Updated Javadoc
+********************************************************************************
+*/
+
+#ifndef ULOC_H
+#define ULOC_H
+
+#include "unicode/utypes.h"
+#include "unicode/uenum.h"
+
+/**
+ * \file
+ * \brief C API: Locale
+ *
+ * <h2> ULoc C API for Locale </h2>
+ * A <code>Locale</code> represents a specific geographical, political,
+ * or cultural region. An operation that requires a <code>Locale</code> to perform
+ * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
+ * to tailor information for the user. For example, displaying a number
+ * is a locale-sensitive operation--the number should be formatted
+ * according to the customs/conventions of the user's native country,
+ * region, or culture. In the C APIs, a locales is simply a const char string.
+ *
+ * <P>
+ * You create a <code>Locale</code> with one of the three options listed below.
+ * Each of the component is separated by '_' in the locale string.
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * newLanguage
+ *
+ * newLanguage + newCountry
+ *
+ * newLanguage + newCountry + newVariant
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ * The first option is a valid <STRONG>ISO
+ * Language Code.</STRONG> These codes are the lower-case two-letter
+ * codes as defined by ISO-639.
+ * You can find a full list of these codes at a number of sites, such as:
+ * <BR><a href ="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
+ * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt</a>
+ *
+ * <P>
+ * The second option includes an additonal <STRONG>ISO Country
+ * Code.</STRONG> These codes are the upper-case two-letter codes
+ * as defined by ISO-3166.
+ * You can find a full list of these codes at a number of sites, such as:
+ * <BR><a href="http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html">
+ * http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html</a>
+ *
+ * <P>
+ * The third option requires another additonal information--the
+ * <STRONG>Variant.</STRONG>
+ * The Variant codes are vendor and browser-specific.
+ * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX.
+ * Where there are two variants, separate them with an underscore, and
+ * put the most important one first. For
+ * example, a Traditional Spanish collation might be referenced, with
+ * "ES", "ES", "Traditional_WIN".
+ *
+ * <P>
+ * Because a <code>Locale</code> is just an identifier for a region,
+ * no validity check is performed when you specify a <code>Locale</code>.
+ * If you want to see whether particular resources are available for the
+ * <code>Locale</code> you asked for, you must query those resources. For
+ * example, ask the <code>UNumberFormat</code> for the locales it supports
+ * using its <code>getAvailable</code> method.
+ * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular
+ * locale, you get back the best available match, not necessarily
+ * precisely what you asked for. For more information, look at
+ * <code>UResourceBundle</code>.
+ *
+ * <P>
+ * The <code>Locale</code> provides a number of convenient constants
+ * that you can use to specify the commonly used
+ * locales. For example, the following refers to a locale
+ * for the United States:
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * ULOC_US
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ *
+ * <P>
+ * Once you've specified a locale you can query it for information about
+ * itself. Use <code>uloc_getCountry</code> to get the ISO Country Code and
+ * <code>uloc_getLanguage</code> to get the ISO Language Code. You can
+ * use <code>uloc_getDisplayCountry</code> to get the
+ * name of the country suitable for displaying to the user. Similarly,
+ * you can use <code>uloc_getDisplayLanguage</code> to get the name of
+ * the language suitable for displaying to the user. Interestingly,
+ * the <code>uloc_getDisplayXXX</code> methods are themselves locale-sensitive
+ * and have two versions: one that uses the default locale and one
+ * that takes a locale as an argument and displays the name or country in
+ * a language appropriate to that locale.
+ *
+ * <P>
+ * The ICU provides a number of services that perform locale-sensitive
+ * operations. For example, the <code>unum_xxx</code> functions format
+ * numbers, currency, or percentages in a locale-sensitive manner.
+ * </P>
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * UErrorCode success = U_ZERO_ERROR;
+ * UNumberFormat *nf;
+ * const char* myLocale = "fr_FR";
+ *
+ * nf = unum_open( UNUM_DEFAULT, NULL, success );
+ * unum_close(nf);
+ * nf = unum_open( UNUM_CURRENCY, NULL, success );
+ * unum_close(nf);
+ * nf = unum_open( UNUM_PERCENT, NULL, success );
+ * unum_close(nf);
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ * Each of these methods has two variants; one with an explicit locale
+ * and one without; the latter using the default locale.
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ *
+ * nf = unum_open( UNUM_DEFAULT, myLocale, success );
+ * unum_close(nf);
+ * nf = unum_open( UNUM_CURRENCY, myLocale, success );
+ * unum_close(nf);
+ * nf = unum_open( UNUM_PERCENT, myLocale, success );
+ * unum_close(nf);
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ * A <code>Locale</code> is the mechanism for identifying the kind of services
+ * (<code>UNumberFormat</code>) that you would like to get. The locale is
+ * <STRONG>just</STRONG> a mechanism for identifying these services.
+ *
+ * <P>
+ * Each international serivce that performs locale-sensitive operations
+ * allows you
+ * to get all the available objects of that type. You can sift
+ * through these objects by language, country, or variant,
+ * and use the display names to present a menu to the user.
+ * For example, you can create a menu of all the collation objects
+ * suitable for a given language. Such classes implement these
+ * three class methods:
+ * \htmlonly<blockquote>\endhtmlonly
+ * <pre>
+ * \code
+ * const char* uloc_getAvailable(int32_t index);
+ * int32_t uloc_countAvailable();
+ * int32_t
+ * uloc_getDisplayName(const char* localeID,
+ * const char* inLocaleID,
+ * UChar* result,
+ * int32_t maxResultSize,
+ * UErrorCode* err);
+ *
+ * \endcode
+ * </pre>
+ * \htmlonly</blockquote>\endhtmlonly
+ * <P>
+ * Concerning POSIX/RFC1766 Locale IDs,
+ * the getLanguage/getCountry/getVariant/getName functions do understand
+ * the POSIX type form of language_COUNTRY.ENCODING\@VARIANT
+ * and if there is not an ICU-stype variant, uloc_getVariant() for example
+ * will return the one listed after the \@at sign. As well, the hyphen
+ * "-" is recognized as a country/variant separator similarly to RFC1766.
+ * So for example, "en-us" will be interpreted as en_US.
+ * As a result, uloc_getName() is far from a no-op, and will have the
+ * effect of converting POSIX/RFC1766 IDs into ICU form, although it does
+ * NOT map any of the actual codes (i.e. russian->ru) in any way.
+ * Applications should call uloc_getName() at the point where a locale ID
+ * is coming from an external source (user entry, OS, web browser)
+ * and pass the resulting string to other ICU functions. For example,
+ * don't use de-de\@EURO as an argument to resourcebundle.
+ *
+ * @see UResourceBundle
+ */
+
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_CHINESE "zh"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_ENGLISH "en"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_FRENCH "fr"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_GERMAN "de"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_ITALIAN "it"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_JAPANESE "ja"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_KOREAN "ko"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_SIMPLIFIED_CHINESE "zh_CN"
+/** Useful constant for this language. @stable ICU 2.0 */
+#define ULOC_TRADITIONAL_CHINESE "zh_TW"
+
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_CANADA "en_CA"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_CANADA_FRENCH "fr_CA"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_CHINA "zh_CN"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_PRC "zh_CN"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_FRANCE "fr_FR"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_GERMANY "de_DE"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_ITALY "it_IT"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_JAPAN "ja_JP"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_KOREA "ko_KR"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_TAIWAN "zh_TW"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_UK "en_GB"
+/** Useful constant for this country/region. @stable ICU 2.0 */
+#define ULOC_US "en_US"
+
+/**
+ * Useful constant for the maximum size of the language part of a locale ID.
+ * (including the terminating NULL).
+ * @stable ICU 2.0
+ */
+#define ULOC_LANG_CAPACITY 12
+
+/**
+ * Useful constant for the maximum size of the country part of a locale ID
+ * (including the terminating NULL).
+ * @stable ICU 2.0
+ */
+#define ULOC_COUNTRY_CAPACITY 4
+/**
+ * Useful constant for the maximum size of the whole locale ID
+ * (including the terminating NULL).
+ * @stable ICU 2.0
+ */
+#define ULOC_FULLNAME_CAPACITY 56
+
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Useful constant for the maximum size of the script part of a locale ID
+ * (including the terminating NULL).
+ * @draft ICU 2.8
+ */
+#define ULOC_SCRIPT_CAPACITY 6
+
+/**
+ * Useful constant for the maximum size of keywords in a locale
+ * @draft ICU 2.8
+ */
+#define ULOC_KEYWORDS_CAPACITY 50
+
+/**
+ * Useful constant for the maximum size of keywords in a locale
+ * @draft ICU 2.8
+ */
+#define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
+
+/**
+ * Character separating keywords from the locale string
+ * different for EBCDIC - TODO
+ * @draft ICU 2.8
+ */
+#define ULOC_KEYWORD_SEPARATOR '@'
+/**
+ * Character for assigning value to a keyword
+ * @draft ICU 2.8
+ */
+#define ULOC_KEYWORD_ASSIGN '='
+/**
+ * Character separating keywords
+ * @draft ICU 2.8
+ */
+#define ULOC_KEYWORD_ITEM_SEPARATOR ';'
+
+#endif /*U_HIDE_DRAFT_API*/
+
+/**
+ * Constants for *_getLocale()
+ * Allow user to select whether she wants information on
+ * requested, valid or actual locale.
+ * For example, a collator for "en_US_CALIFORNIA" was
+ * requested. In the current state of ICU (2.0),
+ * the requested locale is "en_US_CALIFORNIA",
+ * the valid locale is "en_US" (most specific locale supported by ICU)
+ * and the actual locale is "root" (the collation data comes unmodified
+ * from the UCA)
+ * The locale is considered supported by ICU if there is a core ICU bundle
+ * for that locale (although it may be empty).
+ * @stable ICU 2.1
+ */
+typedef enum {
+ /** This is locale the data actually comes from
+ * @stable ICU 2.1
+ */
+ ULOC_ACTUAL_LOCALE = 0,
+ /** This is the most specific locale supported by ICU
+ * @stable ICU 2.1
+ */
+ ULOC_VALID_LOCALE = 1,
+
+#ifndef U_HIDE_DEPRECATED_API
+ /** This is the requested locale
+ * @deprecated ICU 2.8
+ */
+ ULOC_REQUESTED_LOCALE = 2,
+#endif /* U_HIDE_DEPRECATED_API */
+
+ ULOC_DATA_LOCALE_TYPE_LIMIT
+} ULocDataLocaleType ;
+
+
+/**
+ * Gets ICU's default locale.
+ * The returned string is a snapshot in time, and will remain valid
+ * and unchanged even when uloc_setDefault() is called.
+ * The returned storage is owned by ICU, and must not be altered or deleted
+ * by the caller.
+ *
+ * @return the ICU default locale
+ * @system
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2
+uloc_getDefault(void);
+
+/**
+ * Sets ICU's default locale.
+ * By default (without calling this function), ICU's default locale will be based
+ * on information obtained from the underlying system environment.
+ * <p>
+ * Changes to ICU's default locale do not propagate back to the
+ * system environment.
+ * <p>
+ * Changes to ICU's default locale to not affect any ICU services that
+ * may already be open based on the previous default locale value.
+ *
+ * @param localeID the new ICU default locale. A value of NULL will try to get
+ * the system's default locale.
+ * @param status the error information if the setting of default locale fails
+ * @system
+ * @stable ICU 2.0
+ */
+U_STABLE void U_EXPORT2
+uloc_setDefault(const char* localeID,
+ UErrorCode* status);
+
+/**
+ * Gets the language code for the specified locale.
+ *
+ * @param localeID the locale to get the ISO language code with
+ * @param language the language code for localeID
+ * @param languageCapacity the size of the language buffer to store the
+ * language code with
+ * @param err error information if retrieving the language code failed
+ * @return the actual buffer size needed for the language code. If it's greater
+ * than languageCapacity, the returned language code will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getLanguage(const char* localeID,
+ char* language,
+ int32_t languageCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets the script code for the specified locale.
+ *
+ * @param localeID the locale to get the ISO language code with
+ * @param script the language code for localeID
+ * @param scriptCapacity the size of the language buffer to store the
+ * language code with
+ * @param err error information if retrieving the language code failed
+ * @return the actual buffer size needed for the language code. If it's greater
+ * than scriptCapacity, the returned language code will be truncated.
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getScript(const char* localeID,
+ char* script,
+ int32_t scriptCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets the country code for the specified locale.
+ *
+ * @param localeID the locale to get the country code with
+ * @param country the country code for localeID
+ * @param countryCapacity the size of the country buffer to store the
+ * country code with
+ * @param err error information if retrieving the country code failed
+ * @return the actual buffer size needed for the country code. If it's greater
+ * than countryCapacity, the returned country code will be truncated.
+ * @stable ICU 2.0
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getCountry(const char* localeID,
+ char* country,
+ int32_t countryCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets the variant code for the specified locale.
+ *
+ * @param localeID the locale to get the variant code with
+ * @param variant the variant code for localeID
+ * @param variantCapacity the size of the variant buffer to store the
+ * variant code with
+ * @param err error information if retrieving the variant code failed
+ * @return the actual buffer size needed for the variant code. If it's greater
+ * than variantCapacity, the returned variant code will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getVariant(const char* localeID,
+ char* variant,
+ int32_t variantCapacity,
+ UErrorCode* err);
+
+
+/**
+ * Gets the full name for the specified locale.
+ * Note: This has the effect of 'canonicalizing' the ICU locale ID to
+ * a certain extent. Upper and lower case are set as needed.
+ * It does NOT map aliased names in any way.
+ * See the top of this header file.
+ * This API supports preflighting.
+ *
+ * @param localeID the locale to get the full name with
+ * @param name fill in buffer for the name without keywords.
+ * @param nameCapacity capacity of the fill in buffer.
+ * @param err error information if retrieving the full name failed
+ * @return the actual buffer size needed for the full name. If it's greater
+ * than nameCapacity, the returned full name will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getName(const char* localeID,
+ char* name,
+ int32_t nameCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets the full name for the specified locale.
+ * Note: This has the effect of 'canonicalizing' the string to
+ * a certain extent. Upper and lower case are set as needed,
+ * and if the components were in 'POSIX' format they are changed to
+ * ICU format. It does NOT map aliased names in any way.
+ * See the top of this header file.
+ *
+ * @param localeID the locale to get the full name with
+ * @param name the full name for localeID
+ * @param nameCapacity the size of the name buffer to store the
+ * full name with
+ * @param err error information if retrieving the full name failed
+ * @return the actual buffer size needed for the full name. If it's greater
+ * than nameCapacity, the returned full name will be truncated.
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_canonicalize(const char* localeID,
+ char* name,
+ int32_t nameCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets the ISO language code for the specified locale.
+ *
+ * @param localeID the locale to get the ISO language code with
+ * @return language the ISO language code for localeID
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2
+uloc_getISO3Language(const char* localeID);
+
+
+/**
+ * Gets the ISO country code for the specified locale.
+ *
+ * @param localeID the locale to get the ISO country code with
+ * @return country the ISO country code for localeID
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2
+uloc_getISO3Country(const char* localeID);
+
+/**
+ * Gets the Win32 LCID value for the specified locale.
+ * If the ICU locale is not recognized by Windows, 0 will be returned.
+ *
+ * @param localeID the locale to get the Win32 LCID value with
+ * @return country the Win32 LCID for localeID
+ * @stable ICU 2.0
+ */
+U_STABLE uint32_t U_EXPORT2
+uloc_getLCID(const char* localeID);
+
+/**
+ * Gets the language name suitable for display for the specified locale.
+ *
+ * @param locale the locale to get the ISO language code with
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch".
+ * @param language the displayable language code for localeID
+ * @param languageCapacity the size of the language buffer to store the
+ * displayable language code with
+ * @param status error information if retrieving the displayable language code failed
+ * @return the actual buffer size needed for the displayable language code. If it's greater
+ * than languageCapacity, the returned language code will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getDisplayLanguage(const char* locale,
+ const char* displayLocale,
+ UChar* language,
+ int32_t languageCapacity,
+ UErrorCode* status);
+
+/**
+ * Gets the script name suitable for display for the specified locale.
+ *
+ * @param locale the locale to get the displayable script code with. NULL may be used to specify the default.
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "", while passing Locale::getGerman()
+ * for inLocale would result in "". NULL may be used to specify the default.
+ * @param script the displayable country code for localeID
+ * @param scriptCapacity the size of the script buffer to store the
+ * displayable script code with
+ * @param status error information if retrieving the displayable script code failed
+ * @return the actual buffer size needed for the displayable script code. If it's greater
+ * than scriptCapacity, the returned displayable script code will be truncated.
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getDisplayScript(const char* locale,
+ const char* displayLocale,
+ UChar* script,
+ int32_t scriptCapacity,
+ UErrorCode* status);
+
+/**
+ * Gets the country name suitable for display for the specified locale.
+ *
+ * @param locale the locale to get the displayable country code with. NULL may be used to specify the default.
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch". NULL may be used to specify the default.
+ * @param country the displayable country code for localeID
+ * @param countryCapacity the size of the country buffer to store the
+ * displayable country code with
+ * @param status error information if retrieving the displayable country code failed
+ * @return the actual buffer size needed for the displayable country code. If it's greater
+ * than countryCapacity, the returned displayable country code will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getDisplayCountry(const char* locale,
+ const char* displayLocale,
+ UChar* country,
+ int32_t countryCapacity,
+ UErrorCode* status);
+
+
+/**
+ * Gets the variant name suitable for display for the specified locale.
+ *
+ * @param locale the locale to get the displayable variant code with. NULL may be used to specify the default.
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch". NULL may be used to specify the default.
+ * @param variant the displayable variant code for localeID
+ * @param variantCapacity the size of the variant buffer to store the
+ * displayable variant code with
+ * @param status error information if retrieving the displayable variant code failed
+ * @return the actual buffer size needed for the displayable variant code. If it's greater
+ * than variantCapacity, the returned displayable variant code will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getDisplayVariant(const char* locale,
+ const char* displayLocale,
+ UChar* variant,
+ int32_t variantCapacity,
+ UErrorCode* status);
+
+/**
+ * Gets the keyword name suitable for display for the specified locale.
+ * E.g: for the locale string de_DE\@collation=PHONEBOOK, this API gets the display
+ * string for the keyword collation.
+ * Usage:
+ * <code>
+ * UErrorCode status = U_ZERO_ERROR;
+ * const char* keyword =NULL;
+ * int32_t keywordLen = 0;
+ * int32_t keywordCount = 0;
+ * UChar displayKeyword[256];
+ * int32_t displayKeywordLen = 0;
+ * UEnumeration* keywordEnum = uloc_openKeywords("de_DE@collation=PHONEBOOK;calendar=TRADITIONAL", &status);
+ * for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
+ * if(U_FAILURE(status)){
+ * ...something went wrong so handle the error...
+ * break;
+ * }
+ * // the uenum_next returns NUL terminated string
+ * keyword = uenum_next(keywordEnum, &keywordLen, &status);
+ * displayKeywordLen = uloc_getDisplayKeyword(keyword, "en_US", displayKeyword, 256);
+ * ... do something interesting .....
+ * }
+ * uenum_close(keywordEnum);
+ * </code>
+ * @param keyword The keyword whose display string needs to be returned.
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch". NULL may be used to specify the default.
+ * @param dest the buffer to which the displayable keyword should be written.
+ * @param destCapacity The size of the buffer (number of UChars). If it is 0, then
+ * dest may be NULL and the function will only return the length of the
+ * result without writing any of the result string (pre-flighting).
+ * @param status error information if retrieving the displayable string failed.
+ * Should not be NULL and should not indicate failure on entry.
+ * @return the actual buffer size needed for the displayable variant code.
+ * @see #uloc_openKeywords
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getDisplayKeyword(const char* keyword,
+ const char* displayLocale,
+ UChar* dest,
+ int32_t destCapacity,
+ UErrorCode* status);
+/**
+ * Gets the value of the keyword suitable for display for the specified locale.
+ * E.g: for the locale string de_DE\@collation=PHONEBOOK, this API gets the display
+ * string for PHONEBOOK, in the display locale, when "collation" is specified as the keyword.
+ *
+ * @param locale The locale to get the displayable variant code with. NULL may be used to specify the default.
+ * @param keyword The keyword for whose value should be used.
+ * @param displayLocale Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch". NULL may be used to specify the default.
+ * @param dest the buffer to which the displayable keyword should be written.
+ * @param destCapacity The size of the buffer (number of UChars). If it is 0, then
+ * dest may be NULL and the function will only return the length of the
+ * result without writing any of the result string (pre-flighting).
+ * @param status error information if retrieving the displayable string failed.
+ * Should not be NULL and must not indicate failure on entry.
+ * @return the actual buffer size needed for the displayable variant code.
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getDisplayKeywordValue( const char* locale,
+ const char* keyword,
+ const char* displayLocale,
+ UChar* dest,
+ int32_t destCapacity,
+ UErrorCode* status);
+/**
+ * Gets the full name suitable for display for the specified locale.
+ *
+ * @param localeID the locale to get the displayable name with. NULL may be used to specify the default.
+ * @param inLocaleID Specifies the locale to be used to display the name. In other words,
+ * if the locale's language code is "en", passing Locale::getFrench() for
+ * inLocale would result in "Anglais", while passing Locale::getGerman()
+ * for inLocale would result in "Englisch". NULL may be used to specify the default.
+ * @param result the displayable name for localeID
+ * @param maxResultSize the size of the name buffer to store the
+ * displayable full name with
+ * @param err error information if retrieving the displayable name failed
+ * @return the actual buffer size needed for the displayable name. If it's greater
+ * than maxResultSize, the returned displayable name will be truncated.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getDisplayName(const char* localeID,
+ const char* inLocaleID,
+ UChar* result,
+ int32_t maxResultSize,
+ UErrorCode* err);
+
+
+/**
+ * Gets the specified locale from a list of all available locales.
+ * The return value is a pointer to an item of
+ * a locale name array. Both this array and the pointers
+ * it contains are owned by ICU and should not be deleted or written through
+ * by the caller. The locale name is terminated by a null pointer.
+ * @param n the specific locale name index of the available locale list
+ * @return a specified locale name of all available locales
+ * @stable ICU 2.0
+ */
+U_STABLE const char* U_EXPORT2
+uloc_getAvailable(int32_t n);
+
+/**
+ * Gets the size of the all available locale list.
+ *
+ * @return the size of the locale list
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2 uloc_countAvailable(void);
+
+/**
+ *
+ * Gets a list of all available language codes defined in ISO 639. This is a pointer
+ * to an array of pointers to arrays of char. All of these pointers are owned
+ * by ICU-- do not delete them, and do not write through them. The array is
+ * terminated with a null pointer.
+ * @return a list of all available language codes
+ * @stable ICU 2.0
+ */
+U_STABLE const char* const* U_EXPORT2
+uloc_getISOLanguages(void);
+
+/**
+ *
+ * Gets a list of all available 2-letter country codes defined in ISO 639. This is a
+ * pointer to an array of pointers to arrays of char. All of these pointers are
+ * owned by ICU-- do not delete them, and do not write through them. The array is
+ * terminated with a null pointer.
+ * @return a list of all available country codes
+ * @stable ICU 2.0
+ */
+U_STABLE const char* const* U_EXPORT2
+uloc_getISOCountries(void);
+
+/**
+ * Truncate the locale ID string to get the parent locale ID.
+ * Copies the part of the string before the last underscore.
+ * The parent locale ID will be an empty string if there is no
+ * underscore, or if there is only one underscore at localeID[0].
+ *
+ * @param localeID Input locale ID string.
+ * @param parent Output string buffer for the parent locale ID.
+ * @param parentCapacity Size of the output buffer.
+ * @param err A UErrorCode value.
+ * @return The length of the parent locale ID.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+uloc_getParent(const char* localeID,
+ char* parent,
+ int32_t parentCapacity,
+ UErrorCode* err);
+
+
+
+
+/**
+ * Gets the full name for the specified locale.
+ * Note: This has the effect of 'canonicalizing' the string to
+ * a certain extent. Upper and lower case are set as needed,
+ * and if the components were in 'POSIX' format they are changed to
+ * ICU format. It does NOT map aliased names in any way.
+ * See the top of this header file.
+ * This API strips off the keyword part, so "de_DE\@collation=phonebook"
+ * will become "de_DE".
+ * This API supports preflighting.
+ *
+ * @param localeID the locale to get the full name with
+ * @param name fill in buffer for the name without keywords.
+ * @param nameCapacity capacity of the fill in buffer.
+ * @param err error information if retrieving the full name failed
+ * @return the actual buffer size needed for the full name. If it's greater
+ * than nameCapacity, the returned full name will be truncated.
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getBaseName(const char* localeID,
+ char* name,
+ int32_t nameCapacity,
+ UErrorCode* err);
+
+/**
+ * Gets an enumeration of keywords for the specified locale. Enumeration
+ * must get disposed of by the client using uenum_close function.
+ *
+ * @param localeID the locale to get the variant code with
+ * @param status error information if retrieving the keywords failed
+ * @return enumeration of keywords or NULL if there are no keywords.
+ * @draft ICU 2.8
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+uloc_openKeywords(const char* localeID,
+ UErrorCode* status);
+
+/**
+ * Get the value for a keyword. Locale name does not need to be normalized.
+ *
+ * @param localeID locale name containing the keyword ("de_DE@currency=EURO;collation=PHONEBOOK")
+ * @param keywordName name of the keyword for which we want the value. Case insensitive.
+ * @param buffer receiving buffer
+ * @param bufferCapacity capacity of receiving buffer
+ * @param status containing error code - buffer not big enough.
+ * @return the length of keyword value
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_getKeywordValue(const char* localeID,
+ const char* keywordName,
+ char* buffer, int32_t bufferCapacity,
+ UErrorCode* status);
+
+
+/**
+ * Set the value of the specified keyword.
+ * NOTE: Unlike almost every other ICU function which takes a
+ * buffer, this function will NOT truncate the output text. If a
+ * BUFFER_OVERFLOW_ERROR is received, it means that the original
+ * buffer is untouched. This is done to prevent incorrect or possibly
+ * even malformed locales from being generated and used.
+ *
+ * @param keywordName name of the keyword to be set. Case insensitive.
+ * @param keywordValue value of the keyword to be set. If 0-length or
+ * NULL, will result in the keyword being removed. No error is given if
+ * that keyword does not exist.
+ * @param buffer input buffer containing locale to be modified.
+ * @param bufferCapacity capacity of receiving buffer
+ * @param status containing error code - buffer not big enough.
+ * @return the length needed for the buffer
+ * @see uloc_getKeywordValue
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_setKeywordValue(const char* keywordName,
+ const char* keywordValue,
+ char* buffer, int32_t bufferCapacity,
+ UErrorCode* status);
+
+/**
+ * enums for the 'outResult' parameter return value
+ * @see uloc_acceptLanguageFromHTTP
+ * @see uloc_acceptLanguage
+ * @draft ICU 3.2
+ */
+typedef enum {
+ ULOC_ACCEPT_FAILED = 0, /* No exact match was found. */
+ ULOC_ACCEPT_VALID = 1, /* An exact match was found. */
+ ULOC_ACCEPT_FALLBACK = 2 /* A fallback was found, for example,
+ Accept list contained 'ja_JP'
+ which matched available locale 'ja'. */
+} UAcceptResult;
+
+
+/**
+ * @param httpAcceptLanguage - "Accept-Language:" header as per HTTP.
+ * @param result - buffer to accept the result locale
+ * @param resultAvailable the size of the result buffer.
+ * @param availableLocales - list of available locales to match
+ * @param status Error status, may be BUFFER_OVERFLOW_ERROR
+ * @return length needed for the locale.
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable,
+ UAcceptResult *outResult,
+ const char *httpAcceptLanguage,
+ UEnumeration* availableLocales,
+ UErrorCode *status);
+
+/**
+ * @param acceptList -list of acceptable languages
+ * @param acceptListCount - count of acceptList items
+ * @param result - buffer to accept the result locale
+ * @param resultAvailable the size of the result buffer.
+ * @param availableLocales - list of available locales to match
+ * @param status Error status, may be BUFFER_OVERFLOW_ERROR
+ * @return length needed for the locale.
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+uloc_acceptLanguage(char *result, int32_t resultAvailable,
+ UAcceptResult *outResult, const char **acceptList,
+ int32_t acceptListCount,
+ UEnumeration* availableLocales,
+ UErrorCode *status);
+
+/*eof*/
+
+
+#endif /*_ULOC*/
+
+
+
--- /dev/null
+/*
+*******************************************************************************
+* Copyright (c) 1996-2004, International Business Machines Corporation
+* and others. All Rights Reserved.
+*******************************************************************************
+* File unorm.h
+*
+* Created by: Vladimir Weinstein 12052000
+*
+* Modification history :
+*
+* Date Name Description
+* 02/01/01 synwee Added normalization quickcheck enum and method.
+*/
+#ifndef UNORM_H
+#define UNORM_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+#include "unicode/uiter.h"
+
+/**
+ * \file
+ * \brief C API: Unicode Normalization
+ *
+ * <h2>Unicode normalization API</h2>
+ *
+ * <code>unorm_normalize</code> transforms Unicode text into an equivalent composed or
+ * decomposed form, allowing for easier sorting and searching of text.
+ * <code>unorm_normalize</code> supports the standard normalization forms described in
+ * <a href="http://www.unicode.org/unicode/reports/tr15/" target="unicode">
+ * Unicode Standard Annex #15 — Unicode Normalization Forms</a>.
+ *
+ * Characters with accents or other adornments can be encoded in
+ * several different ways in Unicode. For example, take the character A-acute.
+ * In Unicode, this can be encoded as a single character (the
+ * "composed" form):
+ *
+ * \code
+ * 00C1 LATIN CAPITAL LETTER A WITH ACUTE
+ * \endcode
+ *
+ * or as two separate characters (the "decomposed" form):
+ *
+ * \code
+ * 0041 LATIN CAPITAL LETTER A
+ * 0301 COMBINING ACUTE ACCENT
+ * \endcode
+ *
+ * To a user of your program, however, both of these sequences should be
+ * treated as the same "user-level" character "A with acute accent". When you are searching or
+ * comparing text, you must ensure that these two sequences are treated
+ * equivalently. In addition, you must handle characters with more than one
+ * accent. Sometimes the order of a character's combining accents is
+ * significant, while in other cases accent sequences in different orders are
+ * really equivalent.
+ *
+ * Similarly, the string "ffi" can be encoded as three separate letters:
+ *
+ * \code
+ * 0066 LATIN SMALL LETTER F
+ * 0066 LATIN SMALL LETTER F
+ * 0069 LATIN SMALL LETTER I
+ * \endcode
+ *
+ * or as the single character
+ *
+ * \code
+ * FB03 LATIN SMALL LIGATURE FFI
+ * \endcode
+ *
+ * The ffi ligature is not a distinct semantic character, and strictly speaking
+ * it shouldn't be in Unicode at all, but it was included for compatibility
+ * with existing character sets that already provided it. The Unicode standard
+ * identifies such characters by giving them "compatibility" decompositions
+ * into the corresponding semantic characters. When sorting and searching, you
+ * will often want to use these mappings.
+ *
+ * <code>unorm_normalize</code> helps solve these problems by transforming text into the
+ * canonical composed and decomposed forms as shown in the first example above.
+ * In addition, you can have it perform compatibility decompositions so that
+ * you can treat compatibility characters the same as their equivalents.
+ * Finally, <code>unorm_normalize</code> rearranges accents into the proper canonical
+ * order, so that you do not have to worry about accent rearrangement on your
+ * own.
+ *
+ * Form FCD, "Fast C or D", is also designed for collation.
+ * It allows to work on strings that are not necessarily normalized
+ * with an algorithm (like in collation) that works under "canonical closure", i.e., it treats precomposed
+ * characters and their decomposed equivalents the same.
+ *
+ * It is not a normalization form because it does not provide for uniqueness of representation. Multiple strings
+ * may be canonically equivalent (their NFDs are identical) and may all conform to FCD without being identical
+ * themselves.
+ *
+ * The form is defined such that the "raw decomposition", the recursive canonical decomposition of each character,
+ * results in a string that is canonically ordered. This means that precomposed characters are allowed for as long
+ * as their decompositions do not need canonical reordering.
+ *
+ * Its advantage for a process like collation is that all NFD and most NFC texts - and many unnormalized texts -
+ * already conform to FCD and do not need to be normalized (NFD) for such a process. The FCD quick check will
+ * return UNORM_YES for most strings in practice.
+ *
+ * unorm_normalize(UNORM_FCD) may be implemented with UNORM_NFD.
+ *
+ * For more details on FCD see the collation design document:
+ * http://oss.software.ibm.com/cvs/icu/~checkout~/icuhtml/design/collation/ICU_collation_design.htm
+ *
+ * ICU collation performs either NFD or FCD normalization automatically if normalization
+ * is turned on for the collator object.
+ * Beyond collation and string search, normalized strings may be useful for string equivalence comparisons,
+ * transliteration/transcription, unique representations, etc.
+ *
+ * The W3C generally recommends to exchange texts in NFC.
+ * Note also that most legacy character encodings use only precomposed forms and often do not
+ * encode any combining marks by themselves. For conversion to such character encodings the
+ * Unicode text needs to be normalized to NFC.
+ * For more usage examples, see the Unicode Standard Annex.
+ */
+
+/**
+ * Constants for normalization modes.
+ * @stable ICU 2.0
+ */
+typedef enum {
+ /** No decomposition/composition. @stable ICU 2.0 */
+ UNORM_NONE = 1,
+ /** Canonical decomposition. @stable ICU 2.0 */
+ UNORM_NFD = 2,
+ /** Compatibility decomposition. @stable ICU 2.0 */
+ UNORM_NFKD = 3,
+ /** Canonical decomposition followed by canonical composition. @stable ICU 2.0 */
+ UNORM_NFC = 4,
+ /** Default normalization. @stable ICU 2.0 */
+ UNORM_DEFAULT = UNORM_NFC,
+ /** Compatibility decomposition followed by canonical composition. @stable ICU 2.0 */
+ UNORM_NFKC =5,
+ /** "Fast C or D" form. @stable ICU 2.0 */
+ UNORM_FCD = 6,
+
+ /** One more than the highest normalization mode constant. @stable ICU 2.0 */
+ UNORM_MODE_COUNT
+} UNormalizationMode;
+
+/**
+ * Constants for options flags for normalization.
+ * Use 0 for default options,
+ * including normalization according to the Unicode version
+ * that is currently supported by ICU (see u_getUnicodeVersion).
+ * @stable ICU 2.6
+ */
+enum {
+ /**
+ * Options bit set value to select Unicode 3.2 normalization
+ * (except NormalizationCorrections).
+ * At most one Unicode version can be selected at a time.
+ * @stable ICU 2.6
+ */
+ UNORM_UNICODE_3_2=0x20
+};
+
+/**
+ * Lowest-order bit number of unorm_compare() options bits corresponding to
+ * normalization options bits.
+ *
+ * The options parameter for unorm_compare() uses most bits for
+ * itself and for various comparison and folding flags.
+ * The most significant bits, however, are shifted down and passed on
+ * to the normalization implementation.
+ * (That is, from unorm_compare(..., options, ...),
+ * options>>UNORM_COMPARE_NORM_OPTIONS_SHIFT will be passed on to the
+ * internal normalization functions.)
+ *
+ * @see unorm_compare
+ * @stable ICU 2.6
+ */
+#define UNORM_COMPARE_NORM_OPTIONS_SHIFT 20
+
+/**
+ * Normalize a string.
+ * The string will be normalized according the specified normalization mode
+ * and options.
+ *
+ * @param source The string to normalize.
+ * @param sourceLength The length of source, or -1 if NUL-terminated.
+ * @param mode The normalization mode; one of UNORM_NONE,
+ * UNORM_NFD, UNORM_NFC, UNORM_NFKC, UNORM_NFKD, UNORM_DEFAULT.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param result A pointer to a buffer to receive the result string.
+ * The result string is NUL-terminated if possible.
+ * @param resultLength The maximum size of result.
+ * @param status A pointer to a UErrorCode to receive any errors.
+ * @return The total buffer size needed; if greater than resultLength,
+ * the output was truncated, and the error code is set to U_BUFFER_OVERFLOW_ERROR.
+ * @stable ICU 2.0
+ */
+U_STABLE int32_t U_EXPORT2
+unorm_normalize(const UChar *source, int32_t sourceLength,
+ UNormalizationMode mode, int32_t options,
+ UChar *result, int32_t resultLength,
+ UErrorCode *status);
+#endif
+/**
+ * Result values for unorm_quickCheck().
+ * For details see Unicode Technical Report 15.
+ * @stable ICU 2.0
+ */
+typedef enum UNormalizationCheckResult {
+ /**
+ * Indicates that string is not in the normalized format
+ */
+ UNORM_NO,
+ /**
+ * Indicates that string is in the normalized format
+ */
+ UNORM_YES,
+ /**
+ * Indicates that string cannot be determined if it is in the normalized
+ * format without further thorough checks.
+ */
+ UNORM_MAYBE
+} UNormalizationCheckResult;
+#if !UCONFIG_NO_NORMALIZATION
+/**
+ * Performing quick check on a string, to quickly determine if the string is
+ * in a particular normalization format.
+ * Three types of result can be returned UNORM_YES, UNORM_NO or
+ * UNORM_MAYBE. Result UNORM_YES indicates that the argument
+ * string is in the desired normalized format, UNORM_NO determines that
+ * argument string is not in the desired normalized format. A
+ * UNORM_MAYBE result indicates that a more thorough check is required,
+ * the user may have to put the string in its normalized form and compare the
+ * results.
+ *
+ * @param source string for determining if it is in a normalized format
+ * @param sourcelength length of source to test, or -1 if NUL-terminated
+ * @param mode which normalization form to test for
+ * @param status a pointer to a UErrorCode to receive any errors
+ * @return UNORM_YES, UNORM_NO or UNORM_MAYBE
+ *
+ * @see unorm_isNormalized
+ * @stable ICU 2.0
+ */
+U_STABLE UNormalizationCheckResult U_EXPORT2
+unorm_quickCheck(const UChar *source, int32_t sourcelength,
+ UNormalizationMode mode,
+ UErrorCode *status);
+
+/**
+ * Performing quick check on a string; same as unorm_quickCheck but
+ * takes an extra options parameter like most normalization functions.
+ *
+ * @param src String that is to be tested if it is in a normalization format.
+ * @param srcLength Length of source to test, or -1 if NUL-terminated.
+ * @param mode Which normalization form to test for.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return UNORM_YES, UNORM_NO or UNORM_MAYBE
+ *
+ * @see unorm_quickCheck
+ * @see unorm_isNormalized
+ * @stable ICU 2.6
+ */
+U_STABLE UNormalizationCheckResult U_EXPORT2
+unorm_quickCheckWithOptions(const UChar *src, int32_t srcLength,
+ UNormalizationMode mode, int32_t options,
+ UErrorCode *pErrorCode);
+
+/**
+ * Test if a string is in a given normalization form.
+ * This is semantically equivalent to source.equals(normalize(source, mode)) .
+ *
+ * Unlike unorm_quickCheck(), this function returns a definitive result,
+ * never a "maybe".
+ * For NFD, NFKD, and FCD, both functions work exactly the same.
+ * For NFC and NFKC where quickCheck may return "maybe", this function will
+ * perform further tests to arrive at a TRUE/FALSE result.
+ *
+ * @param src String that is to be tested if it is in a normalization format.
+ * @param srcLength Length of source to test, or -1 if NUL-terminated.
+ * @param mode Which normalization form to test for.
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return Boolean value indicating whether the source string is in the
+ * "mode" normalization form.
+ *
+ * @see unorm_quickCheck
+ * @stable ICU 2.2
+ */
+U_STABLE UBool U_EXPORT2
+unorm_isNormalized(const UChar *src, int32_t srcLength,
+ UNormalizationMode mode,
+ UErrorCode *pErrorCode);
+
+/**
+ * Test if a string is in a given normalization form; same as unorm_isNormalized but
+ * takes an extra options parameter like most normalization functions.
+ *
+ * @param src String that is to be tested if it is in a normalization format.
+ * @param srcLength Length of source to test, or -1 if NUL-terminated.
+ * @param mode Which normalization form to test for.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return Boolean value indicating whether the source string is in the
+ * "mode/options" normalization form.
+ *
+ * @see unorm_quickCheck
+ * @see unorm_isNormalized
+ * @stable ICU 2.6
+ */
+U_STABLE UBool U_EXPORT2
+unorm_isNormalizedWithOptions(const UChar *src, int32_t srcLength,
+ UNormalizationMode mode, int32_t options,
+ UErrorCode *pErrorCode);
+
+/**
+ * Iterative normalization forward.
+ * This function (together with unorm_previous) is somewhat
+ * similar to the C++ Normalizer class (see its non-static functions).
+ *
+ * Iterative normalization is useful when only a small portion of a longer
+ * string/text needs to be processed.
+ *
+ * For example, the likelihood may be high that processing the first 10% of some
+ * text will be sufficient to find certain data.
+ * Another example: When one wants to concatenate two normalized strings and get a
+ * normalized result, it is much more efficient to normalize just a small part of
+ * the result around the concatenation place instead of re-normalizing everything.
+ *
+ * The input text is an instance of the C character iteration API UCharIterator.
+ * It may wrap around a simple string, a CharacterIterator, a Replaceable, or any
+ * other kind of text object.
+ *
+ * If a buffer overflow occurs, then the caller needs to reset the iterator to the
+ * old index and call the function again with a larger buffer - if the caller cares
+ * for the actual output.
+ * Regardless of the output buffer, the iterator will always be moved to the next
+ * normalization boundary.
+ *
+ * This function (like unorm_previous) serves two purposes:
+ *
+ * 1) To find the next boundary so that the normalization of the part of the text
+ * from the current position to that boundary does not affect and is not affected
+ * by the part of the text beyond that boundary.
+ *
+ * 2) To normalize the text up to the boundary.
+ *
+ * The second step is optional, per the doNormalize parameter.
+ * It is omitted for operations like string concatenation, where the two adjacent
+ * string ends need to be normalized together.
+ * In such a case, the output buffer will just contain a copy of the text up to the
+ * boundary.
+ *
+ * pNeededToNormalize is an output-only parameter. Its output value is only defined
+ * if normalization was requested (doNormalize) and successful (especially, no
+ * buffer overflow).
+ * It is useful for operations like a normalizing transliterator, where one would
+ * not want to replace a piece of text if it is not modified.
+ *
+ * If doNormalize==TRUE and pNeededToNormalize!=NULL then *pNeeded... is set TRUE
+ * if the normalization was necessary.
+ *
+ * If doNormalize==FALSE then *pNeededToNormalize will be set to FALSE.
+ *
+ * If the buffer overflows, then *pNeededToNormalize will be undefined;
+ * essentially, whenever U_FAILURE is true (like in buffer overflows), this result
+ * will be undefined.
+ *
+ * @param src The input text in the form of a C character iterator.
+ * @param dest The output buffer; can be NULL if destCapacity==0 for pure preflighting.
+ * @param destCapacity The number of UChars that fit into dest.
+ * @param mode The normalization mode.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param doNormalize Indicates if the source text up to the next boundary
+ * is to be normalized (TRUE) or just copied (FALSE).
+ * @param pNeededToNormalize Output flag indicating if the normalization resulted in
+ * different text from the input.
+ * Not defined if an error occurs including buffer overflow.
+ * Always FALSE if !doNormalize.
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return Length of output (number of UChars) when successful or buffer overflow.
+ *
+ * @see unorm_previous
+ * @see unorm_normalize
+ *
+ * @stable ICU 2.1
+ */
+U_STABLE int32_t U_EXPORT2
+unorm_next(UCharIterator *src,
+ UChar *dest, int32_t destCapacity,
+ UNormalizationMode mode, int32_t options,
+ UBool doNormalize, UBool *pNeededToNormalize,
+ UErrorCode *pErrorCode);
+
+/**
+ * Iterative normalization backward.
+ * This function (together with unorm_next) is somewhat
+ * similar to the C++ Normalizer class (see its non-static functions).
+ * For all details see unorm_next.
+ *
+ * @param src The input text in the form of a C character iterator.
+ * @param dest The output buffer; can be NULL if destCapacity==0 for pure preflighting.
+ * @param destCapacity The number of UChars that fit into dest.
+ * @param mode The normalization mode.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param doNormalize Indicates if the source text up to the next boundary
+ * is to be normalized (TRUE) or just copied (FALSE).
+ * @param pNeededToNormalize Output flag indicating if the normalization resulted in
+ * different text from the input.
+ * Not defined if an error occurs including buffer overflow.
+ * Always FALSE if !doNormalize.
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return Length of output (number of UChars) when successful or buffer overflow.
+ *
+ * @see unorm_next
+ * @see unorm_normalize
+ *
+ * @stable ICU 2.1
+ */
+U_STABLE int32_t U_EXPORT2
+unorm_previous(UCharIterator *src,
+ UChar *dest, int32_t destCapacity,
+ UNormalizationMode mode, int32_t options,
+ UBool doNormalize, UBool *pNeededToNormalize,
+ UErrorCode *pErrorCode);
+
+/**
+ * Concatenate normalized strings, making sure that the result is normalized as well.
+ *
+ * If both the left and the right strings are in
+ * the normalization form according to "mode/options",
+ * then the result will be
+ *
+ * \code
+ * dest=normalize(left+right, mode, options)
+ * \endcode
+ *
+ * With the input strings already being normalized,
+ * this function will use unorm_next() and unorm_previous()
+ * to find the adjacent end pieces of the input strings.
+ * Only the concatenation of these end pieces will be normalized and
+ * then concatenated with the remaining parts of the input strings.
+ *
+ * It is allowed to have dest==left to avoid copying the entire left string.
+ *
+ * @param left Left source string, may be same as dest.
+ * @param leftLength Length of left source string, or -1 if NUL-terminated.
+ * @param right Right source string.
+ * @param rightLength Length of right source string, or -1 if NUL-terminated.
+ * @param dest The output buffer; can be NULL if destCapacity==0 for pure preflighting.
+ * @param destCapacity The number of UChars that fit into dest.
+ * @param mode The normalization mode.
+ * @param options The normalization options, ORed together (0 for no options).
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return Length of output (number of UChars) when successful or buffer overflow.
+ *
+ * @see unorm_normalize
+ * @see unorm_next
+ * @see unorm_previous
+ *
+ * @stable ICU 2.1
+ */
+U_STABLE int32_t U_EXPORT2
+unorm_concatenate(const UChar *left, int32_t leftLength,
+ const UChar *right, int32_t rightLength,
+ UChar *dest, int32_t destCapacity,
+ UNormalizationMode mode, int32_t options,
+ UErrorCode *pErrorCode);
+
+/**
+ * Option bit for unorm_compare:
+ * Both input strings are assumed to fulfill FCD conditions.
+ * @stable ICU 2.2
+ */
+#define UNORM_INPUT_IS_FCD 0x20000
+
+/**
+ * Option bit for unorm_compare:
+ * Perform case-insensitive comparison.
+ * @stable ICU 2.2
+ */
+#define U_COMPARE_IGNORE_CASE 0x10000
+
+#ifndef U_COMPARE_CODE_POINT_ORDER
+/* see also unistr.h and ustring.h */
+/**
+ * Option bit for u_strCaseCompare, u_strcasecmp, unorm_compare, etc:
+ * Compare strings in code point order instead of code unit order.
+ * @stable ICU 2.2
+ */
+#define U_COMPARE_CODE_POINT_ORDER 0x8000
+#endif
+
+/**
+ * Compare two strings for canonical equivalence.
+ * Further options include case-insensitive comparison and
+ * code point order (as opposed to code unit order).
+ *
+ * Canonical equivalence between two strings is defined as their normalized
+ * forms (NFD or NFC) being identical.
+ * This function compares strings incrementally instead of normalizing
+ * (and optionally case-folding) both strings entirely,
+ * improving performance significantly.
+ *
+ * Bulk normalization is only necessary if the strings do not fulfill the FCD
+ * conditions. Only in this case, and only if the strings are relatively long,
+ * is memory allocated temporarily.
+ * For FCD strings and short non-FCD strings there is no memory allocation.
+ *
+ * Semantically, this is equivalent to
+ * strcmp[CodePointOrder](NFD(foldCase(NFD(s1))), NFD(foldCase(NFD(s2))))
+ * where code point order and foldCase are all optional.
+ *
+ * UAX 21 2.5 Caseless Matching specifies that for a canonical caseless match
+ * the case folding must be performed first, then the normalization.
+ *
+ * @param s1 First source string.
+ * @param length1 Length of first source string, or -1 if NUL-terminated.
+ *
+ * @param s2 Second source string.
+ * @param length2 Length of second source string, or -1 if NUL-terminated.
+ *
+ * @param options A bit set of options:
+ * - U_FOLD_CASE_DEFAULT or 0 is used for default options:
+ * Case-sensitive comparison in code unit order, and the input strings
+ * are quick-checked for FCD.
+ *
+ * - UNORM_INPUT_IS_FCD
+ * Set if the caller knows that both s1 and s2 fulfill the FCD conditions.
+ * If not set, the function will quickCheck for FCD
+ * and normalize if necessary.
+ *
+ * - U_COMPARE_CODE_POINT_ORDER
+ * Set to choose code point order instead of code unit order
+ * (see u_strCompare for details).
+ *
+ * - U_COMPARE_IGNORE_CASE
+ * Set to compare strings case-insensitively using case folding,
+ * instead of case-sensitively.
+ * If set, then the following case folding options are used.
+ *
+ * - Options as used with case-insensitive comparisons, currently:
+ *
+ * - U_FOLD_CASE_EXCLUDE_SPECIAL_I
+ * (see u_strCaseCompare for details)
+ *
+ * - regular normalization options shifted left by UNORM_COMPARE_NORM_OPTIONS_SHIFT
+ *
+ * @param pErrorCode ICU error code in/out parameter.
+ * Must fulfill U_SUCCESS before the function call.
+ * @return <0 or 0 or >0 as usual for string comparisons
+ *
+ * @see unorm_normalize
+ * @see UNORM_FCD
+ * @see u_strCompare
+ * @see u_strCaseCompare
+ *
+ * @stable ICU 2.2
+ */
+U_STABLE int32_t U_EXPORT2
+unorm_compare(const UChar *s1, int32_t length1,
+ const UChar *s2, int32_t length2,
+ uint32_t options,
+ UErrorCode *pErrorCode);
+
+#endif /* #if !UCONFIG_NO_NORMALIZATION */
+
+#endif
--- /dev/null
+/*
+*******************************************************************************
+*
+* Copyright (C) 2002-2004, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+*******************************************************************************
+* file name: uset.h
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2002mar07
+* created by: Markus W. Scherer
+*
+* C version of UnicodeSet.
+*/
+
+
+/**
+ * \file
+ * \brief C API: Unicode Set
+ *
+ * <p>This is a C wrapper around the C++ UnicodeSet class.</p>
+ */
+
+#ifndef __USET_H__
+#define __USET_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+
+#ifndef UCNV_H
+struct USet;
+/**
+ * A UnicodeSet. Use the uset_* API to manipulate. Create with
+ * uset_open*, and destroy with uset_close.
+ * @stable ICU 2.4
+ */
+typedef struct USet USet;
+#endif
+
+/**
+ * Bitmask values to be passed to uset_openPatternOptions() or
+ * uset_applyPattern() taking an option parameter.
+ * @stable ICU 2.4
+ */
+enum {
+ /**
+ * Ignore white space within patterns unless quoted or escaped.
+ * @stable ICU 2.4
+ */
+ USET_IGNORE_SPACE = 1,
+
+ /**
+ * Enable case insensitive matching. E.g., "[ab]" with this flag
+ * will match 'a', 'A', 'b', and 'B'. "[^ab]" with this flag will
+ * match all except 'a', 'A', 'b', and 'B'. This performs a full
+ * closure over case mappings, e.g. U+017F for s.
+ * @stable ICU 2.4
+ */
+ USET_CASE_INSENSITIVE = 2,
+
+ /**
+ * Bitmask for UnicodeSet::closeOver() indicating letter case.
+ * This may be ORed together with other selectors.
+ * @internal
+ */
+ USET_CASE = 2,
+
+ /**
+ * Enable case insensitive matching. E.g., "[ab]" with this flag
+ * will match 'a', 'A', 'b', and 'B'. "[^ab]" with this flag will
+ * match all except 'a', 'A', 'b', and 'B'. This adds the lower-,
+ * title-, and uppercase mappings as well as the case folding
+ * of each existing element in the set.
+ * @draft ICU 3.2
+ */
+ USET_ADD_CASE_MAPPINGS = 4,
+
+ /**
+ * Enough for any single-code point set
+ * @internal
+ */
+ USET_SERIALIZED_STATIC_ARRAY_CAPACITY=8
+};
+
+/**
+ * A serialized form of a Unicode set. Limited manipulations are
+ * possible directly on a serialized set. See below.
+ * @stable ICU 2.4
+ */
+typedef struct USerializedSet {
+ /**
+ * The serialized Unicode Set.
+ * @stable ICU 2.4
+ */
+ const uint16_t *array;
+ /**
+ * The length of the array that contains BMP characters.
+ * @stable ICU 2.4
+ */
+ int32_t bmpLength;
+ /**
+ * The total length of the array.
+ * @stable ICU 2.4
+ */
+ int32_t length;
+ /**
+ * A small buffer for the array to reduce memory allocations.
+ * @stable ICU 2.4
+ */
+ uint16_t staticArray[USET_SERIALIZED_STATIC_ARRAY_CAPACITY];
+} USerializedSet;
+
+/*********************************************************************
+ * USet API
+ *********************************************************************/
+
+/**
+ * Creates a USet object that contains the range of characters
+ * start..end, inclusive.
+ * @param start first character of the range, inclusive
+ * @param end last character of the range, inclusive
+ * @return a newly created USet. The caller must call uset_close() on
+ * it when done.
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_open(UChar32 start, UChar32 end);
+
+/**
+ * Creates a set from the given pattern. See the UnicodeSet class
+ * description for the syntax of the pattern language.
+ * @param pattern a string specifying what characters are in the set
+ * @param patternLength the length of the pattern, or -1 if null
+ * terminated
+ * @param ec the error code
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_openPattern(const UChar* pattern, int32_t patternLength,
+ UErrorCode* ec);
+
+/**
+ * Creates a set from the given pattern. See the UnicodeSet class
+ * description for the syntax of the pattern language.
+ * @param pattern a string specifying what characters are in the set
+ * @param patternLength the length of the pattern, or -1 if null
+ * terminated
+ * @param options bitmask for options to apply to the pattern.
+ * Valid options are USET_IGNORE_SPACE and USET_CASE_INSENSITIVE.
+ * @param ec the error code
+ * @stable ICU 2.4
+ */
+U_STABLE USet* U_EXPORT2
+uset_openPatternOptions(const UChar* pattern, int32_t patternLength,
+ uint32_t options,
+ UErrorCode* ec);
+
+/**
+ * Disposes of the storage used by a USet object. This function should
+ * be called exactly once for objects returned by uset_open().
+ * @param set the object to dispose of
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_close(USet* set);
+
+/**
+ * Causes the USet object to represent the range <code>start - end</code>.
+ * If <code>start > end</code> then this USet is set to an empty range.
+ * @param set the object to set to the given range
+ * @param start first character in the set, inclusive
+ * @param end last character in the set, inclusive
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_set(USet* set,
+ UChar32 start, UChar32 end);
+
+/**
+ * Modifies the set to represent the set specified by the given
+ * pattern. See the UnicodeSet class description for the syntax of
+ * the pattern language. See also the User Guide chapter about UnicodeSet.
+ * <em>Empties the set passed before applying the pattern.</em>
+ * @param set The set to which the pattern is to be applied.
+ * @param pattern A pointer to UChar string specifying what characters are in the set.
+ * The character at pattern[0] must be a '['.
+ * @param patternLength The length of the UChar string. -1 if NUL terminated.
+ * @param options A bitmask for options to apply to the pattern.
+ * Valid options are USET_IGNORE_SPACE and USET_CASE_INSENSITIVE.
+ * @param status Returns an error if the pattern cannot be parsed.
+ * @return Upon successful parse, the value is either
+ * the index of the character after the closing ']'
+ * of the parsed pattern.
+ * If the status code indicates failure, then the return value
+ * is the index of the error in the source.
+ *
+ * @draft ICU 2.8
+ */
+U_DRAFT int32_t U_EXPORT2
+uset_applyPattern(USet *set,
+ const UChar *pattern, int32_t patternLength,
+ uint32_t options,
+ UErrorCode *status);
+
+/**
+ * Modifies the set to contain those code points which have the given value
+ * for the given binary or enumerated property, as returned by
+ * u_getIntPropertyValue. Prior contents of this set are lost.
+ *
+ * @param set the object to contain the code points defined by the property
+ *
+ * @param prop a property in the range UCHAR_BIN_START..UCHAR_BIN_LIMIT-1
+ * or UCHAR_INT_START..UCHAR_INT_LIMIT-1
+ * or UCHAR_MASK_START..UCHAR_MASK_LIMIT-1.
+ *
+ * @param value a value in the range u_getIntPropertyMinValue(prop)..
+ * u_getIntPropertyMaxValue(prop), with one exception. If prop is
+ * UCHAR_GENERAL_CATEGORY_MASK, then value should not be a UCharCategory, but
+ * rather a mask value produced by U_GET_GC_MASK(). This allows grouped
+ * categories such as [:L:] to be represented.
+ *
+ * @param ec error code input/output parameter
+ *
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_applyIntPropertyValue(USet* set,
+ UProperty prop, int32_t value, UErrorCode* ec);
+
+/**
+ * Modifies the set to contain those code points which have the
+ * given value for the given property. Prior contents of this
+ * set are lost.
+ *
+ * @param set the object to contain the code points defined by the given
+ * property and value alias
+ *
+ * @param prop a string specifying a property alias, either short or long.
+ * The name is matched loosely. See PropertyAliases.txt for names and a
+ * description of loose matching. If the value string is empty, then this
+ * string is interpreted as either a General_Category value alias, a Script
+ * value alias, a binary property alias, or a special ID. Special IDs are
+ * matched loosely and correspond to the following sets:
+ *
+ * "ANY" = [\\u0000-\\U0010FFFF],
+ * "ASCII" = [\\u0000-\\u007F].
+ *
+ * @param propLength the length of the prop, or -1 if NULL
+ *
+ * @param value a string specifying a value alias, either short or long.
+ * The name is matched loosely. See PropertyValueAliases.txt for names
+ * and a description of loose matching. In addition to aliases listed,
+ * numeric values and canonical combining classes may be expressed
+ * numerically, e.g., ("nv", "0.5") or ("ccc", "220"). The value string
+ * may also be empty.
+ *
+ * @param valueLength the length of the value, or -1 if NULL
+ *
+ * @param ec error code input/output parameter
+ *
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_applyPropertyAlias(USet* set,
+ const UChar *prop, int32_t propLength,
+ const UChar *value, int32_t valueLength,
+ UErrorCode* ec);
+
+/**
+ * Return true if the given position, in the given pattern, appears
+ * to be the start of a UnicodeSet pattern.
+ *
+ * @param pattern a string specifying the pattern
+ * @param patternLength the length of the pattern, or -1 if NULL
+ * @param pos the given position
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_resemblesPattern(const UChar *pattern, int32_t patternLength,
+ int32_t pos);
+
+/**
+ * Returns a string representation of this set. If the result of
+ * calling this function is passed to a uset_openPattern(), it
+ * will produce another set that is equal to this one.
+ * @param set the set
+ * @param result the string to receive the rules, may be NULL
+ * @param resultCapacity the capacity of result, may be 0 if result is NULL
+ * @param escapeUnprintable if TRUE then convert unprintable
+ * character to their hex escape representations, \\uxxxx or
+ * \\Uxxxxxxxx. Unprintable characters are those other than
+ * U+000A, U+0020..U+007E.
+ * @param ec error code.
+ * @return length of string, possibly larger than resultCapacity
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_toPattern(const USet* set,
+ UChar* result, int32_t resultCapacity,
+ UBool escapeUnprintable,
+ UErrorCode* ec);
+
+/**
+ * Adds the given character to the given USet. After this call,
+ * uset_contains(set, c) will return TRUE.
+ * @param set the object to which to add the character
+ * @param c the character to add
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_add(USet* set, UChar32 c);
+
+/**
+ * Adds all of the elements in the specified set to this set if
+ * they're not already present. This operation effectively
+ * modifies this set so that its value is the <i>union</i> of the two
+ * sets. The behavior of this operation is unspecified if the specified
+ * collection is modified while the operation is in progress.
+ *
+ * @param set the object to which to add the set
+ * @param additionalSet the source set whose elements are to be added to this set.
+ * @stable ICU 2.6
+ */
+U_STABLE void U_EXPORT2
+uset_addAll(USet* set, const USet *additionalSet);
+
+/**
+ * Adds the given range of characters to the given USet. After this call,
+ * uset_contains(set, start, end) will return TRUE.
+ * @param set the object to which to add the character
+ * @param start the first character of the range to add, inclusive
+ * @param end the last character of the range to add, inclusive
+ * @stable ICU 2.2
+ */
+U_STABLE void U_EXPORT2
+uset_addRange(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Adds the given string to the given USet. After this call,
+ * uset_containsString(set, str, strLen) will return TRUE.
+ * @param set the object to which to add the character
+ * @param str the string to add
+ * @param strLen the length of the string or -1 if null terminated.
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_addString(USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Removes the given character from the given USet. After this call,
+ * uset_contains(set, c) will return FALSE.
+ * @param set the object from which to remove the character
+ * @param c the character to remove
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_remove(USet* set, UChar32 c);
+
+/**
+ * Removes the given range of characters from the given USet. After this call,
+ * uset_contains(set, start, end) will return FALSE.
+ * @param set the object to which to add the character
+ * @param start the first character of the range to remove, inclusive
+ * @param end the last character of the range to remove, inclusive
+ * @stable ICU 2.2
+ */
+U_STABLE void U_EXPORT2
+uset_removeRange(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Removes the given string to the given USet. After this call,
+ * uset_containsString(set, str, strLen) will return FALSE.
+ * @param set the object to which to add the character
+ * @param str the string to remove
+ * @param strLen the length of the string or -1 if null terminated.
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_removeString(USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Removes from this set all of its elements that are contained in the
+ * specified set. This operation effectively modifies this
+ * set so that its value is the <i>asymmetric set difference</i> of
+ * the two sets.
+ * @param set the object from which the elements are to be removed
+ * @param removeSet the object that defines which elements will be
+ * removed from this set
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_removeAll(USet* set, const USet* removeSet);
+
+/**
+ * Retain only the elements in this set that are contained in the
+ * specified range. If <code>start > end</code> then an empty range is
+ * retained, leaving the set empty. This is equivalent to
+ * a boolean logic AND, or a set INTERSECTION.
+ *
+ * @param set the object for which to retain only the specified range
+ * @param start first character, inclusive, of range to be retained
+ * to this set.
+ * @param end last character, inclusive, of range to be retained
+ * to this set.
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_retain(USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Retains only the elements in this set that are contained in the
+ * specified set. In other words, removes from this set all of
+ * its elements that are not contained in the specified set. This
+ * operation effectively modifies this set so that its value is
+ * the <i>intersection</i> of the two sets.
+ *
+ * @param set the object on which to perform the retain
+ * @param retain set that defines which elements this set will retain
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_retainAll(USet* set, const USet* retain);
+
+/**
+ * Reallocate this objects internal structures to take up the least
+ * possible space, without changing this object's value.
+ *
+ * @param set the object on which to perfrom the compact
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_compact(USet* set);
+
+/**
+ * Inverts this set. This operation modifies this set so that
+ * its value is its complement. This operation does not affect
+ * the multicharacter strings, if any.
+ * @param set the set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_complement(USet* set);
+
+/**
+ * Complements in this set all elements contained in the specified
+ * set. Any character in the other set will be removed if it is
+ * in this set, or will be added if it is not in this set.
+ *
+ * @param set the set with which to complement
+ * @param complement set that defines which elements will be xor'ed
+ * from this set.
+ * @draft ICU 3.2
+ */
+U_DRAFT void U_EXPORT2
+uset_complementAll(USet* set, const USet* complement);
+
+/**
+ * Removes all of the elements from this set. This set will be
+ * empty after this call returns.
+ * @param set the set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_clear(USet* set);
+
+/**
+ * Returns TRUE if the given USet contains no characters and no
+ * strings.
+ * @param set the set
+ * @return true if set is empty
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_isEmpty(const USet* set);
+
+/**
+ * Returns TRUE if the given USet contains the given character.
+ * @param set the set
+ * @param c The codepoint to check for within the set
+ * @return true if set contains c
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_contains(const USet* set, UChar32 c);
+
+/**
+ * Returns TRUE if the given USet contains all characters c
+ * where start <= c && c <= end.
+ * @param set the set
+ * @param start the first character of the range to test, inclusive
+ * @param end the last character of the range to test, inclusive
+ * @return TRUE if set contains the range
+ * @stable ICU 2.2
+ */
+U_STABLE UBool U_EXPORT2
+uset_containsRange(const USet* set, UChar32 start, UChar32 end);
+
+/**
+ * Returns TRUE if the given USet contains the given string.
+ * @param set the set
+ * @param str the string
+ * @param strLen the length of the string or -1 if null terminated.
+ * @return true if set contains str
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_containsString(const USet* set, const UChar* str, int32_t strLen);
+
+/**
+ * Returns the index of the given character within this set, where
+ * the set is ordered by ascending code point. If the character
+ * is not in this set, return -1. The inverse of this method is
+ * <code>charAt()</code>.
+ * @param set the set
+ * @param c the character to obtain the index for
+ * @return an index from 0..size()-1, or -1
+ * @draft ICU 3.2
+ */
+U_DRAFT int32_t U_EXPORT2
+uset_indexOf(const USet* set, UChar32 c);
+
+/**
+ * Returns the character at the given index within this set, where
+ * the set is ordered by ascending code point. If the index is
+ * out of range, return (UChar32)-1. The inverse of this method is
+ * <code>indexOf()</code>.
+ * @param set the set
+ * @param index an index from 0..size()-1 to obtain the char for
+ * @return the character at the given index, or (UChar32)-1.
+ * @draft ICU 3.2
+ */
+U_DRAFT UChar32 U_EXPORT2
+uset_charAt(const USet* set, int32_t index);
+
+/**
+ * Returns the number of characters and strings contained in the given
+ * USet.
+ * @param set the set
+ * @return a non-negative integer counting the characters and strings
+ * contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_size(const USet* set);
+
+/**
+ * Returns the number of items in this set. An item is either a range
+ * of characters or a single multicharacter string.
+ * @param set the set
+ * @return a non-negative integer counting the character ranges
+ * and/or strings contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getItemCount(const USet* set);
+
+/**
+ * Returns an item of this set. An item is either a range of
+ * characters or a single multicharacter string.
+ * @param set the set
+ * @param itemIndex a non-negative integer in the range 0..
+ * uset_getItemCount(set)-1
+ * @param start pointer to variable to receive first character
+ * in range, inclusive
+ * @param end pointer to variable to receive last character in range,
+ * inclusive
+ * @param str buffer to receive the string, may be NULL
+ * @param strCapacity capacity of str, or 0 if str is NULL
+ * @param ec error code
+ * @return the length of the string (>= 2), or 0 if the item is a
+ * range, in which case it is the range *start..*end, or -1 if
+ * itemIndex is out of range
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getItem(const USet* set, int32_t itemIndex,
+ UChar32* start, UChar32* end,
+ UChar* str, int32_t strCapacity,
+ UErrorCode* ec);
+
+/**
+ * Returns true if set1 contains all the characters and strings
+ * of set2. It answers the question, 'Is set1 a subset of set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsAll(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains none of the characters and strings
+ * of set2. It answers the question, 'Is set1 a disjoint set of set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsNone(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains some of the characters and strings
+ * of set2. It answers the question, 'Does set1 and set2 have an intersection?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_containsSome(const USet* set1, const USet* set2);
+
+/**
+ * Returns true if set1 contains all of the characters and strings
+ * of set2, and vis versa. It answers the question, 'Is set1 equal to set2?'
+ * @param set1 set to be checked for containment
+ * @param set2 set to be checked for containment
+ * @return true if the test condition is met
+ * @draft ICU 3.2
+ */
+U_DRAFT UBool U_EXPORT2
+uset_equals(const USet* set1, const USet* set2);
+
+/*********************************************************************
+ * Serialized set API
+ *********************************************************************/
+
+/**
+ * Serializes this set into an array of 16-bit integers. Serialization
+ * (currently) only records the characters in the set; multicharacter
+ * strings are ignored.
+ *
+ * The array
+ * has following format (each line is one 16-bit integer):
+ *
+ * length = (n+2*m) | (m!=0?0x8000:0)
+ * bmpLength = n; present if m!=0
+ * bmp[0]
+ * bmp[1]
+ * ...
+ * bmp[n-1]
+ * supp-high[0]
+ * supp-low[0]
+ * supp-high[1]
+ * supp-low[1]
+ * ...
+ * supp-high[m-1]
+ * supp-low[m-1]
+ *
+ * The array starts with a header. After the header are n bmp
+ * code points, then m supplementary code points. Either n or m
+ * or both may be zero. n+2*m is always <= 0x7FFF.
+ *
+ * If there are no supplementary characters (if m==0) then the
+ * header is one 16-bit integer, 'length', with value n.
+ *
+ * If there are supplementary characters (if m!=0) then the header
+ * is two 16-bit integers. The first, 'length', has value
+ * (n+2*m)|0x8000. The second, 'bmpLength', has value n.
+ *
+ * After the header the code points are stored in ascending order.
+ * Supplementary code points are stored as most significant 16
+ * bits followed by least significant 16 bits.
+ *
+ * @param set the set
+ * @param dest pointer to buffer of destCapacity 16-bit integers.
+ * May be NULL only if destCapacity is zero.
+ * @param destCapacity size of dest, or zero. Must not be negative.
+ * @param pErrorCode pointer to the error code. Will be set to
+ * U_INDEX_OUTOFBOUNDS_ERROR if n+2*m > 0x7FFF. Will be set to
+ * U_BUFFER_OVERFLOW_ERROR if n+2*m+(m!=0?2:1) > destCapacity.
+ * @return the total length of the serialized format, including
+ * the header, that is, n+2*m+(m!=0?2:1), or 0 on error other
+ * than U_BUFFER_OVERFLOW_ERROR.
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_serialize(const USet* set, uint16_t* dest, int32_t destCapacity, UErrorCode* pErrorCode);
+
+/**
+ * Given a serialized array, fill in the given serialized set object.
+ * @param fillSet pointer to result
+ * @param src pointer to start of array
+ * @param srcLength length of array
+ * @return true if the given array is valid, otherwise false
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_getSerializedSet(USerializedSet* fillSet, const uint16_t* src, int32_t srcLength);
+
+/**
+ * Set the USerializedSet to contain the given character (and nothing
+ * else).
+ * @param fillSet pointer to result
+ * @param c The codepoint to set
+ * @stable ICU 2.4
+ */
+U_STABLE void U_EXPORT2
+uset_setSerializedToOne(USerializedSet* fillSet, UChar32 c);
+
+/**
+ * Returns TRUE if the given USerializedSet contains the given
+ * character.
+ * @param set the serialized set
+ * @param c The codepoint to check for within the set
+ * @return true if set contains c
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_serializedContains(const USerializedSet* set, UChar32 c);
+
+/**
+ * Returns the number of disjoint ranges of characters contained in
+ * the given serialized set. Ignores any strings contained in the
+ * set.
+ * @param set the serialized set
+ * @return a non-negative integer counting the character ranges
+ * contained in set
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t U_EXPORT2
+uset_getSerializedRangeCount(const USerializedSet* set);
+
+/**
+ * Returns a range of characters contained in the given serialized
+ * set.
+ * @param set the serialized set
+ * @param rangeIndex a non-negative integer in the range 0..
+ * uset_getSerializedRangeCount(set)-1
+ * @param pStart pointer to variable to receive first character
+ * in range, inclusive
+ * @param pEnd pointer to variable to receive last character in range,
+ * inclusive
+ * @return true if rangeIndex is valid, otherwise false
+ * @stable ICU 2.4
+ */
+U_STABLE UBool U_EXPORT2
+uset_getSerializedRange(const USerializedSet* set, int32_t rangeIndex,
+ UChar32* pStart, UChar32* pEnd);
+
+#endif
+/* This file is intentionally left blank. */
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CallFrame.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+JSValuePtr CallFrame::thisValue()
+{
+ return this[codeBlock()->thisRegister()].jsValue(this);
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CallFrame_h
+#define CallFrame_h
+
+#include "JSGlobalData.h"
+#include "RegisterFile.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+ class Arguments;
+ class JSActivation;
+ class Interpreter;
+
+ // Represents the current state of script execution.
+ // Passed as the first argument to most functions.
+ class ExecState : private Register {
+ public:
+ JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
+ CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
+ ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
+
+ JSValuePtr thisValue();
+
+ // Global object in which execution began.
+ JSGlobalObject* dynamicGlobalObject();
+
+ // Global object in which the currently executing code was defined.
+ // Differs from dynamicGlobalObject() during function calls across web browser frames.
+ JSGlobalObject* lexicalGlobalObject() const
+ {
+ return scopeChain()->globalObject();
+ }
+
+ // Differs from lexicalGlobalObject because this will have DOM window shell rather than
+ // the actual DOM window, which can't be "this" for security reasons.
+ JSObject* globalThisValue() const
+ {
+ return scopeChain()->globalThisObject();
+ }
+
+ // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
+ // We should make this more uniform and either use a reference everywhere
+ // or a pointer everywhere.
+ JSGlobalData& globalData() const
+ {
+ return *scopeChain()->globalData;
+ }
+
+ // Convenience functions for access to global data.
+ // It takes a few memory references to get from a call frame to the global data
+ // pointer, so these are inefficient, and should be used sparingly in new code.
+ // But they're used in many places in legacy code, so they're not going away any time soon.
+
+ void setException(JSValuePtr exception) { globalData().exception = exception; }
+ void clearException() { globalData().exception = noValue(); }
+ JSValuePtr exception() const { return globalData().exception; }
+ JSValuePtr* exceptionSlot() { return &globalData().exception; }
+ bool hadException() const { return globalData().exception; }
+
+ const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
+ const ArgList& emptyList() const { return *globalData().emptyList; }
+ Interpreter* interpreter() { return globalData().interpreter; }
+ Heap* heap() { return &globalData().heap; }
+
+ static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
+ static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
+ static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
+ static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
+ static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
+ static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
+ static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
+
+ private:
+ friend class Arguments;
+ friend class JSActivation;
+ friend class JSGlobalObject;
+ friend class Interpreter;
+
+ static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
+ Register* registers() { return this; }
+
+ CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
+
+ int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
+ CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
+ Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
+ Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
+ int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
+
+ void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
+ void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
+ void setCalleeArguments(Arguments* arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; }
+ void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; }
+ void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
+ void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; }
+
+ ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
+ CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
+ {
+ ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
+
+ setCodeBlock(codeBlock);
+ setScopeChain(scopeChain);
+ setCallerFrame(callerFrame);
+ this[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
+ this[RegisterFile::ReturnValueRegister] = returnValueRegister;
+ setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
+ setCallee(function);
+ setCalleeArguments(0);
+ }
+
+ static const intptr_t HostCallFrameFlag = 1;
+
+ static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
+ bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
+ CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
+ CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
+
+ ExecState();
+ ~ExecState();
+ };
+
+} // namespace JSC
+
+#endif // CallFrame_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Interpreter.h"
+
+#include "Arguments.h"
+#include "BatchedTransitionOptimizer.h"
+#include "CodeBlock.h"
+#include "DebuggerCallFrame.h"
+#include "EvalCodeCache.h"
+#include "ExceptionHelpers.h"
+#include "CallFrame.h"
+#include "GlobalEvalFunction.h"
+#include "JSActivation.h"
+#include "JSArray.h"
+#include "JSByteArray.h"
+#include "JSFunction.h"
+#include "JSNotAnObject.h"
+#include "JSPropertyNameIterator.h"
+#include "JSStaticScopeObject.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "Parser.h"
+#include "Profiler.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "Register.h"
+#include "Collector.h"
+#include "Debugger.h"
+#include "Operations.h"
+#include "SamplingTool.h"
+#include <stdio.h>
+
+#if ENABLE(JIT)
+#include "JIT.h"
+#endif
+
+#if ENABLE(ASSEMBLER)
+#include "AssemblerBuffer.h"
+#endif
+
+#if PLATFORM(DARWIN)
+#include <mach/mach.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if PLATFORM(WIN_OS)
+#include <windows.h>
+#endif
+
+#if PLATFORM(QT)
+#include <QDateTime>
+#endif
+
+using namespace std;
+
+namespace JSC {
+
+// Preferred number of milliseconds between each timeout check
+static const int preferredScriptCheckTimeInterval = 1000;
+
+static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, void* pc)
+{
+#if ENABLE(JIT)
+ return codeBlock->getBytecodeIndex(callFrame, pc);
+#else
+ UNUSED_PARAM(callFrame);
+ return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
+#endif
+}
+
+// Returns the depth of the scope chain within a given call frame.
+static int depth(CodeBlock* codeBlock, ScopeChain& sc)
+{
+ if (!codeBlock->needsFullScopeChain())
+ return 0;
+ return sc.localDepth();
+}
+
+static inline bool jsLess(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
+{
+ if (JSValuePtr::areBothInt32Fast(v1, v2))
+ return v1.getInt32Fast() < v2.getInt32Fast();
+
+ double n1;
+ double n2;
+ if (v1.getNumber(n1) && v2.getNumber(n2))
+ return n1 < n2;
+
+ Interpreter* interpreter = callFrame->interpreter();
+ if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
+ return asString(v1)->value() < asString(v2)->value();
+
+ JSValuePtr p1;
+ JSValuePtr p2;
+ bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+
+ if (wasNotString1 | wasNotString2)
+ return n1 < n2;
+
+ return asString(p1)->value() < asString(p2)->value();
+}
+
+static inline bool jsLessEq(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
+{
+ if (JSValuePtr::areBothInt32Fast(v1, v2))
+ return v1.getInt32Fast() <= v2.getInt32Fast();
+
+ double n1;
+ double n2;
+ if (v1.getNumber(n1) && v2.getNumber(n2))
+ return n1 <= n2;
+
+ Interpreter* interpreter = callFrame->interpreter();
+ if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
+ return !(asString(v2)->value() < asString(v1)->value());
+
+ JSValuePtr p1;
+ JSValuePtr p2;
+ bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+
+ if (wasNotString1 | wasNotString2)
+ return n1 <= n2;
+
+ return !(asString(p2)->value() < asString(p1)->value());
+}
+
+static NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
+{
+ // exception for the Date exception in defaultValue()
+ JSValuePtr p1 = v1.toPrimitive(callFrame);
+ JSValuePtr p2 = v2.toPrimitive(callFrame);
+
+ if (p1.isString() || p2.isString()) {
+ RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep());
+ if (!value)
+ return throwOutOfMemoryError(callFrame);
+ return jsString(callFrame, value.release());
+ }
+
+ return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
+}
+
+// Fast-path choices here are based on frequency data from SunSpider:
+// <times> Add case: <t1> <t2>
+// ---------------------------
+// 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
+// 247412 Add case: 5 5
+// 20900 Add case: 5 6
+// 13962 Add case: 5 3
+// 4000 Add case: 3 5
+
+static ALWAYS_INLINE JSValuePtr jsAdd(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
+{
+ double left;
+ double right = 0.0;
+
+ bool rightIsNumber = v2.getNumber(right);
+ if (rightIsNumber && v1.getNumber(left))
+ return jsNumber(callFrame, left + right);
+
+ bool leftIsString = v1.isString();
+ if (leftIsString && v2.isString()) {
+ RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
+ if (!value)
+ return throwOutOfMemoryError(callFrame);
+ return jsString(callFrame, value.release());
+ }
+
+ if (rightIsNumber & leftIsString) {
+ RefPtr<UString::Rep> value = v2.isInt32Fast() ?
+ concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
+ concatenate(asString(v1)->value().rep(), right);
+
+ if (!value)
+ return throwOutOfMemoryError(callFrame);
+ return jsString(callFrame, value.release());
+ }
+
+ // All other cases are pretty uncommon
+ return jsAddSlowCase(callFrame, v1, v2);
+}
+
+static JSValuePtr jsTypeStringForValue(CallFrame* callFrame, JSValuePtr v)
+{
+ if (v.isUndefined())
+ return jsNontrivialString(callFrame, "undefined");
+ if (v.isBoolean())
+ return jsNontrivialString(callFrame, "boolean");
+ if (v.isNumber())
+ return jsNontrivialString(callFrame, "number");
+ if (v.isString())
+ return jsNontrivialString(callFrame, "string");
+ if (v.isObject()) {
+ // Return "undefined" for objects that should be treated
+ // as null when doing comparisons.
+ if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
+ return jsNontrivialString(callFrame, "undefined");
+ CallData callData;
+ if (asObject(v)->getCallData(callData) != CallTypeNone)
+ return jsNontrivialString(callFrame, "function");
+ }
+ return jsNontrivialString(callFrame, "object");
+}
+
+static bool jsIsObjectType(JSValuePtr v)
+{
+ if (!v.isCell())
+ return v.isNull();
+
+ JSType type = asCell(v)->structure()->typeInfo().type();
+ if (type == NumberType || type == StringType)
+ return false;
+ if (type == ObjectType) {
+ if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
+ return false;
+ CallData callData;
+ if (asObject(v)->getCallData(callData) != CallTypeNone)
+ return false;
+ }
+ return true;
+}
+
+static bool jsIsFunctionType(JSValuePtr v)
+{
+ if (v.isObject()) {
+ CallData callData;
+ if (asObject(v)->getCallData(callData) != CallTypeNone)
+ return true;
+ }
+ return false;
+}
+
+NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+{
+ int dst = (vPC + 1)->u.operand;
+ int property = (vPC + 2)->u.operand;
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& ident = codeBlock->identifier(property);
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ exceptionValue = callFrame->globalData().exception;
+ if (exceptionValue)
+ return false;
+ callFrame[dst] = JSValuePtr(result);
+ return true;
+ }
+ } while (++iter != end);
+ exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+ return false;
+}
+
+NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+{
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ int dst = (vPC + 1)->u.operand;
+ int property = (vPC + 2)->u.operand;
+ int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain();
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+ while (skip--) {
+ ++iter;
+ ASSERT(iter != end);
+ }
+ Identifier& ident = codeBlock->identifier(property);
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ exceptionValue = callFrame->globalData().exception;
+ if (exceptionValue)
+ return false;
+ callFrame[dst] = JSValuePtr(result);
+ return true;
+ }
+ } while (++iter != end);
+ exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+ return false;
+}
+
+NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+{
+ int dst = (vPC + 1)->u.operand;
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
+ ASSERT(globalObject->isGlobalObject());
+ int property = (vPC + 3)->u.operand;
+ Structure* structure = (vPC + 4)->u.structure;
+ int offset = (vPC + 5)->u.operand;
+
+ if (structure == globalObject->structure()) {
+ callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset));
+ return true;
+ }
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& ident = codeBlock->identifier(property);
+ PropertySlot slot(globalObject);
+ if (globalObject->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
+ if (vPC[4].u.structure)
+ vPC[4].u.structure->deref();
+ globalObject->structure()->ref();
+ vPC[4] = globalObject->structure();
+ vPC[5] = slot.cachedOffset();
+ callFrame[dst] = JSValuePtr(result);
+ return true;
+ }
+
+ exceptionValue = callFrame->globalData().exception;
+ if (exceptionValue)
+ return false;
+ callFrame[dst] = JSValuePtr(result);
+ return true;
+ }
+
+ exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+ return false;
+}
+
+static ALWAYS_INLINE JSValuePtr inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
+{
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator next = iter;
+ ++next;
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+
+ PropertySlot slot;
+ JSObject* base;
+ while (true) {
+ base = *iter;
+ if (next == end || base->getPropertySlot(callFrame, property, slot))
+ return base;
+
+ iter = next;
+ ++next;
+ }
+
+ ASSERT_NOT_REACHED();
+ return noValue();
+}
+
+NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
+{
+ int dst = (vPC + 1)->u.operand;
+ int property = (vPC + 2)->u.operand;
+ callFrame[dst] = JSValuePtr(inlineResolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
+}
+
+NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+{
+ int baseDst = (vPC + 1)->u.operand;
+ int propDst = (vPC + 2)->u.operand;
+ int property = (vPC + 3)->u.operand;
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+
+ // FIXME: add scopeDepthIsZero optimization
+
+ ASSERT(iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& ident = codeBlock->identifier(property);
+ JSObject* base;
+ do {
+ base = *iter;
+ PropertySlot slot(base);
+ if (base->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ exceptionValue = callFrame->globalData().exception;
+ if (exceptionValue)
+ return false;
+ callFrame[propDst] = JSValuePtr(result);
+ callFrame[baseDst] = JSValuePtr(base);
+ return true;
+ }
+ ++iter;
+ } while (iter != end);
+
+ exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+ return false;
+}
+
+NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+{
+ int baseDst = (vPC + 1)->u.operand;
+ int funcDst = (vPC + 2)->u.operand;
+ int property = (vPC + 3)->u.operand;
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+
+ // FIXME: add scopeDepthIsZero optimization
+
+ ASSERT(iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& ident = codeBlock->identifier(property);
+ JSObject* base;
+ do {
+ base = *iter;
+ PropertySlot slot(base);
+ if (base->getPropertySlot(callFrame, ident, slot)) {
+ // ECMA 11.2.3 says that if we hit an activation the this value should be null.
+ // However, section 10.2.3 says that in the case where the value provided
+ // by the caller is null, the global object should be used. It also says
+ // that the section does not apply to internal functions, but for simplicity
+ // of implementation we use the global object anyway here. This guarantees
+ // that in host objects you always get a valid object for this.
+ // We also handle wrapper substitution for the global object at the same time.
+ JSObject* thisObj = base->toThisObject(callFrame);
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ exceptionValue = callFrame->globalData().exception;
+ if (exceptionValue)
+ return false;
+
+ callFrame[baseDst] = JSValuePtr(thisObj);
+ callFrame[funcDst] = JSValuePtr(result);
+ return true;
+ }
+ ++iter;
+ } while (iter != end);
+
+ exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+ return false;
+}
+
+ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
+{
+ Register* r = callFrame->registers();
+ Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
+
+ if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
+ if (UNLIKELY(!registerFile->grow(newEnd)))
+ return 0;
+ r += registerOffset;
+ } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
+ size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
+ registerOffset += omittedArgCount;
+ newEnd += omittedArgCount;
+ if (!registerFile->grow(newEnd))
+ return 0;
+ r += registerOffset;
+
+ Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
+ for (size_t i = 0; i < omittedArgCount; ++i)
+ argv[i] = jsUndefined();
+ } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
+ size_t numParameters = newCodeBlock->m_numParameters;
+ registerOffset += numParameters;
+ newEnd += numParameters;
+
+ if (!registerFile->grow(newEnd))
+ return 0;
+ r += registerOffset;
+
+ Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
+ for (size_t i = 0; i < numParameters; ++i)
+ argv[i + argc] = argv[i];
+ }
+
+ return CallFrame::create(r);
+}
+
+static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData)
+{
+ if (value.isObject())
+ return false;
+ exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+ return true;
+}
+
+NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue)
+{
+ if (argc < 2)
+ return jsUndefined();
+
+ JSValuePtr program = argv[1].jsValue(callFrame);
+
+ if (!program.isString())
+ return program;
+
+ UString programSource = asString(program)->value();
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
+
+ JSValuePtr result = jsUndefined();
+ if (evalNode)
+ result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
+
+ return result;
+}
+
+Interpreter::Interpreter()
+ : m_sampler(0)
+#if ENABLE(JIT)
+ , m_ctiArrayLengthTrampoline(0)
+ , m_ctiStringLengthTrampoline(0)
+ , m_ctiVirtualCallPreLink(0)
+ , m_ctiVirtualCallLink(0)
+ , m_ctiVirtualCall(0)
+#endif
+ , m_reentryDepth(0)
+ , m_timeoutTime(0)
+ , m_timeAtLastCheckTimeout(0)
+ , m_timeExecuting(0)
+ , m_timeoutCheckCount(0)
+ , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
+{
+ initTimeout();
+ privateExecute(InitializeAndReturn, 0, 0, 0);
+
+ // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
+ void* storage = fastMalloc(sizeof(CollectorBlock));
+
+ JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
+ m_jsArrayVptr = jsArray->vptr();
+ jsArray->~JSCell();
+
+ JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+ m_jsByteArrayVptr = jsByteArray->vptr();
+ jsByteArray->~JSCell();
+
+ JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
+ m_jsStringVptr = jsString->vptr();
+ jsString->~JSCell();
+
+ JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
+ m_jsFunctionVptr = jsFunction->vptr();
+ jsFunction->~JSCell();
+
+ fastFree(storage);
+}
+
+void Interpreter::initialize(JSGlobalData* globalData)
+{
+#if ENABLE(JIT)
+ JIT::compileCTIMachineTrampolines(globalData);
+#else
+ UNUSED_PARAM(globalData);
+#endif
+}
+
+Interpreter::~Interpreter()
+{
+}
+
+#ifndef NDEBUG
+
+void Interpreter::dumpCallFrame(CallFrame* callFrame)
+{
+ callFrame->codeBlock()->dump(callFrame);
+ dumpRegisters(callFrame);
+}
+
+void Interpreter::dumpRegisters(CallFrame* callFrame)
+{
+ printf("Register frame: \n\n");
+ printf("----------------------------------------------------\n");
+ printf(" use | address | value \n");
+ printf("----------------------------------------------------\n");
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile();
+ const Register* it;
+ const Register* end;
+
+ if (codeBlock->codeType() == GlobalCode) {
+ it = registerFile->lastGlobal();
+ end = it + registerFile->numGlobals();
+ while (it != end) {
+ printf("[global var] | %10p | %10p \n", it, (*it).v());
+ ++it;
+ }
+ printf("----------------------------------------------------\n");
+ }
+
+ it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
+ printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
+ end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
+ if (it != end) {
+ do {
+ printf("[param] | %10p | %10p \n", it, (*it).v());
+ ++it;
+ } while (it != end);
+ }
+ printf("----------------------------------------------------\n");
+
+ printf("[CodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[ScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[CallerRegisters] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[ReturnPC] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("[OptionalCalleeArguments] | %10p | %10p \n", it, (*it).v()); ++it;
+ printf("----------------------------------------------------\n");
+
+ int registerCount = 0;
+
+ end = it + codeBlock->m_numVars;
+ if (it != end) {
+ do {
+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
+ ++it;
+ ++registerCount;
+ } while (it != end);
+ }
+ printf("----------------------------------------------------\n");
+
+ end = it + codeBlock->m_numConstants;
+ if (it != end) {
+ do {
+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
+ ++it;
+ ++registerCount;
+ } while (it != end);
+ }
+ printf("----------------------------------------------------\n");
+
+ end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars;
+ if (it != end) {
+ do {
+ printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
+ ++it;
+ ++registerCount;
+ } while (it != end);
+ }
+ printf("----------------------------------------------------\n");
+}
+
+#endif
+
+bool Interpreter::isOpcode(Opcode opcode)
+{
+#if HAVE(COMPUTED_GOTO)
+ return opcode != HashTraits<Opcode>::emptyValue()
+ && !HashTraits<Opcode>::isDeletedValue(opcode)
+ && m_opcodeIDTable.contains(opcode);
+#else
+ return opcode >= 0 && opcode <= op_end;
+#endif
+}
+
+NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
+{
+ CodeBlock* oldCodeBlock = codeBlock;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
+ DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
+ if (callFrame->callee())
+ debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
+ else
+ debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
+ }
+
+ if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
+ if (callFrame->callee())
+ profiler->didExecute(callFrame, callFrame->callee());
+ else
+ profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo());
+ }
+
+ // If this call frame created an activation or an 'arguments' object, tear it off.
+ if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
+ while (!scopeChain->object->isObject(&JSActivation::info))
+ scopeChain = scopeChain->pop();
+ static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
+ } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
+ if (!arguments->isTornOff())
+ arguments->copyRegisters();
+ }
+
+ if (oldCodeBlock->needsFullScopeChain())
+ scopeChain->deref();
+
+ void* returnPC = callFrame->returnPC();
+ callFrame = callFrame->callerFrame();
+ if (callFrame->hasHostCallFrameFlag())
+ return false;
+
+ codeBlock = callFrame->codeBlock();
+ bytecodeOffset = bytecodeOffsetForPC(callFrame, codeBlock, returnPC);
+ return true;
+}
+
+NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
+{
+ // Set up the exception object
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ if (exceptionValue.isObject()) {
+ JSObject* exception = asObject(exceptionValue);
+ if (exception->isNotAnObjectErrorStub()) {
+ exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
+ exceptionValue = exception;
+ } else {
+ if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) &&
+ !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) &&
+ !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) &&
+ !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) &&
+ !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) &&
+ !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
+ if (explicitThrow) {
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);
+ exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete);
+
+ // We only hit this path for error messages and throw statements, which don't have a specific failure position
+ // So we just give the full range of the error/throw statement.
+ exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
+ } else
+ exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
+ exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete);
+ exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete);
+ }
+
+ if (exception->isWatchdogException()) {
+ while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
+ // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
+ }
+ return 0;
+ }
+ }
+ }
+
+ if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
+ DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
+ debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset));
+ }
+
+ // If we throw in the middle of a call instruction, we need to notify
+ // the profiler manually that the call instruction has returned, since
+ // we'll never reach the relevant op_profile_did_call.
+ if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
+#if !ENABLE(JIT)
+ if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
+ profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame));
+ else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
+ profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));
+#else
+ int functionRegisterIndex;
+ if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
+ profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));
+#endif
+ }
+
+ // Calculate an exception handler vPC, unwinding call frames as necessary.
+
+ HandlerInfo* handler = 0;
+ while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
+ if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
+ return 0;
+ }
+
+ // Now unwind the scope chain within the exception handler's call frame.
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChain sc(scopeChain);
+ int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
+ ASSERT(scopeDelta >= 0);
+ while (scopeDelta--)
+ scopeChain = scopeChain->pop();
+ callFrame->setScopeChain(scopeChain);
+
+ return handler;
+}
+
+JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception)
+{
+ ASSERT(!scopeChain->globalData->exception);
+
+ if (m_reentryDepth >= MaxReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
+
+ Register* oldEnd = m_registerFile.end();
+ Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
+ if (!m_registerFile.grow(newEnd)) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject());
+
+ JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
+ JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
+ globalObject->copyGlobalsTo(m_registerFile);
+
+ CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
+ newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
+
+ if (codeBlock->needsFullScopeChain())
+ scopeChain->ref();
+
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (*profiler)
+ (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
+
+ JSValuePtr result;
+ {
+ SamplingTool::CallRecord callRecord(m_sampler);
+
+ m_reentryDepth++;
+#if ENABLE(JIT)
+ if (!codeBlock->jitCode())
+ JIT::compile(scopeChain->globalData, codeBlock);
+ result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#else
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
+ m_reentryDepth--;
+ }
+
+ if (*profiler)
+ (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());
+
+ if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
+ lastGlobalObject->copyGlobalsTo(m_registerFile);
+
+ m_registerFile.shrink(oldEnd);
+
+ return result;
+}
+
+JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception)
+{
+ ASSERT(!scopeChain->globalData->exception);
+
+ if (m_reentryDepth >= MaxReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ Register* oldEnd = m_registerFile.end();
+ int argc = 1 + args.size(); // implicit "this" parameter
+
+ if (!m_registerFile.grow(oldEnd + argc)) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
+
+ CallFrame* newCallFrame = CallFrame::create(oldEnd);
+ size_t dst = 0;
+ newCallFrame[0] = JSValuePtr(thisObj);
+ ArgList::const_iterator end = args.end();
+ for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+ newCallFrame[++dst] = *it;
+
+ CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
+ newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
+ if (UNLIKELY(!newCallFrame)) {
+ *exception = createStackOverflowError(callFrame);
+ m_registerFile.shrink(oldEnd);
+ return jsNull();
+ }
+ // a 0 codeBlock indicates a built-in caller
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
+
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (*profiler)
+ (*profiler)->willExecute(callFrame, function);
+
+ JSValuePtr result;
+ {
+ SamplingTool::CallRecord callRecord(m_sampler);
+
+ m_reentryDepth++;
+#if ENABLE(JIT)
+ if (!codeBlock->jitCode())
+ JIT::compile(scopeChain->globalData, codeBlock);
+ result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#else
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
+ m_reentryDepth--;
+ }
+
+ if (*profiler)
+ (*profiler)->didExecute(callFrame, function);
+
+ m_registerFile.shrink(oldEnd);
+ return result;
+}
+
+JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception)
+{
+ return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
+}
+
+JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValuePtr* exception)
+{
+ ASSERT(!scopeChain->globalData->exception);
+
+ if (m_reentryDepth >= MaxReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
+
+ EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);
+
+ JSVariableObject* variableObject;
+ for (ScopeChainNode* node = scopeChain; ; node = node->next) {
+ ASSERT(node);
+ if (node->object->isVariableObject()) {
+ variableObject = static_cast<JSVariableObject*>(node->object);
+ break;
+ }
+ }
+
+ { // Scope for BatchedTransitionOptimizer
+
+ BatchedTransitionOptimizer optimizer(variableObject);
+
+ const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack();
+ DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end();
+ for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
+ const Identifier& ident = (*it).first;
+ if (!variableObject->hasProperty(callFrame, ident)) {
+ PutPropertySlot slot;
+ variableObject->put(callFrame, ident, jsUndefined(), slot);
+ }
+ }
+
+ const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack();
+ DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end();
+ for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
+ PutPropertySlot slot;
+ variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot);
+ }
+
+ }
+
+ Register* oldEnd = m_registerFile.end();
+ Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
+ if (!m_registerFile.grow(newEnd)) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
+
+ CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
+
+ // a 0 codeBlock indicates a built-in caller
+ newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
+
+ if (codeBlock->needsFullScopeChain())
+ scopeChain->ref();
+
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (*profiler)
+ (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
+
+ JSValuePtr result;
+ {
+ SamplingTool::CallRecord callRecord(m_sampler);
+
+ m_reentryDepth++;
+#if ENABLE(JIT)
+ if (!codeBlock->jitCode())
+ JIT::compile(scopeChain->globalData, codeBlock);
+ result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#else
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
+ m_reentryDepth--;
+ }
+
+ if (*profiler)
+ (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo());
+
+ m_registerFile.shrink(oldEnd);
+ return result;
+}
+
+NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
+{
+ Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
+ if (!debugger)
+ return;
+
+ switch (debugHookID) {
+ case DidEnterCallFrame:
+ debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+ return;
+ case WillLeaveCallFrame:
+ debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+ return;
+ case WillExecuteStatement:
+ debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+ return;
+ case WillExecuteProgram:
+ debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+ return;
+ case DidExecuteProgram:
+ debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+ return;
+ case DidReachBreakpoint:
+ debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+ return;
+ }
+}
+
+void Interpreter::resetTimeoutCheck()
+{
+ m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
+ m_timeAtLastCheckTimeout = 0;
+ m_timeExecuting = 0;
+}
+
+// Returns the time the current thread has spent executing, in milliseconds.
+static inline unsigned getCPUTime()
+{
+#if PLATFORM(DARWIN)
+ mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
+ thread_basic_info_data_t info;
+
+ // Get thread information
+ mach_port_t threadPort = mach_thread_self();
+ thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
+ mach_port_deallocate(mach_task_self(), threadPort);
+
+ unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
+ time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
+
+ return time;
+#elif HAVE(SYS_TIME_H)
+ // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#elif PLATFORM(QT)
+ QDateTime t = QDateTime::currentDateTime();
+ return t.toTime_t() * 1000 + t.time().msec();
+#elif PLATFORM(WIN_OS)
+ union {
+ FILETIME fileTime;
+ unsigned long long fileTimeAsLong;
+ } userTime, kernelTime;
+
+ // GetThreadTimes won't accept NULL arguments so we pass these even though
+ // they're not used.
+ FILETIME creationTime, exitTime;
+
+ GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
+
+ return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
+#else
+#error Platform does not have getCurrentTime function
+#endif
+}
+
+// We have to return a JSValue here, gcc seems to produce worse code if
+// we attempt to return a bool
+ALWAYS_INLINE bool Interpreter::checkTimeout(JSGlobalObject* globalObject)
+{
+ unsigned currentTime = getCPUTime();
+
+ if (!m_timeAtLastCheckTimeout) {
+ // Suspicious amount of looping in a script -- start timing it
+ m_timeAtLastCheckTimeout = currentTime;
+ return false;
+ }
+
+ unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
+
+ if (timeDiff == 0)
+ timeDiff = 1;
+
+ m_timeExecuting += timeDiff;
+ m_timeAtLastCheckTimeout = currentTime;
+
+ // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
+ // preferredScriptCheckTimeInterval
+ m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
+ // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
+ // preferred script check time interval.
+ if (m_ticksUntilNextTimeoutCheck == 0)
+ m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
+
+ if (globalObject->shouldInterruptScriptBeforeTimeout())
+ return true;
+
+ if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
+ if (globalObject->shouldInterruptScript())
+ return true;
+
+ resetTimeoutCheck();
+ }
+
+ return false;
+}
+
+NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
+{
+ int dst = (++vPC)->u.operand;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& property = codeBlock->identifier((++vPC)->u.operand);
+ JSValuePtr value = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
+ callFrame[dst] = JSValuePtr(scope);
+
+ return callFrame->scopeChain()->push(scope);
+}
+
+NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot)
+{
+ // Recursive invocation may already have specialized this instruction.
+ if (vPC[0].u.opcode != getOpcode(op_put_by_id))
+ return;
+
+ if (!baseValue.isCell())
+ return;
+
+ // Uncacheable: give up.
+ if (!slot.isCacheable()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = baseCell->structure();
+
+ if (structure->isDictionary()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
+ // Cache miss: record Structure to compare against next time.
+ Structure* lastStructure = vPC[4].u.structure;
+ if (structure != lastStructure) {
+ // First miss: record Structure to compare against next time.
+ if (!lastStructure) {
+ vPC[4] = structure;
+ return;
+ }
+
+ // Second miss: give up.
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
+ // Cache hit: Specialize instruction and ref Structures.
+
+ // If baseCell != slot.base(), then baseCell must be a proxy for another object.
+ if (baseCell != slot.base()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
+ // Structure transition, cache transition info
+ if (slot.type() == PutPropertySlot::NewProperty) {
+ vPC[0] = getOpcode(op_put_by_id_transition);
+ vPC[4] = structure->previousID();
+ vPC[5] = structure;
+ vPC[6] = structure->prototypeChain(callFrame);
+ vPC[7] = slot.cachedOffset();
+ codeBlock->refStructures(vPC);
+ return;
+ }
+
+ vPC[0] = getOpcode(op_put_by_id_replace);
+ vPC[5] = slot.cachedOffset();
+ codeBlock->refStructures(vPC);
+}
+
+NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
+{
+ codeBlock->derefStructures(vPC);
+ vPC[0] = getOpcode(op_put_by_id);
+ vPC[4] = 0;
+}
+
+static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValuePtr baseValue, const PropertySlot& slot)
+{
+ JSCell* cell = asCell(baseValue);
+ size_t count = 0;
+
+ while (slot.slotBase() != cell) {
+ JSValuePtr v = cell->structure()->prototypeForLookup(callFrame);
+
+ // If we didn't find slotBase in baseValue's prototype chain, then baseValue
+ // must be a proxy for another object.
+
+ if (v.isNull())
+ return 0;
+
+ cell = asCell(v);
+
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (cell->structure()->isDictionary())
+ asObject(cell)->setStructure(Structure::fromDictionaryTransition(cell->structure()));
+
+ ++count;
+ }
+
+ ASSERT(count);
+ return count;
+}
+
+NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
+{
+ // Recursive invocation may already have specialized this instruction.
+ if (vPC[0].u.opcode != getOpcode(op_get_by_id))
+ return;
+
+ // FIXME: Cache property access for immediates.
+ if (!baseValue.isCell()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
+ vPC[0] = getOpcode(op_get_array_length);
+ return;
+ }
+
+ if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
+ vPC[0] = getOpcode(op_get_string_length);
+ return;
+ }
+
+ // Uncacheable: give up.
+ if (!slot.isCacheable()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ Structure* structure = asCell(baseValue)->structure();
+
+ if (structure->isDictionary()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ // Cache miss
+ Structure* lastStructure = vPC[4].u.structure;
+ if (structure != lastStructure) {
+ // First miss: record Structure to compare against next time.
+ if (!lastStructure) {
+ vPC[4] = structure;
+ return;
+ }
+
+ // Second miss: give up.
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ // Cache hit: Specialize instruction and ref Structures.
+
+ if (slot.slotBase() == baseValue) {
+ vPC[0] = getOpcode(op_get_by_id_self);
+ vPC[5] = slot.cachedOffset();
+
+ codeBlock->refStructures(vPC);
+ return;
+ }
+
+ if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
+ ASSERT(slot.slotBase().isObject());
+
+ JSObject* baseObject = asObject(slot.slotBase());
+
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (baseObject->structure()->isDictionary())
+ baseObject->setStructure(Structure::fromDictionaryTransition(baseObject->structure()));
+
+ vPC[0] = getOpcode(op_get_by_id_proto);
+ vPC[5] = baseObject->structure();
+ vPC[6] = slot.cachedOffset();
+
+ codeBlock->refStructures(vPC);
+ return;
+ }
+
+ size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
+ if (!count) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ vPC[0] = getOpcode(op_get_by_id_chain);
+ vPC[4] = structure;
+ vPC[5] = structure->prototypeChain(callFrame);
+ vPC[6] = count;
+ vPC[7] = slot.cachedOffset();
+ codeBlock->refStructures(vPC);
+}
+
+NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
+{
+ codeBlock->derefStructures(vPC);
+ vPC[0] = getOpcode(op_get_by_id);
+ vPC[4] = 0;
+}
+
+JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception)
+{
+ // One-time initialization of our address tables. We have to put this code
+ // here because our labels are only in scope inside this function.
+ if (flag == InitializeAndReturn) {
+ #if HAVE(COMPUTED_GOTO)
+ #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id;
+ FOR_EACH_OPCODE_ID(ADD_BYTECODE);
+ #undef ADD_BYTECODE
+
+ #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id);
+ FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
+ #undef ADD_OPCODE_ID
+ ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
+ #endif // HAVE(COMPUTED_GOTO)
+ return noValue();
+ }
+
+#if ENABLE(JIT)
+ // Currently with CTI enabled we never interpret functions
+ ASSERT_NOT_REACHED();
+#endif
+
+ JSGlobalData* globalData = &callFrame->globalData();
+ JSValuePtr exceptionValue = noValue();
+ HandlerInfo* handler = 0;
+
+ Instruction* vPC = callFrame->codeBlock()->instructions().begin();
+ Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
+ unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
+
+#define CHECK_FOR_EXCEPTION() \
+ do { \
+ if (UNLIKELY(globalData->exception != noValue())) { \
+ exceptionValue = globalData->exception; \
+ goto vm_throw; \
+ } \
+ } while (0)
+
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+
+#define CHECK_FOR_TIMEOUT() \
+ if (!--tickCount) { \
+ if (checkTimeout(callFrame->dynamicGlobalObject())) { \
+ exceptionValue = jsNull(); \
+ goto vm_throw; \
+ } \
+ tickCount = m_ticksUntilNextTimeoutCheck; \
+ }
+
+#if ENABLE(OPCODE_SAMPLING)
+ #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
+ #define CTI_SAMPLER ARG_globalData->interpreter->sampler()
+#else
+ #define SAMPLE(codeBlock, vPC)
+ #define CTI_SAMPLER 0
+#endif
+
+#if HAVE(COMPUTED_GOTO)
+ #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode
+#if ENABLE(OPCODE_STATS)
+ #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
+#else
+ #define DEFINE_OPCODE(opcode) opcode:
+#endif
+ NEXT_INSTRUCTION();
+#else
+ #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
+#if ENABLE(OPCODE_STATS)
+ #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
+#else
+ #define DEFINE_OPCODE(opcode) case opcode:
+#endif
+ while (1) { // iterator loop begins
+ interpreterLoopStart:;
+ switch (vPC->u.opcode)
+#endif
+ {
+ DEFINE_OPCODE(op_new_object) {
+ /* new_object dst(r)
+
+ Constructs a new empty Object instance using the original
+ constructor, and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_new_array) {
+ /* new_array dst(r) firstArg(r) argCount(n)
+
+ Constructs a new Array instance using the original
+ constructor, and puts the result in register dst.
+ The array will contain argCount elements with values
+ taken from registers starting at register firstArg.
+ */
+ int dst = (++vPC)->u.operand;
+ int firstArg = (++vPC)->u.operand;
+ int argCount = (++vPC)->u.operand;
+ ArgList args(callFrame->registers() + firstArg, argCount);
+ callFrame[dst] = JSValuePtr(constructArray(callFrame, args));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_new_regexp) {
+ /* new_regexp dst(r) regExp(re)
+
+ Constructs a new RegExp instance using the original
+ constructor from regexp regExp, and puts the result in
+ register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int regExp = (++vPC)->u.operand;
+ callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_mov) {
+ /* mov dst(r) src(r)
+
+ Copies register src to register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = callFrame[src];
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_eq) {
+ /* eq dst(r) src1(r) src2(r)
+
+ Checks whether register src1 and register src2 are equal,
+ as with the ECMAScript '==' operator, and puts the result
+ as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
+ callFrame[dst] = JSFastMath::equal(src1, src2);
+ else {
+ JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_eq_null) {
+ /* eq_null dst(r) src(r)
+
+ Checks whether register src is null, as with the ECMAScript '!='
+ operator, and puts the result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+
+ if (src.isUndefinedOrNull()) {
+ callFrame[dst] = jsBoolean(true);
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+
+ callFrame[dst] = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_neq) {
+ /* neq dst(r) src1(r) src2(r)
+
+ Checks whether register src1 and register src2 are not
+ equal, as with the ECMAScript '!=' operator, and puts the
+ result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
+ callFrame[dst] = JSFastMath::notEqual(src1, src2);
+ else {
+ JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_neq_null) {
+ /* neq_null dst(r) src(r)
+
+ Checks whether register src is not null, as with the ECMAScript '!='
+ operator, and puts the result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+
+ if (src.isUndefinedOrNull()) {
+ callFrame[dst] = jsBoolean(false);
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+
+ callFrame[dst] = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_stricteq) {
+ /* stricteq dst(r) src1(r) src2(r)
+
+ Checks whether register src1 and register src2 are strictly
+ equal, as with the ECMAScript '===' operator, and puts the
+ result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_nstricteq) {
+ /* nstricteq dst(r) src1(r) src2(r)
+
+ Checks whether register src1 and register src2 are not
+ strictly equal, as with the ECMAScript '!==' operator, and
+ puts the result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_less) {
+ /* less dst(r) src1(r) src2(r)
+
+ Checks whether register src1 is less than register src2, as
+ with the ECMAScript '<' operator, and puts the result as
+ a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_lesseq) {
+ /* lesseq dst(r) src1(r) src2(r)
+
+ Checks whether register src1 is less than or equal to
+ register src2, as with the ECMAScript '<=' operator, and
+ puts the result as a boolean in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_pre_inc) {
+ /* pre_inc srcDst(r)
+
+ Converts register srcDst to number, adds one, and puts the result
+ back in register srcDst.
+ */
+ int srcDst = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ if (JSFastMath::canDoFastAdditiveOperations(v))
+ callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
+ else {
+ JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
+ CHECK_FOR_EXCEPTION();
+ callFrame[srcDst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_pre_dec) {
+ /* pre_dec srcDst(r)
+
+ Converts register srcDst to number, subtracts one, and puts the result
+ back in register srcDst.
+ */
+ int srcDst = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ if (JSFastMath::canDoFastAdditiveOperations(v))
+ callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
+ else {
+ JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
+ CHECK_FOR_EXCEPTION();
+ callFrame[srcDst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_post_inc) {
+ /* post_inc dst(r) srcDst(r)
+
+ Converts register srcDst to number. The number itself is
+ written to register dst, and the number plus one is written
+ back to register srcDst.
+ */
+ int dst = (++vPC)->u.operand;
+ int srcDst = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ if (JSFastMath::canDoFastAdditiveOperations(v)) {
+ callFrame[dst] = v;
+ callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
+ } else {
+ JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = number;
+ callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1));
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_post_dec) {
+ /* post_dec dst(r) srcDst(r)
+
+ Converts register srcDst to number. The number itself is
+ written to register dst, and the number minus one is written
+ back to register srcDst.
+ */
+ int dst = (++vPC)->u.operand;
+ int srcDst = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ if (JSFastMath::canDoFastAdditiveOperations(v)) {
+ callFrame[dst] = v;
+ callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
+ } else {
+ JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = number;
+ callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1));
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_to_jsnumber) {
+ /* to_jsnumber dst(r) src(r)
+
+ Converts register src to number, and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+
+ JSValuePtr srcVal = callFrame[src].jsValue(callFrame);
+
+ if (LIKELY(srcVal.isNumber()))
+ callFrame[dst] = callFrame[src];
+ else {
+ JSValuePtr result = srcVal.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_negate) {
+ /* negate dst(r) src(r)
+
+ Converts register src to number, negates it, and puts the
+ result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ ++vPC;
+ double v;
+ if (src.getNumber(v))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, -v));
+ else {
+ JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_add) {
+ /* add dst(r) src1(r) src2(r)
+
+ Adds register src1 and register src2, and puts the result
+ in register dst. (JS add may be string concatenation or
+ numeric add, depending on the types of the operands.)
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
+ callFrame[dst] = JSValuePtr(JSFastMath::addImmediateNumbers(src1, src2));
+ else {
+ JSValuePtr result = jsAdd(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_mul) {
+ /* mul dst(r) src1(r) src2(r)
+
+ Multiplies register src1 and register src2 (converted to
+ numbers), and puts the product in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ double left;
+ double right;
+ if (JSValuePtr::areBothInt32Fast(src1, src2)) {
+ int32_t left = src1.getInt32Fast();
+ int32_t right = src2.getInt32Fast();
+ if ((left | right) >> 15 == 0)
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
+ else
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right)));
+ } else if (src1.getNumber(left) && src2.getNumber(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_div) {
+ /* div dst(r) dividend(r) divisor(r)
+
+ Divides register dividend (converted to number) by the
+ register divisor (converted to number), and puts the
+ quotient in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ double left;
+ double right;
+ if (dividend.getNumber(left) && divisor.getNumber(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left / right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_mod) {
+ /* mod dst(r) dividend(r) divisor(r)
+
+ Divides register dividend (converted to number) by
+ register divisor (converted to number), and puts the
+ remainder in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int dividend = (++vPC)->u.operand;
+ int divisor = (++vPC)->u.operand;
+
+ JSValuePtr dividendValue = callFrame[dividend].jsValue(callFrame);
+ JSValuePtr divisorValue = callFrame[divisor].jsValue(callFrame);
+
+ if (JSValuePtr::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != js0()) {
+ // We expect the result of the modulus of a number that was representable as an int32 to also be representable
+ // as an int32.
+ JSValuePtr result = JSValuePtr::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast());
+ ASSERT(result);
+ callFrame[dst] = result;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+
+ double d = dividendValue.toNumber(callFrame);
+ JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame)));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_sub) {
+ /* sub dst(r) src1(r) src2(r)
+
+ Subtracts register src2 (converted to number) from register
+ src1 (converted to number), and puts the difference in
+ register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ double left;
+ double right;
+ if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
+ callFrame[dst] = JSValuePtr(JSFastMath::subImmediateNumbers(src1, src2));
+ else if (src1.getNumber(left) && src2.getNumber(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left - right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_lshift) {
+ /* lshift dst(r) val(r) shift(r)
+
+ Performs left shift of register val (converted to int32) by
+ register shift (converted to uint32), and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t left;
+ uint32_t right;
+ if (JSValuePtr::areBothInt32Fast(val, shift))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
+ else if (val.numberToInt32(left) && shift.numberToUInt32(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left << (right & 0x1f)));
+ else {
+ JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_rshift) {
+ /* rshift dst(r) val(r) shift(r)
+
+ Performs arithmetic right shift of register val (converted
+ to int32) by register shift (converted to
+ uint32), and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t left;
+ uint32_t right;
+ if (JSFastMath::canDoFastRshift(val, shift))
+ callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ else if (val.numberToInt32(left) && shift.numberToUInt32(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left >> (right & 0x1f)));
+ else {
+ JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_urshift) {
+ /* rshift dst(r) val(r) shift(r)
+
+ Performs logical right shift of register val (converted
+ to uint32) by register shift (converted to
+ uint32), and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (JSFastMath::canDoFastUrshift(val, shift))
+ callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ else {
+ JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_bitand) {
+ /* bitand dst(r) src1(r) src2(r)
+
+ Computes bitwise AND of register src1 (converted to int32)
+ and register src2 (converted to int32), and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t left;
+ int32_t right;
+ if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
+ callFrame[dst] = JSValuePtr(JSFastMath::andImmediateNumbers(src1, src2));
+ else if (src1.numberToInt32(left) && src2.numberToInt32(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left & right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_bitxor) {
+ /* bitxor dst(r) src1(r) src2(r)
+
+ Computes bitwise XOR of register src1 (converted to int32)
+ and register src2 (converted to int32), and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t left;
+ int32_t right;
+ if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
+ callFrame[dst] = JSValuePtr(JSFastMath::xorImmediateNumbers(src1, src2));
+ else if (src1.numberToInt32(left) && src2.numberToInt32(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left ^ right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_bitor) {
+ /* bitor dst(r) src1(r) src2(r)
+
+ Computes bitwise OR of register src1 (converted to int32)
+ and register src2 (converted to int32), and puts the
+ result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t left;
+ int32_t right;
+ if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
+ callFrame[dst] = JSValuePtr(JSFastMath::orImmediateNumbers(src1, src2));
+ else if (src1.numberToInt32(left) && src2.numberToInt32(right))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, left | right));
+ else {
+ JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_bitnot) {
+ /* bitnot dst(r) src(r)
+
+ Computes bitwise NOT of register src1 (converted to int32),
+ and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int32_t value;
+ if (src.numberToInt32(value))
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, ~value));
+ else {
+ JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ }
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_not) {
+ /* not dst(r) src(r)
+
+ Computes logical NOT of register src (converted to
+ boolean), and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_instanceof) {
+ /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
+
+ Tests whether register value is an instance of register
+ constructor, and puts the boolean result in register
+ dst. Register constructorProto must contain the "prototype"
+ property (not the actual prototype) of the object in
+ register constructor. This lookup is separated so that
+ polymorphic inline caching can apply.
+
+ Raises an exception if register constructor is not an
+ object.
+ */
+ int dst = vPC[1].u.operand;
+ int value = vPC[2].u.operand;
+ int base = vPC[3].u.operand;
+ int baseProto = vPC[4].u.operand;
+
+ JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
+
+ if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+ goto vm_throw;
+
+ JSObject* baseObj = asObject(baseVal);
+ callFrame[dst] = jsBoolean(baseObj->structure()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false);
+
+ vPC += 5;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_typeof) {
+ /* typeof dst(r) src(r)
+
+ Determines the type string for src according to ECMAScript
+ rules, and puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_undefined) {
+ /* is_undefined dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "undefined", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[src].jsValue(callFrame);
+ callFrame[dst] = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_boolean) {
+ /* is_boolean dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "boolean", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_number) {
+ /* is_number dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "number", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_string) {
+ /* is_string dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "string", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_object) {
+ /* is_object dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "object", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_is_function) {
+ /* is_function dst(r) src(r)
+
+ Determines whether the type string for src according to
+ the ECMAScript rules is "function", and puts the result
+ in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_in) {
+ /* in dst(r) property(r) base(r)
+
+ Tests whether register base has a property named register
+ property, and puts the boolean result in register dst.
+
+ Raises an exception if register constructor is not an
+ object.
+ */
+ int dst = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+ int base = (++vPC)->u.operand;
+
+ JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
+ if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+ goto vm_throw;
+
+ JSObject* baseObj = asObject(baseVal);
+
+ JSValuePtr propName = callFrame[property].jsValue(callFrame);
+
+ uint32_t i;
+ if (propName.getUInt32(i))
+ callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, i));
+ else {
+ Identifier property(callFrame, propName.toString(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, property));
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve) {
+ /* resolve dst(r) property(id)
+
+ Looks up the property named by identifier property in the
+ scope chain, and writes the resulting value to register
+ dst. If the property is not found, raises an exception.
+ */
+ if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
+ goto vm_throw;
+
+ vPC += 3;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve_skip) {
+ /* resolve_skip dst(r) property(id) skip(n)
+
+ Looks up the property named by identifier property in the
+ scope chain skipping the top 'skip' levels, and writes the resulting
+ value to register dst. If the property is not found, raises an exception.
+ */
+ if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
+ goto vm_throw;
+
+ vPC += 4;
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve_global) {
+ /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
+
+ Performs a dynamic property lookup for the given property, on the provided
+ global object. If structure matches the Structure of the global then perform
+ a fast lookup using the case offset, otherwise fall back to a full resolve and
+ cache the new structure and offset
+ */
+ if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
+ goto vm_throw;
+
+ vPC += 6;
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_global_var) {
+ /* get_global_var dst(r) globalObject(c) index(n)
+
+ Gets the global var at global slot index and places it in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
+ ASSERT(scope->isGlobalObject());
+ int index = (++vPC)->u.operand;
+
+ callFrame[dst] = scope->registerAt(index);
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_global_var) {
+ /* put_global_var globalObject(c) index(n) value(r)
+
+ Puts value into global slot index.
+ */
+ JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
+ ASSERT(scope->isGlobalObject());
+ int index = (++vPC)->u.operand;
+ int value = (++vPC)->u.operand;
+
+ scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_scoped_var) {
+ /* get_scoped_var dst(r) index(n) skip(n)
+
+ Loads the contents of the index-th local from the scope skip nodes from
+ the top of the scope chain, and places it in register dst
+ */
+ int dst = (++vPC)->u.operand;
+ int index = (++vPC)->u.operand;
+ int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+ while (skip--) {
+ ++iter;
+ ASSERT(iter != end);
+ }
+
+ ASSERT((*iter)->isVariableObject());
+ JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
+ callFrame[dst] = scope->registerAt(index);
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_scoped_var) {
+ /* put_scoped_var index(n) skip(n) value(r)
+
+ */
+ int index = (++vPC)->u.operand;
+ int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
+ int value = (++vPC)->u.operand;
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+ while (skip--) {
+ ++iter;
+ ASSERT(iter != end);
+ }
+
+ ASSERT((*iter)->isVariableObject());
+ JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
+ scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve_base) {
+ /* resolve_base dst(r) property(id)
+
+ Searches the scope chain for an object containing
+ identifier property, and if one is found, writes it to
+ register dst. If none is found, the outermost scope (which
+ will be the global object) is stored in register dst.
+ */
+ resolveBase(callFrame, vPC);
+
+ vPC += 3;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve_with_base) {
+ /* resolve_with_base baseDst(r) propDst(r) property(id)
+
+ Searches the scope chain for an object containing
+ identifier property, and if one is found, writes it to
+ register srcDst, and the retrieved property value to register
+ propDst. If the property is not found, raises an exception.
+
+ This is more efficient than doing resolve_base followed by
+ resolve, or resolve_base followed by get_by_id, as it
+ avoids duplicate hash lookups.
+ */
+ if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
+ goto vm_throw;
+
+ vPC += 4;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_resolve_func) {
+ /* resolve_func baseDst(r) funcDst(r) property(id)
+
+ Searches the scope chain for an object containing
+ identifier property, and if one is found, writes the
+ appropriate object to use as "this" when calling its
+ properties to register baseDst; and the retrieved property
+ value to register propDst. If the property is not found,
+ raises an exception.
+
+ This differs from resolve_with_base, because the
+ global this value will be substituted for activations or
+ the global object, which is the right behavior for function
+ calls but not for other property lookup.
+ */
+ if (UNLIKELY(!resolveBaseAndFunc(callFrame, vPC, exceptionValue)))
+ goto vm_throw;
+
+ vPC += 4;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id) {
+ /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
+
+ Generic property access: Gets the property named by identifier
+ property from the value base, and puts the result in register dst.
+ */
+ int dst = vPC[1].u.operand;
+ int base = vPC[2].u.operand;
+ int property = vPC[3].u.operand;
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ Identifier& ident = codeBlock->identifier(property);
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ CHECK_FOR_EXCEPTION();
+
+ tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
+
+ callFrame[dst] = result;
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_self) {
+ /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
+
+ Cached property access: Attempts to get a cached property from the
+ value base. If the cache misses, op_get_by_id_self reverts to
+ op_get_by_id.
+ */
+ int base = vPC[2].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+
+ if (LIKELY(baseValue.isCell())) {
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = vPC[4].u.structure;
+
+ if (LIKELY(baseCell->structure() == structure)) {
+ ASSERT(baseCell->isObject());
+ JSObject* baseObject = asObject(baseCell);
+ int dst = vPC[1].u.operand;
+ int offset = vPC[5].u.operand;
+
+ ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+ callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ }
+
+ uncacheGetByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_proto) {
+ /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
+
+ Cached property access: Attempts to get a cached property from the
+ value base's prototype. If the cache misses, op_get_by_id_proto
+ reverts to op_get_by_id.
+ */
+ int base = vPC[2].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+
+ if (LIKELY(baseValue.isCell())) {
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = vPC[4].u.structure;
+
+ if (LIKELY(baseCell->structure() == structure)) {
+ ASSERT(structure->prototypeForLookup(callFrame).isObject());
+ JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
+ Structure* prototypeStructure = vPC[5].u.structure;
+
+ if (LIKELY(protoObject->structure() == prototypeStructure)) {
+ int dst = vPC[1].u.operand;
+ int offset = vPC[6].u.operand;
+
+ ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
+ callFrame[dst] = JSValuePtr(protoObject->getDirectOffset(offset));
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ }
+ }
+
+ uncacheGetByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_self_list) {
+ // Polymorphic self access caching currently only supported when JITting.
+ ASSERT_NOT_REACHED();
+ // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_proto_list) {
+ // Polymorphic prototype access caching currently only supported when JITting.
+ ASSERT_NOT_REACHED();
+ // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_chain) {
+ /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
+
+ Cached property access: Attempts to get a cached property from the
+ value base's prototype chain. If the cache misses, op_get_by_id_chain
+ reverts to op_get_by_id.
+ */
+ int base = vPC[2].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+
+ if (LIKELY(baseValue.isCell())) {
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = vPC[4].u.structure;
+
+ if (LIKELY(baseCell->structure() == structure)) {
+ RefPtr<Structure>* it = vPC[5].u.structureChain->head();
+ size_t count = vPC[6].u.operand;
+ RefPtr<Structure>* end = it + count;
+
+ while (true) {
+ JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
+
+ if (UNLIKELY(baseObject->structure() != (*it).get()))
+ break;
+
+ if (++it == end) {
+ int dst = vPC[1].u.operand;
+ int offset = vPC[7].u.operand;
+
+ ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+ callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+
+ // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
+ baseCell = baseObject;
+ }
+ }
+ }
+
+ uncacheGetByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_id_generic) {
+ /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
+
+ Generic property access: Gets the property named by identifier
+ property from the value base, and puts the result in register dst.
+ */
+ int dst = vPC[1].u.operand;
+ int base = vPC[2].u.operand;
+ int property = vPC[3].u.operand;
+
+ Identifier& ident = callFrame->codeBlock()->identifier(property);
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ CHECK_FOR_EXCEPTION();
+
+ callFrame[dst] = result;
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_array_length) {
+ /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
+
+ Cached property access: Gets the length of the array in register base,
+ and puts the result in register dst. If register base does not hold
+ an array, op_get_array_length reverts to op_get_by_id.
+ */
+
+ int base = vPC[2].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ if (LIKELY(isJSArray(baseValue))) {
+ int dst = vPC[1].u.operand;
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length()));
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+
+ uncacheGetByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_string_length) {
+ /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
+
+ Cached property access: Gets the length of the string in register base,
+ and puts the result in register dst. If register base does not hold
+ a string, op_get_string_length reverts to op_get_by_id.
+ */
+
+ int base = vPC[2].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ if (LIKELY(isJSString(baseValue))) {
+ int dst = vPC[1].u.operand;
+ callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size()));
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+
+ uncacheGetByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_id) {
+ /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+
+ Generic property access: Sets the property named by identifier
+ property, belonging to register base, to register value.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+
+ int base = vPC[1].u.operand;
+ int property = vPC[2].u.operand;
+ int value = vPC[3].u.operand;
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ Identifier& ident = codeBlock->identifier(property);
+ PutPropertySlot slot;
+ baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ CHECK_FOR_EXCEPTION();
+
+ tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_id_transition) {
+ /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
+
+ Cached property access: Attempts to set a new property with a cached transition
+ property named by identifier property, belonging to register base,
+ to register value. If the cache misses, op_put_by_id_transition
+ reverts to op_put_by_id_generic.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = vPC[1].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+
+ if (LIKELY(baseValue.isCell())) {
+ JSCell* baseCell = asCell(baseValue);
+ Structure* oldStructure = vPC[4].u.structure;
+ Structure* newStructure = vPC[5].u.structure;
+
+ if (LIKELY(baseCell->structure() == oldStructure)) {
+ ASSERT(baseCell->isObject());
+ JSObject* baseObject = asObject(baseCell);
+
+ RefPtr<Structure>* it = vPC[6].u.structureChain->head();
+
+ JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame);
+ while (!proto.isNull()) {
+ if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
+ uncachePutByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ ++it;
+ proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
+ }
+
+ baseObject->transitionTo(newStructure);
+
+ int value = vPC[3].u.operand;
+ unsigned offset = vPC[7].u.operand;
+ ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
+ baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ }
+
+ uncachePutByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_id_replace) {
+ /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
+
+ Cached property access: Attempts to set a pre-existing, cached
+ property named by identifier property, belonging to register base,
+ to register value. If the cache misses, op_put_by_id_replace
+ reverts to op_put_by_id.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = vPC[1].u.operand;
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+
+ if (LIKELY(baseValue.isCell())) {
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = vPC[4].u.structure;
+
+ if (LIKELY(baseCell->structure() == structure)) {
+ ASSERT(baseCell->isObject());
+ JSObject* baseObject = asObject(baseCell);
+ int value = vPC[3].u.operand;
+ unsigned offset = vPC[5].u.operand;
+
+ ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
+ baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ }
+
+ uncachePutByID(callFrame->codeBlock(), vPC);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_id_generic) {
+ /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+
+ Generic property access: Sets the property named by identifier
+ property, belonging to register base, to register value.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = vPC[1].u.operand;
+ int property = vPC[2].u.operand;
+ int value = vPC[3].u.operand;
+
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ Identifier& ident = callFrame->codeBlock()->identifier(property);
+ PutPropertySlot slot;
+ baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ CHECK_FOR_EXCEPTION();
+
+ vPC += 8;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_del_by_id) {
+ /* del_by_id dst(r) base(r) property(id)
+
+ Converts register base to Object, deletes the property
+ named by identifier property from the object, and writes a
+ boolean indicating success (if true) or failure (if false)
+ to register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+
+ JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame);
+ Identifier& ident = callFrame->codeBlock()->identifier(property);
+ JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_by_val) {
+ /* get_by_val dst(r) base(r) property(r)
+
+ Converts register base to Object, gets the property named
+ by register property from the object, and puts the result
+ in register dst. property is nominally converted to string
+ but numbers are treated more efficiently.
+ */
+ int dst = (++vPC)->u.operand;
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+
+ JSValuePtr result;
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (isJSArray(baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canGetIndex(i))
+ result = jsArray->getIndex(i);
+ else
+ result = jsArray->JSArray::get(callFrame, i);
+ } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
+ result = asString(baseValue)->getIndex(&callFrame->globalData(), i);
+ else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
+ result = asByteArray(baseValue)->getIndex(callFrame, i);
+ else
+ result = baseValue.get(callFrame, i);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ result = baseValue.get(callFrame, property);
+ }
+
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_val) {
+ /* put_by_val base(r) property(r) value(r)
+
+ Sets register value on register base as the property named
+ by register property. Base is converted to object
+ first. register property is nominally converted to string
+ but numbers are treated more efficiently.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+ int value = (++vPC)->u.operand;
+
+ JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (isJSArray(baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canSetIndex(i))
+ jsArray->setIndex(i, callFrame[value].jsValue(callFrame));
+ else
+ jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame));
+ } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ JSByteArray* jsByteArray = asByteArray(baseValue);
+ double dValue = 0;
+ JSValuePtr jsValue = callFrame[value].jsValue(callFrame);
+ if (jsValue.isInt32Fast())
+ jsByteArray->setIndex(i, jsValue.getInt32Fast());
+ else if (jsValue.getNumber(dValue))
+ jsByteArray->setIndex(i, dValue);
+ else
+ baseValue.put(callFrame, i, jsValue);
+ } else
+ baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame));
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ if (!globalData->exception) { // Don't put to an object if toString threw an exception.
+ PutPropertySlot slot;
+ baseValue.put(callFrame, property, callFrame[value].jsValue(callFrame), slot);
+ }
+ }
+
+ CHECK_FOR_EXCEPTION();
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_del_by_val) {
+ /* del_by_val dst(r) base(r) property(r)
+
+ Converts register base to Object, deletes the property
+ named by register property from the object, and writes a
+ boolean indicating success (if true) or failure (if false)
+ to register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+
+ JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw
+
+ JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+ JSValuePtr result;
+ uint32_t i;
+ if (subscript.getUInt32(i))
+ result = jsBoolean(baseObj->deleteProperty(callFrame, i));
+ else {
+ CHECK_FOR_EXCEPTION();
+ Identifier property(callFrame, subscript.toString(callFrame));
+ CHECK_FOR_EXCEPTION();
+ result = jsBoolean(baseObj->deleteProperty(callFrame, property));
+ }
+
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = result;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_by_index) {
+ /* put_by_index base(r) property(n) value(r)
+
+ Sets register value on register base as the property named
+ by the immediate number property. Base is converted to
+ object first.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+
+ This opcode is mainly used to initialize array literals.
+ */
+ int base = (++vPC)->u.operand;
+ unsigned property = (++vPC)->u.operand;
+ int value = (++vPC)->u.operand;
+
+ callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_loop) {
+ /* loop target(offset)
+
+ Jumps unconditionally to offset target from the current
+ instruction.
+
+ Additionally this loop instruction may terminate JS execution is
+ the JS timeout is reached.
+ */
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+ int target = (++vPC)->u.operand;
+ CHECK_FOR_TIMEOUT();
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jmp) {
+ /* jmp target(offset)
+
+ Jumps unconditionally to offset target from the current
+ instruction.
+ */
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+ int target = (++vPC)->u.operand;
+
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_loop_if_true) {
+ /* loop_if_true cond(r) target(offset)
+
+ Jumps to offset target from the current instruction, if and
+ only if register cond converts to boolean as true.
+
+ Additionally this loop instruction may terminate JS execution is
+ the JS timeout is reached.
+ */
+ int cond = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ vPC += target;
+ CHECK_FOR_TIMEOUT();
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jtrue) {
+ /* jtrue cond(r) target(offset)
+
+ Jumps to offset target from the current instruction, if and
+ only if register cond converts to boolean as true.
+ */
+ int cond = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jfalse) {
+ /* jfalse cond(r) target(offset)
+
+ Jumps to offset target from the current instruction, if and
+ only if register cond converts to boolean as false.
+ */
+ int cond = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jeq_null) {
+ /* jeq_null src(r) target(offset)
+
+ Jumps to offset target from the current instruction, if and
+ only if register src is null.
+ */
+ int src = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+
+ if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jneq_null) {
+ /* jneq_null src(r) target(offset)
+
+ Jumps to offset target from the current instruction, if and
+ only if register src is not null.
+ */
+ int src = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+
+ if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_loop_if_less) {
+ /* loop_if_less src1(r) src2(r) target(offset)
+
+ Checks whether register src1 is less than register src2, as
+ with the ECMAScript '<' operator, and then jumps to offset
+ target from the current instruction, if and only if the
+ result of the comparison is true.
+
+ Additionally this loop instruction may terminate JS execution is
+ the JS timeout is reached.
+ */
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int target = (++vPC)->u.operand;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION();
+
+ if (result) {
+ vPC += target;
+ CHECK_FOR_TIMEOUT();
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_loop_if_lesseq) {
+ /* loop_if_lesseq src1(r) src2(r) target(offset)
+
+ Checks whether register src1 is less than or equal to register
+ src2, as with the ECMAScript '<=' operator, and then jumps to
+ offset target from the current instruction, if and only if the
+ result of the comparison is true.
+
+ Additionally this loop instruction may terminate JS execution is
+ the JS timeout is reached.
+ */
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int target = (++vPC)->u.operand;
+
+ bool result = jsLessEq(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION();
+
+ if (result) {
+ vPC += target;
+ CHECK_FOR_TIMEOUT();
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jnless) {
+ /* jnless src1(r) src2(r) target(offset)
+
+ Checks whether register src1 is less than register src2, as
+ with the ECMAScript '<' operator, and then jumps to offset
+ target from the current instruction, if and only if the
+ result of the comparison is false.
+ */
+ JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ int target = (++vPC)->u.operand;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION();
+
+ if (!result) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_switch_imm) {
+ /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
+
+ Performs a range checked switch on the scrutinee value, using
+ the tableIndex-th immediate switch jump table. If the scrutinee value
+ is an immediate number in the range covered by the referenced jump
+ table, and the value at jumpTable[scrutinee value] is non-zero, then
+ that value is used as the jump offset, otherwise defaultOffset is used.
+ */
+ int tableIndex = (++vPC)->u.operand;
+ int defaultOffset = (++vPC)->u.operand;
+ JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (scrutinee.isInt32Fast())
+ vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset);
+ else {
+ int32_t value;
+ if (scrutinee.numberToInt32(value))
+ vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset);
+ else
+ vPC += defaultOffset;
+ }
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_switch_char) {
+ /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
+
+ Performs a range checked switch on the scrutinee value, using
+ the tableIndex-th character switch jump table. If the scrutinee value
+ is a single character string in the range covered by the referenced jump
+ table, and the value at jumpTable[scrutinee value] is non-zero, then
+ that value is used as the jump offset, otherwise defaultOffset is used.
+ */
+ int tableIndex = (++vPC)->u.operand;
+ int defaultOffset = (++vPC)->u.operand;
+ JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (!scrutinee.isString())
+ vPC += defaultOffset;
+ else {
+ UString::Rep* value = asString(scrutinee)->value().rep();
+ if (value->size() != 1)
+ vPC += defaultOffset;
+ else
+ vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset);
+ }
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_switch_string) {
+ /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
+
+ Performs a sparse hashmap based switch on the value in the scrutinee
+ register, using the tableIndex-th string switch jump table. If the
+ scrutinee value is a string that exists as a key in the referenced
+ jump table, then the value associated with the string is used as the
+ jump offset, otherwise defaultOffset is used.
+ */
+ int tableIndex = (++vPC)->u.operand;
+ int defaultOffset = (++vPC)->u.operand;
+ JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ if (!scrutinee.isString())
+ vPC += defaultOffset;
+ else
+ vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset);
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_new_func) {
+ /* new_func dst(r) func(f)
+
+ Constructs a new Function instance from function func and
+ the current scope chain using the original Function
+ constructor, using the rules for function declarations, and
+ puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int func = (++vPC)->u.operand;
+
+ callFrame[dst] = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_new_func_exp) {
+ /* new_func_exp dst(r) func(f)
+
+ Constructs a new Function instance from function func and
+ the current scope chain using the original Function
+ constructor, using the rules for function expressions, and
+ puts the result in register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int func = (++vPC)->u.operand;
+
+ callFrame[dst] = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_call_eval) {
+ /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
+
+ Call a function named "eval" with no explicit "this" value
+ (which may therefore be the eval operator). If register
+ thisVal is the global object, and register func contains
+ that global object's original global eval function, then
+ perform the eval operator in local scope (interpreting
+ the argument registers as for the "call"
+ opcode). Otherwise, act exactly as the "call" opcode would.
+ */
+
+ int dst = vPC[1].u.operand;
+ int func = vPC[2].u.operand;
+ int argCount = vPC[3].u.operand;
+ int registerOffset = vPC[4].u.operand;
+
+ JSValuePtr funcVal = callFrame[func].jsValue(callFrame);
+
+ Register* newCallFrame = callFrame->registers() + registerOffset;
+ Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
+ JSValuePtr thisValue = argv[0].jsValue(callFrame);
+ JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
+
+ if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
+ JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
+ if (exceptionValue)
+ goto vm_throw;
+ callFrame[dst] = result;
+
+ vPC += 5;
+ NEXT_INSTRUCTION();
+ }
+
+ // We didn't find the blessed version of eval, so process this
+ // instruction as a normal function call.
+ // fall through to op_call
+ }
+ DEFINE_OPCODE(op_call) {
+ /* call dst(r) func(r) argCount(n) registerOffset(n)
+
+ Perform a function call.
+
+ registerOffset is the distance the callFrame pointer should move
+ before the VM initializes the new call frame's header.
+
+ dst is where op_ret should store its result.
+ */
+
+ int dst = vPC[1].u.operand;
+ int func = vPC[2].u.operand;
+ int argCount = vPC[3].u.operand;
+ int registerOffset = vPC[4].u.operand;
+
+ JSValuePtr v = callFrame[func].jsValue(callFrame);
+
+ CallData callData;
+ CallType callType = v.getCallData(callData);
+
+ if (callType == CallTypeJS) {
+ ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
+ FunctionBodyNode* functionBodyNode = callData.js.functionBody;
+ CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+
+ CallFrame* previousCallFrame = callFrame;
+
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (UNLIKELY(!callFrame)) {
+ callFrame = previousCallFrame;
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+
+ callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+ vPC = newCodeBlock->instructions().begin();
+
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+
+ NEXT_INSTRUCTION();
+ }
+
+ if (callType == CallTypeHost) {
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
+
+ Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
+ ArgList args(thisRegister + 1, argCount - 1);
+
+ // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
+ JSValuePtr thisValue = thisRegister->jsValue(callFrame);
+ if (thisValue == jsNull())
+ thisValue = callFrame->globalThisValue();
+
+ JSValuePtr returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(m_sampler);
+ returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
+ }
+ CHECK_FOR_EXCEPTION();
+
+ callFrame[dst] = JSValuePtr(returnValue);
+
+ vPC += 5;
+ NEXT_INSTRUCTION();
+ }
+
+ ASSERT(callType == CallTypeNone);
+
+ exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ DEFINE_OPCODE(op_tear_off_activation) {
+ /* tear_off_activation activation(r)
+
+ Copy all locals and parameters to new memory allocated on
+ the heap, and make the passed activation use this memory
+ in the future when looking up entries in the symbol table.
+ If there is an 'arguments' object, then it will also use
+ this memory for storing the named parameters, but not any
+ extra arguments.
+
+ This opcode should only be used immediately before op_ret.
+ */
+
+ int src = (++vPC)->u.operand;
+ ASSERT(callFrame->codeBlock()->needsFullScopeChain());
+
+ asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_tear_off_arguments) {
+ /* tear_off_arguments
+
+ Copy all arguments to new memory allocated on the heap,
+ and make the 'arguments' object use this memory in the
+ future when looking up named parameters, but not any
+ extra arguments. If an activation object exists for the
+ current function context, then the tear_off_activation
+ opcode should be used instead.
+
+ This opcode should only be used immediately before op_ret.
+ */
+
+ ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
+
+ callFrame->optionalCalleeArguments()->copyRegisters();
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_ret) {
+ /* ret result(r)
+
+ Return register result as the return value of the current
+ function call, writing it into the caller's expected return
+ value register. In addition, unwind one call frame and
+ restore the scope chain, code block instruction pointer and
+ register base to those of the calling function.
+ */
+
+ int result = (++vPC)->u.operand;
+
+ if (callFrame->codeBlock()->needsFullScopeChain())
+ callFrame->scopeChain()->deref();
+
+ JSValuePtr returnValue = callFrame[result].jsValue(callFrame);
+
+ vPC = callFrame->returnPC();
+ int dst = callFrame->returnValueRegister();
+ callFrame = callFrame->callerFrame();
+
+ if (callFrame->hasHostCallFrameFlag())
+ return returnValue;
+
+ callFrame[dst] = JSValuePtr(returnValue);
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_enter) {
+ /* enter
+
+ Initializes local variables to undefined and fills constant
+ registers with their values. If the code block requires an
+ activation, enter_with_activation should be used instead.
+
+ This opcode should only be used at the beginning of a code
+ block.
+ */
+
+ size_t i = 0;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ for (size_t count = codeBlock->m_numVars; i < count; ++i)
+ callFrame[i] = jsUndefined();
+
+ for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
+ callFrame[i] = codeBlock->constantRegister(j);
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_enter_with_activation) {
+ /* enter_with_activation dst(r)
+
+ Initializes local variables to undefined, fills constant
+ registers with their values, creates an activation object,
+ and places the new activation both in dst and at the top
+ of the scope chain. If the code block does not require an
+ activation, enter should be used instead.
+
+ This opcode should only be used at the beginning of a code
+ block.
+ */
+
+ size_t i = 0;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ for (size_t count = codeBlock->m_numVars; i < count; ++i)
+ callFrame[i] = jsUndefined();
+
+ for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
+ callFrame[i] = codeBlock->constantRegister(j);
+
+ int dst = (++vPC)->u.operand;
+ JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode()));
+ callFrame[dst] = activation;
+ callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_convert_this) {
+ /* convert_this this(r)
+
+ Takes the value in the 'this' register, converts it to a
+ value that is suitable for use as the 'this' value, and
+ stores it in the 'this' register. This opcode is emitted
+ to avoid doing the conversion in the caller unnecessarily.
+
+ This opcode should only be used at the beginning of a code
+ block.
+ */
+
+ int thisRegister = (++vPC)->u.operand;
+ JSValuePtr thisVal = callFrame[thisRegister].getJSValue();
+ if (thisVal.needsThisConversion())
+ callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_create_arguments) {
+ /* create_arguments
+
+ Creates the 'arguments' object and places it in both the
+ 'arguments' call frame slot and the local 'arguments'
+ register.
+
+ This opcode should only be used at the beginning of a code
+ block.
+ */
+
+ Arguments* arguments = new (globalData) Arguments(callFrame);
+ callFrame->setCalleeArguments(arguments);
+ callFrame[RegisterFile::ArgumentsRegister] = arguments;
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_construct) {
+ /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
+
+ Invoke register "func" as a constructor. For JS
+ functions, the calling convention is exactly as for the
+ "call" opcode, except that the "this" value is a newly
+ created Object. For native constructors, no "this"
+ value is passed. In either case, the argCount and registerOffset
+ registers are interpreted as for the "call" opcode.
+
+ Register proto must contain the prototype property of
+ register func. This is to enable polymorphic inline
+ caching of this lookup.
+ */
+
+ int dst = vPC[1].u.operand;
+ int func = vPC[2].u.operand;
+ int argCount = vPC[3].u.operand;
+ int registerOffset = vPC[4].u.operand;
+ int proto = vPC[5].u.operand;
+ int thisRegister = vPC[6].u.operand;
+
+ JSValuePtr v = callFrame[func].jsValue(callFrame);
+
+ ConstructData constructData;
+ ConstructType constructType = v.getConstructData(constructData);
+
+ if (constructType == ConstructTypeJS) {
+ ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
+ FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
+ CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+
+ Structure* structure;
+ JSValuePtr prototype = callFrame[proto].jsValue(callFrame);
+ if (prototype.isObject())
+ structure = asObject(prototype)->inheritorID();
+ else
+ structure = callDataScopeChain->globalObject()->emptyObjectStructure();
+ JSObject* newObject = new (globalData) JSObject(structure);
+
+ callFrame[thisRegister] = JSValuePtr(newObject); // "this" value
+
+ CallFrame* previousCallFrame = callFrame;
+
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (UNLIKELY(!callFrame)) {
+ callFrame = previousCallFrame;
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+
+ callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+ vPC = newCodeBlock->instructions().begin();
+
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+
+ NEXT_INSTRUCTION();
+ }
+
+ if (constructType == ConstructTypeHost) {
+ ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
+
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
+
+ JSValuePtr returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(m_sampler);
+ returnValue = constructData.native.function(newCallFrame, asObject(v), args);
+ }
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = JSValuePtr(returnValue);
+
+ vPC += 7;
+ NEXT_INSTRUCTION();
+ }
+
+ ASSERT(constructType == ConstructTypeNone);
+
+ exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ DEFINE_OPCODE(op_construct_verify) {
+ /* construct_verify dst(r) override(r)
+
+ Verifies that register dst holds an object. If not, moves
+ the object in register override to register dst.
+ */
+
+ int dst = vPC[1].u.operand;;
+ if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) {
+ vPC += 3;
+ NEXT_INSTRUCTION();
+ }
+
+ int override = vPC[2].u.operand;
+ callFrame[dst] = callFrame[override];
+
+ vPC += 3;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_push_scope) {
+ /* push_scope scope(r)
+
+ Converts register scope to object, and pushes it onto the top
+ of the current scope chain. The contents of the register scope
+ are replaced by the result of toObject conversion of the scope.
+ */
+ int scope = (++vPC)->u.operand;
+ JSValuePtr v = callFrame[scope].jsValue(callFrame);
+ JSObject* o = v.toObject(callFrame);
+ CHECK_FOR_EXCEPTION();
+
+ callFrame[scope] = JSValuePtr(o);
+ callFrame->setScopeChain(callFrame->scopeChain()->push(o));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_pop_scope) {
+ /* pop_scope
+
+ Removes the top item from the current scope chain.
+ */
+ callFrame->setScopeChain(callFrame->scopeChain()->pop());
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_get_pnames) {
+ /* get_pnames dst(r) base(r)
+
+ Creates a property name list for register base and puts it
+ in register dst. This is not a true JavaScript value, just
+ a synthetic value used to keep the iteration state in a
+ register.
+ */
+ int dst = (++vPC)->u.operand;
+ int base = (++vPC)->u.operand;
+
+ callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame));
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_next_pname) {
+ /* next_pname dst(r) iter(r) target(offset)
+
+ Tries to copies the next name from property name list in
+ register iter. If there are names left, then copies one to
+ register dst, and jumps to offset target. If there are none
+ left, invalidates the iterator and continues to the next
+ instruction.
+ */
+ int dst = (++vPC)->u.operand;
+ int iter = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+
+ JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator();
+ if (JSValuePtr temp = it->next(callFrame)) {
+ CHECK_FOR_TIMEOUT();
+ callFrame[dst] = JSValuePtr(temp);
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+ it->invalidate();
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jmp_scopes) {
+ /* jmp_scopes count(n) target(offset)
+
+ Removes the a number of items from the current scope chain
+ specified by immediate number count, then jumps to offset
+ target.
+ */
+ int count = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+
+ ScopeChainNode* tmp = callFrame->scopeChain();
+ while (count--)
+ tmp = tmp->pop();
+ callFrame->setScopeChain(tmp);
+
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+#if HAVE(COMPUTED_GOTO)
+ // Appease GCC
+ goto *(&&skip_new_scope);
+#endif
+ DEFINE_OPCODE(op_push_new_scope) {
+ /* new_scope dst(r) property(id) value(r)
+
+ Constructs a new StaticScopeObject with property set to value. That scope
+ object is then pushed onto the ScopeChain. The scope object is then stored
+ in dst for GC.
+ */
+ callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
+
+ vPC += 4;
+ NEXT_INSTRUCTION();
+ }
+#if HAVE(COMPUTED_GOTO)
+ skip_new_scope:
+#endif
+ DEFINE_OPCODE(op_catch) {
+ /* catch ex(r)
+
+ Retrieves the VMs current exception and puts it in register
+ ex. This is only valid after an exception has been raised,
+ and usually forms the beginning of an exception handler.
+ */
+ ASSERT(exceptionValue);
+ ASSERT(!globalData->exception);
+ int ex = (++vPC)->u.operand;
+ callFrame[ex] = exceptionValue;
+ exceptionValue = noValue();
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_throw) {
+ /* throw ex(r)
+
+ Throws register ex as an exception. This involves three
+ steps: first, it is set as the current exception in the
+ VM's internal state, then the stack is unwound until an
+ exception handler or a native code boundary is found, and
+ then control resumes at the exception handler if any or
+ else the script returns control to the nearest native caller.
+ */
+
+ int ex = (++vPC)->u.operand;
+ exceptionValue = callFrame[ex].jsValue(callFrame);
+
+ handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
+ if (!handler) {
+ *exception = exceptionValue;
+ return jsNull();
+ }
+
+ vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_unexpected_load) {
+ /* unexpected_load load dst(r) src(k)
+
+ Copies constant src to register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ callFrame[dst] = JSValuePtr(callFrame->codeBlock()->unexpectedConstant(src));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_new_error) {
+ /* new_error dst(r) type(n) message(k)
+
+ Constructs a new Error instance using the original
+ constructor, using immediate number n as the type and
+ constant message as the message string. The result is
+ written to register dst.
+ */
+ int dst = (++vPC)->u.operand;
+ int type = (++vPC)->u.operand;
+ int message = (++vPC)->u.operand;
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ callFrame[dst] = JSValuePtr(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_end) {
+ /* end result(r)
+
+ Return register result as the value of a global or eval
+ program. Return control to the calling native code.
+ */
+
+ if (callFrame->codeBlock()->needsFullScopeChain()) {
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ ASSERT(scopeChain->refCount > 1);
+ scopeChain->deref();
+ }
+ int result = (++vPC)->u.operand;
+ return callFrame[result].jsValue(callFrame);
+ }
+ DEFINE_OPCODE(op_put_getter) {
+ /* put_getter base(r) property(id) function(r)
+
+ Sets register function on register base as the getter named
+ by identifier property. Base and function are assumed to be
+ objects as this op should only be used for getters defined
+ in object literal form.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+ int function = (++vPC)->u.operand;
+
+ ASSERT(callFrame[base].jsValue(callFrame).isObject());
+ JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ Identifier& ident = callFrame->codeBlock()->identifier(property);
+ ASSERT(callFrame[function].jsValue(callFrame).isObject());
+ baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_put_setter) {
+ /* put_setter base(r) property(id) function(r)
+
+ Sets register function on register base as the setter named
+ by identifier property. Base and function are assumed to be
+ objects as this op should only be used for setters defined
+ in object literal form.
+
+ Unlike many opcodes, this one does not write any output to
+ the register file.
+ */
+ int base = (++vPC)->u.operand;
+ int property = (++vPC)->u.operand;
+ int function = (++vPC)->u.operand;
+
+ ASSERT(callFrame[base].jsValue(callFrame).isObject());
+ JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ Identifier& ident = callFrame->codeBlock()->identifier(property);
+ ASSERT(callFrame[function].jsValue(callFrame).isObject());
+ baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_jsr) {
+ /* jsr retAddrDst(r) target(offset)
+
+ Places the address of the next instruction into the retAddrDst
+ register and jumps to offset target from the current instruction.
+ */
+ int retAddrDst = (++vPC)->u.operand;
+ int target = (++vPC)->u.operand;
+ callFrame[retAddrDst] = vPC + 1;
+
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_sret) {
+ /* sret retAddrSrc(r)
+
+ Jumps to the address stored in the retAddrSrc register. This
+ differs from op_jmp because the target address is stored in a
+ register, not as an immediate.
+ */
+ int retAddrSrc = (++vPC)->u.operand;
+ vPC = callFrame[retAddrSrc].vPC();
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_debug) {
+ /* debug debugHookID(n) firstLine(n) lastLine(n)
+
+ Notifies the debugger of the current state of execution. This opcode
+ is only generated while the debugger is attached.
+ */
+ int debugHookID = (++vPC)->u.operand;
+ int firstLine = (++vPC)->u.operand;
+ int lastLine = (++vPC)->u.operand;
+
+ debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_profile_will_call) {
+ /* op_profile_will_call function(r)
+
+ Notifies the profiler of the beginning of a function call. This opcode
+ is only generated if developer tools are enabled.
+ */
+ int function = vPC[1].u.operand;
+
+ if (*enabledProfilerReference)
+ (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame));
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_profile_did_call) {
+ /* op_profile_did_call function(r)
+
+ Notifies the profiler of the end of a function call. This opcode
+ is only generated if developer tools are enabled.
+ */
+ int function = vPC[1].u.operand;
+
+ if (*enabledProfilerReference)
+ (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame));
+
+ vPC += 2;
+ NEXT_INSTRUCTION();
+ }
+ vm_throw: {
+ globalData->exception = noValue();
+ if (!tickCount) {
+ // The exceptionValue is a lie! (GCC produces bad code for reasons I
+ // cannot fathom if we don't assign to the exceptionValue before branching)
+ exceptionValue = createInterruptedExecutionException(globalData);
+ }
+ handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false);
+ if (!handler) {
+ *exception = exceptionValue;
+ return jsNull();
+ }
+
+ vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
+ NEXT_INSTRUCTION();
+ }
+ }
+#if !HAVE(COMPUTED_GOTO)
+ } // iterator loop ends
+#endif
+ #undef NEXT_INSTRUCTION
+ #undef DEFINE_OPCODE
+ #undef CHECK_FOR_EXCEPTION
+ #undef CHECK_FOR_TIMEOUT
+}
+
+JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
+{
+ CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+ if (!functionCallFrame)
+ return jsNull();
+
+ CodeBlock* codeBlock = functionCallFrame->codeBlock();
+ if (codeBlock->usesArguments()) {
+ ASSERT(codeBlock->codeType() == FunctionCode);
+ SymbolTable& symbolTable = codeBlock->symbolTable();
+ int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
+ return functionCallFrame[argumentsIndex].jsValue(callFrame);
+ }
+
+ Arguments* arguments = functionCallFrame->optionalCalleeArguments();
+ if (!arguments) {
+ arguments = new (functionCallFrame) Arguments(functionCallFrame);
+ arguments->copyRegisters();
+ callFrame->setCalleeArguments(arguments);
+ }
+
+ return arguments;
+}
+
+JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
+{
+ CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+ if (!functionCallFrame)
+ return jsNull();
+
+ CallFrame* callerFrame = functionCallFrame->callerFrame();
+ if (callerFrame->hasHostCallFrameFlag())
+ return jsNull();
+
+ JSValuePtr caller = callerFrame->callee();
+ if (!caller)
+ return jsNull();
+
+ return caller;
+}
+
+void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const
+{
+ function = noValue();
+ lineNumber = -1;
+ sourceURL = UString();
+
+ CallFrame* callerFrame = callFrame->callerFrame();
+ if (callerFrame->hasHostCallFrameFlag())
+ return;
+
+ CodeBlock* callerCodeBlock = callerFrame->codeBlock();
+ if (!callerCodeBlock)
+ return;
+
+ unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
+ lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
+ sourceID = callerCodeBlock->ownerNode()->sourceID();
+ sourceURL = callerCodeBlock->ownerNode()->sourceURL();
+ function = callerFrame->callee();
+}
+
+CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function)
+{
+ for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
+ if (candidate->callee() == function)
+ return candidate;
+ }
+ return 0;
+}
+
+#if ENABLE(JIT)
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+NEVER_INLINE void Interpreter::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot& slot)
+{
+ // The interpreter checks for recursion here; I do not believe this can occur in CTI.
+
+ if (!baseValue.isCell())
+ return;
+
+ // Uncacheable: give up.
+ if (!slot.isCacheable()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
+ return;
+ }
+
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = baseCell->structure();
+
+ if (structure->isDictionary()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
+ return;
+ }
+
+ // If baseCell != base, then baseCell must be a proxy for another object.
+ if (baseCell != slot.base()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
+ return;
+ }
+
+ StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
+
+ // Cache hit: Specialize instruction and ref Structures.
+
+ // Structure transition, cache transition info
+ if (slot.type() == PutPropertySlot::NewProperty) {
+ StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
+ JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
+ return;
+ }
+
+ stubInfo->initPutByIdReplace(structure);
+
+#if USE(CTI_REPATCH_PIC)
+ UNUSED_PARAM(callFrame);
+ JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress);
+#else
+ JIT::compilePutByIdReplace(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
+#endif
+}
+
+NEVER_INLINE void Interpreter::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
+{
+ // FIXME: Write a test that proves we need to check for recursion here just
+ // like the interpreter does, then add a check for recursion.
+
+ // FIXME: Cache property access for immediates.
+ if (!baseValue.isCell()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
+ return;
+ }
+
+ if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
+#if USE(CTI_REPATCH_PIC)
+ JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
+#else
+ ctiPatchCallByReturnAddress(returnAddress, m_ctiArrayLengthTrampoline);
+#endif
+ return;
+ }
+ if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
+ // The tradeoff of compiling an patched inline string length access routine does not seem
+ // to pay off, so we currently only do this for arrays.
+ ctiPatchCallByReturnAddress(returnAddress, m_ctiStringLengthTrampoline);
+ return;
+ }
+
+ // Uncacheable: give up.
+ if (!slot.isCacheable()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
+ return;
+ }
+
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = baseCell->structure();
+
+ if (structure->isDictionary()) {
+ ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
+ return;
+ }
+
+ // In the interpreter the last structure is trapped here; in CTI we use the
+ // *_second method to achieve a similar (but not quite the same) effect.
+
+ StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
+
+ // Cache hit: Specialize instruction and ref Structures.
+
+ if (slot.slotBase() == baseValue) {
+ // set this up, so derefStructures can do it's job.
+ stubInfo->initGetByIdSelf(structure);
+
+#if USE(CTI_REPATCH_PIC)
+ JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress);
+#else
+ JIT::compileGetByIdSelf(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
+#endif
+ return;
+ }
+
+ if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
+ ASSERT(slot.slotBase().isObject());
+
+ JSObject* slotBaseObject = asObject(slot.slotBase());
+
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (slotBaseObject->structure()->isDictionary())
+ slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure()));
+
+ stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
+
+ JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress);
+ return;
+ }
+
+ size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
+ if (!count) {
+ stubInfo->opcodeID = op_get_by_id_generic;
+ return;
+ }
+
+ StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ stubInfo->initGetByIdChain(structure, prototypeChain);
+ JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, slot.cachedOffset(), returnAddress);
+}
+
+#endif
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
+#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK
+#define SETUP_VA_LISTL_ARGS
+#endif
+
+#ifndef NDEBUG
+
+extern "C" {
+
+static void jscGeneratedNativeCode()
+{
+ // When executing a CTI function (which might do an allocation), we hack the return address
+ // to pretend to be executing this function, to keep stack logging tools from blowing out
+ // memory.
+}
+
+}
+
+struct StackHack {
+ ALWAYS_INLINE StackHack(void** location)
+ {
+ returnAddressLocation = location;
+ savedReturnAddress = *returnAddressLocation;
+ ctiSetReturnAddress(returnAddressLocation, reinterpret_cast<void*>(jscGeneratedNativeCode));
+ }
+ ALWAYS_INLINE ~StackHack()
+ {
+ ctiSetReturnAddress(returnAddressLocation, savedReturnAddress);
+ }
+
+ void** returnAddressLocation;
+ void* savedReturnAddress;
+};
+
+#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS; StackHack stackHack(&STUB_RETURN_ADDRESS_SLOT)
+#define STUB_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address
+#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
+
+#else
+
+#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS
+#define STUB_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&STUB_RETURN_ADDRESS_SLOT, address);
+#define STUB_RETURN_ADDRESS STUB_RETURN_ADDRESS_SLOT
+
+#endif
+
+// The reason this is not inlined is to avoid having to do a PIC branch
+// to get the address of the ctiVMThrowTrampoline function. It's also
+// good to keep the code size down by leaving as much of the exception
+// handling code out of line as possible.
+static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
+{
+ ASSERT(globalData->exception);
+ globalData->exceptionLocation = exceptionLocation;
+ ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline));
+}
+
+static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
+{
+ globalData->exception = createStackOverflowError(callFrame);
+ returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
+}
+
+#define VM_THROW_EXCEPTION() \
+ do { \
+ VM_THROW_EXCEPTION_AT_END(); \
+ return 0; \
+ } while (0)
+#define VM_THROW_EXCEPTION_2() \
+ do { \
+ VM_THROW_EXCEPTION_AT_END(); \
+ RETURN_PAIR(0, 0); \
+ } while (0)
+#define VM_THROW_EXCEPTION_AT_END() \
+ returnToThrowTrampoline(ARG_globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
+
+#define CHECK_FOR_EXCEPTION() \
+ do { \
+ if (UNLIKELY(ARG_globalData->exception != noValue())) \
+ VM_THROW_EXCEPTION(); \
+ } while (0)
+#define CHECK_FOR_EXCEPTION_AT_END() \
+ do { \
+ if (UNLIKELY(ARG_globalData->exception != noValue())) \
+ VM_THROW_EXCEPTION_AT_END(); \
+ } while (0)
+#define CHECK_FOR_EXCEPTION_VOID() \
+ do { \
+ if (UNLIKELY(ARG_globalData->exception != noValue())) { \
+ VM_THROW_EXCEPTION_AT_END(); \
+ return; \
+ } \
+ } while (0)
+
+JSObject* Interpreter::cti_op_convert_this(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v1 = ARG_src1;
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSObject* result = v1.toThisObject(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+void Interpreter::cti_op_end(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ScopeChainNode* scopeChain = ARG_callFrame->scopeChain();
+ ASSERT(scopeChain->refCount > 1);
+ scopeChain->deref();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_add(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v1 = ARG_src1;
+ JSValuePtr v2 = ARG_src2;
+
+ double left;
+ double right = 0.0;
+
+ bool rightIsNumber = v2.getNumber(right);
+ if (rightIsNumber && v1.getNumber(left))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left + right));
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool leftIsString = v1.isString();
+ if (leftIsString && v2.isString()) {
+ RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
+ if (UNLIKELY(!value)) {
+ throwOutOfMemoryError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+
+ return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
+ }
+
+ if (rightIsNumber & leftIsString) {
+ RefPtr<UString::Rep> value = v2.isInt32Fast() ?
+ concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
+ concatenate(asString(v1)->value().rep(), right);
+
+ if (UNLIKELY(!value)) {
+ throwOutOfMemoryError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
+ }
+
+ // All other cases are pretty uncommon
+ JSValuePtr result = jsAddSlowCase(callFrame, v1, v2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_pre_inc(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) + 1);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+int Interpreter::cti_timeout_check(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ if (interpreter->checkTimeout(ARG_callFrame->dynamicGlobalObject())) {
+ ARG_globalData->exception = createInterruptedExecutionException(ARG_globalData);
+ VM_THROW_EXCEPTION_AT_END();
+ }
+
+ return interpreter->m_ticksUntilNextTimeoutCheck;
+}
+
+void Interpreter::cti_register_file_check(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->m_numCalleeRegisters)))
+ return;
+
+ // Rewind to the previous call frame because op_call already optimistically
+ // moved the call frame forward.
+ CallFrame* oldCallFrame = ARG_callFrame->callerFrame();
+ ARG_setCallFrame(oldCallFrame);
+ throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), STUB_RETURN_ADDRESS);
+}
+
+int Interpreter::cti_op_loop_if_less(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+int Interpreter::cti_op_loop_if_lesseq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool result = jsLessEq(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+JSObject* Interpreter::cti_op_new_object(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return constructEmptyObject(ARG_callFrame);
+}
+
+void Interpreter::cti_op_put_by_id_generic(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ PutPropertySlot slot;
+ ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_generic(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+void Interpreter::cti_op_put_by_id(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ PutPropertySlot slot;
+ ARG_src1.put(callFrame, ident, ARG_src3, slot);
+
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+void Interpreter::cti_op_put_by_id_second(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ PutPropertySlot slot;
+ ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
+ ARG_globalData->interpreter->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), STUB_RETURN_ADDRESS, ARG_src1, slot);
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+void Interpreter::cti_op_put_by_id_fail(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ PutPropertySlot slot;
+ ARG_src1.put(callFrame, ident, ARG_src3, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_second(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+
+ ARG_globalData->interpreter->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_self_fail(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Identifier& ident = *ARG_id2;
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, ident, slot);
+
+ CHECK_FOR_EXCEPTION();
+
+ if (baseValue.isCell()
+ && slot.isCacheable()
+ && !asCell(baseValue)->structure()->isDictionary()
+ && slot.slotBase() == baseValue) {
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+
+ ASSERT(slot.slotBase().isObject());
+
+ PolymorphicAccessStructureList* polymorphicStructureList;
+ int listIndex = 1;
+
+ if (stubInfo->opcodeID == op_get_by_id_self) {
+ ASSERT(!stubInfo->stubRoutine);
+ polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure);
+ stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
+ } else {
+ polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
+ listIndex = stubInfo->u.getByIdSelfList.listSize;
+ stubInfo->u.getByIdSelfList.listSize++;
+ }
+
+ JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
+
+ if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
+ } else {
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
+ }
+ return JSValuePtr::encode(result);
+}
+
+static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
+{
+ PolymorphicAccessStructureList* prototypeStructureList = 0;
+ listIndex = 1;
+
+ switch (stubInfo->opcodeID) {
+ case op_get_by_id_proto:
+ prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
+ stubInfo->stubRoutine = 0;
+ stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
+ break;
+ case op_get_by_id_chain:
+ prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
+ stubInfo->stubRoutine = 0;
+ stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
+ break;
+ case op_get_by_id_proto_list:
+ prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
+ listIndex = stubInfo->u.getByIdProtoList.listSize;
+ stubInfo->u.getByIdProtoList.listSize++;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
+ return prototypeStructureList;
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(callFrame, *ARG_id2, slot);
+
+ CHECK_FOR_EXCEPTION();
+
+ if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
+ return JSValuePtr::encode(result);
+ }
+
+ Structure* structure = asCell(baseValue)->structure();
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+
+ ASSERT(slot.slotBase().isObject());
+ JSObject* slotBaseObject = asObject(slot.slotBase());
+
+ if (slot.slotBase() == baseValue)
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
+ else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (slotBaseObject->structure()->isDictionary())
+ slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure()));
+
+ int listIndex;
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+
+ JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset());
+
+ if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
+ } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
+ int listIndex;
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+
+ JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, structure->prototypeChain(callFrame), count, slot.cachedOffset());
+
+ if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
+ } else
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
+
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list_full(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_fail(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_array_fail(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_string_fail(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr baseValue = ARG_src1;
+ PropertySlot slot(baseValue);
+ JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+#endif
+
+JSValueEncodedAsPointer* Interpreter::cti_op_instanceof(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr value = ARG_src1;
+ JSValuePtr baseVal = ARG_src2;
+ JSValuePtr proto = ARG_src3;
+
+ // at least one of these checks must have failed to get to the slow case
+ ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
+ || !value.isObject() || !baseVal.isObject() || !proto.isObject()
+ || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
+
+ if (!baseVal.isObject()) {
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+
+ if (!asObject(baseVal)->structure()->typeInfo().implementsHasInstance())
+ return JSValuePtr::encode(jsBoolean(false));
+
+ if (!proto.isObject()) {
+ throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
+ VM_THROW_EXCEPTION();
+ }
+
+ if (!value.isObject())
+ return JSValuePtr::encode(jsBoolean(false));
+
+ JSValuePtr result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_del_by_id(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSObject* baseObj = ARG_src1.toObject(callFrame);
+
+ JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, *ARG_id2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_mul(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left * right));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSObject* Interpreter::cti_op_new_func(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return ARG_func1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
+}
+
+void* Interpreter::cti_op_call_JSFunction(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+#ifndef NDEBUG
+ CallData callData;
+ ASSERT(ARG_src1.getCallData(callData) == CallTypeJS);
+#endif
+
+ ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node();
+ CodeBlock* newCodeBlock = &asFunction(ARG_src1)->body()->bytecode(callDataScopeChain);
+
+ if (!newCodeBlock->jitCode())
+ JIT::compile(ARG_globalData, newCodeBlock);
+
+ return newCodeBlock;
+}
+
+VoidPtrPair Interpreter::cti_op_call_arityCheck(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* newCodeBlock = ARG_codeBlock4;
+ int argCount = ARG_int3;
+
+ ASSERT(argCount != newCodeBlock->m_numParameters);
+
+ CallFrame* oldCallFrame = callFrame->callerFrame();
+
+ if (argCount > newCodeBlock->m_numParameters) {
+ size_t numParameters = newCodeBlock->m_numParameters;
+ Register* r = callFrame->registers() + numParameters;
+
+ Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
+ for (size_t i = 0; i < numParameters; ++i)
+ argv[i + argCount] = argv[i];
+
+ callFrame = CallFrame::create(r);
+ callFrame->setCallerFrame(oldCallFrame);
+ } else {
+ size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
+ Register* r = callFrame->registers() + omittedArgCount;
+ Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
+ if (!ARG_registerFile->grow(newEnd)) {
+ // Rewind to the previous call frame because op_call already optimistically
+ // moved the call frame forward.
+ ARG_setCallFrame(oldCallFrame);
+ throwStackOverflowError(oldCallFrame, ARG_globalData, ARG_returnAddress2, STUB_RETURN_ADDRESS);
+ RETURN_PAIR(0, 0);
+ }
+
+ Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
+ for (size_t i = 0; i < omittedArgCount; ++i)
+ argv[i] = jsUndefined();
+
+ callFrame = CallFrame::create(r);
+ callFrame->setCallerFrame(oldCallFrame);
+ }
+
+ RETURN_PAIR(newCodeBlock, callFrame);
+}
+
+void* Interpreter::cti_vm_dontLazyLinkCall(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSFunction* callee = asFunction(ARG_src1);
+ CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
+ if (!codeBlock->jitCode())
+ JIT::compile(ARG_globalData, codeBlock);
+
+ ctiPatchCallByReturnAddress(ARG_returnAddress2, ARG_globalData->interpreter->m_ctiVirtualCallLink);
+
+ return codeBlock->jitCode();
+}
+
+void* Interpreter::cti_vm_lazyLinkCall(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSFunction* callee = asFunction(ARG_src1);
+ CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
+ if (!codeBlock->jitCode())
+ JIT::compile(ARG_globalData, codeBlock);
+
+ CallLinkInfo* callLinkInfo = &ARG_callFrame->callerFrame()->codeBlock()->getCallLinkInfo(ARG_returnAddress2);
+ JIT::linkCall(callee, codeBlock, codeBlock->jitCode(), callLinkInfo, ARG_int3);
+
+ return codeBlock->jitCode();
+}
+
+JSObject* Interpreter::cti_op_push_activation(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode()));
+ ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->copy()->push(activation));
+ return activation;
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_call_NotJSFunction(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr funcVal = ARG_src1;
+
+ CallData callData;
+ CallType callType = funcVal.getCallData(callData);
+
+ ASSERT(callType != CallTypeJS);
+
+ if (callType == CallTypeHost) {
+ int registerOffset = ARG_int2;
+ int argCount = ARG_int3;
+ CallFrame* previousCallFrame = ARG_callFrame;
+ CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
+
+ callFrame->init(0, static_cast<Instruction*>(STUB_RETURN_ADDRESS), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
+ ARG_setCallFrame(callFrame);
+
+ Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
+ ArgList argList(argv + 1, argCount - 1);
+
+ JSValuePtr returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+
+ // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
+ JSValuePtr thisValue = argv[0].jsValue(callFrame);
+ if (thisValue == jsNull())
+ thisValue = callFrame->globalThisValue();
+
+ returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
+ }
+ ARG_setCallFrame(previousCallFrame);
+ CHECK_FOR_EXCEPTION();
+
+ return JSValuePtr::encode(returnValue);
+ }
+
+ ASSERT(callType == CallTypeNone);
+
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+void Interpreter::cti_op_create_arguments(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame);
+ ARG_callFrame->setCalleeArguments(arguments);
+ ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
+}
+
+void Interpreter::cti_op_create_arguments_no_params(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame, Arguments::NoParameters);
+ ARG_callFrame->setCalleeArguments(arguments);
+ ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
+}
+
+void Interpreter::cti_op_tear_off_activation(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
+ asActivation(ARG_src1)->copyRegisters(ARG_callFrame->optionalCalleeArguments());
+}
+
+void Interpreter::cti_op_tear_off_arguments(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ASSERT(ARG_callFrame->codeBlock()->usesArguments() && !ARG_callFrame->codeBlock()->needsFullScopeChain());
+ ARG_callFrame->optionalCalleeArguments()->copyRegisters();
+}
+
+void Interpreter::cti_op_profile_will_call(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ASSERT(*ARG_profilerReference);
+ (*ARG_profilerReference)->willExecute(ARG_callFrame, ARG_src1);
+}
+
+void Interpreter::cti_op_profile_did_call(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ASSERT(*ARG_profilerReference);
+ (*ARG_profilerReference)->didExecute(ARG_callFrame, ARG_src1);
+}
+
+void Interpreter::cti_op_ret_scopeChain(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
+ ARG_callFrame->scopeChain()->deref();
+}
+
+JSObject* Interpreter::cti_op_new_array(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ArgList argList(&ARG_callFrame->registers()[ARG_int1], ARG_int2);
+ return constructArray(ARG_callFrame, argList);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_resolve(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+
+ Identifier& ident = *ARG_id1;
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+ }
+ } while (++iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+JSObject* Interpreter::cti_op_construct_JSConstruct(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+#ifndef NDEBUG
+ ConstructData constructData;
+ ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTypeJS);
+#endif
+
+ Structure* structure;
+ if (ARG_src4.isObject())
+ structure = asObject(ARG_src4)->inheritorID();
+ else
+ structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
+ return new (ARG_globalData) JSObject(structure);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_construct_NotJSConstruct(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr constrVal = ARG_src1;
+ int argCount = ARG_int3;
+ int thisRegister = ARG_int5;
+
+ ConstructData constructData;
+ ConstructType constructType = constrVal.getConstructData(constructData);
+
+ if (constructType == ConstructTypeHost) {
+ ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
+
+ JSValuePtr returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+ returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
+ }
+ CHECK_FOR_EXCEPTION();
+
+ return JSValuePtr::encode(returnValue);
+ }
+
+ ASSERT(constructType == ConstructTypeNone);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ JSValuePtr baseValue = ARG_src1;
+ JSValuePtr subscript = ARG_src2;
+
+ JSValuePtr result;
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (interpreter->isJSArray(baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canGetIndex(i))
+ result = jsArray->getIndex(i);
+ else
+ result = jsArray->JSArray::get(callFrame, i);
+ } else if (interpreter->isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
+ result = asString(baseValue)->getIndex(ARG_globalData, i);
+ else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val_byte_array));
+ return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
+ } else
+ result = baseValue.get(callFrame, i);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ result = baseValue.get(callFrame, property);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val_byte_array(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ JSValuePtr baseValue = ARG_src1;
+ JSValuePtr subscript = ARG_src2;
+
+ JSValuePtr result;
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
+ }
+
+ result = baseValue.get(callFrame, i);
+ if (!interpreter->isJSByteArray(baseValue))
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val));
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ result = baseValue.get(callFrame, property);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+VoidPtrPair Interpreter::cti_op_resolve_func(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+
+ // FIXME: add scopeDepthIsZero optimization
+
+ ASSERT(iter != end);
+
+ Identifier& ident = *ARG_id1;
+ JSObject* base;
+ do {
+ base = *iter;
+ PropertySlot slot(base);
+ if (base->getPropertySlot(callFrame, ident, slot)) {
+ // ECMA 11.2.3 says that if we hit an activation the this value should be null.
+ // However, section 10.2.3 says that in the case where the value provided
+ // by the caller is null, the global object should be used. It also says
+ // that the section does not apply to internal functions, but for simplicity
+ // of implementation we use the global object anyway here. This guarantees
+ // that in host objects you always get a valid object for this.
+ // We also handle wrapper substitution for the global object at the same time.
+ JSObject* thisObj = base->toThisObject(callFrame);
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ RETURN_PAIR(thisObj, JSValuePtr::encode(result));
+ }
+ ++iter;
+ } while (iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION_2();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_sub(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left - right));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+void Interpreter::cti_op_put_by_val(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ JSValuePtr baseValue = ARG_src1;
+ JSValuePtr subscript = ARG_src2;
+ JSValuePtr value = ARG_src3;
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (interpreter->isJSArray(baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canSetIndex(i))
+ jsArray->setIndex(i, value);
+ else
+ jsArray->JSArray::put(callFrame, i, value);
+ } else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ JSByteArray* jsByteArray = asByteArray(baseValue);
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val_byte_array));
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ if (value.isInt32Fast()) {
+ jsByteArray->setIndex(i, value.getInt32Fast());
+ return;
+ } else {
+ double dValue = 0;
+ if (value.getNumber(dValue)) {
+ jsByteArray->setIndex(i, dValue);
+ return;
+ }
+ }
+
+ baseValue.put(callFrame, i, value);
+ } else
+ baseValue.put(callFrame, i, value);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
+ PutPropertySlot slot;
+ baseValue.put(callFrame, property, value, slot);
+ }
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+void Interpreter::cti_op_put_by_val_array(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr baseValue = ARG_src1;
+ int i = ARG_int2;
+ JSValuePtr value = ARG_src3;
+
+ ASSERT(ARG_globalData->interpreter->isJSArray(baseValue));
+
+ if (LIKELY(i >= 0))
+ asArray(baseValue)->JSArray::put(callFrame, i, value);
+ else {
+ // This should work since we're re-boxing an immediate unboxed in JIT code.
+ ASSERT(JSValuePtr::makeInt32Fast(i));
+ Identifier property(callFrame, JSValuePtr::makeInt32Fast(i).toString(callFrame));
+ // FIXME: can toString throw an exception here?
+ if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
+ PutPropertySlot slot;
+ baseValue.put(callFrame, property, value, slot);
+ }
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+void Interpreter::cti_op_put_by_val_byte_array(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ JSValuePtr baseValue = ARG_src1;
+ JSValuePtr subscript = ARG_src2;
+ JSValuePtr value = ARG_src3;
+
+ if (LIKELY(subscript.isUInt32Fast())) {
+ uint32_t i = subscript.getUInt32Fast();
+ if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ JSByteArray* jsByteArray = asByteArray(baseValue);
+
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ if (value.isInt32Fast()) {
+ jsByteArray->setIndex(i, value.getInt32Fast());
+ return;
+ } else {
+ double dValue = 0;
+ if (value.getNumber(dValue)) {
+ jsByteArray->setIndex(i, dValue);
+ return;
+ }
+ }
+ }
+
+ if (!interpreter->isJSByteArray(baseValue))
+ ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val));
+ baseValue.put(callFrame, i, value);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
+ PutPropertySlot slot;
+ baseValue.put(callFrame, property, value, slot);
+ }
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_lesseq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+int Interpreter::cti_op_loop_if_true(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool result = src1.toBoolean(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_negate(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src = ARG_src1;
+
+ double v;
+ if (src.getNumber(v))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, -v));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, -src.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_resolve_base(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain()));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_resolve_skip(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ int skip = ARG_int2;
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+ while (skip--) {
+ ++iter;
+ ASSERT(iter != end);
+ }
+ Identifier& ident = *ARG_id1;
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+ }
+ } while (++iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_resolve_global(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSGlobalObject* globalObject = asGlobalObject(ARG_src1);
+ Identifier& ident = *ARG_id2;
+ unsigned globalResolveInfoIndex = ARG_int3;
+ ASSERT(globalObject->isGlobalObject());
+
+ PropertySlot slot(globalObject);
+ if (globalObject->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
+ GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
+ if (globalResolveInfo.structure)
+ globalResolveInfo.structure->deref();
+ globalObject->structure()->ref();
+ globalResolveInfo.structure = globalObject->structure();
+ globalResolveInfo.offset = slot.cachedOffset();
+ return JSValuePtr::encode(result);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+ }
+
+ unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
+ VM_THROW_EXCEPTION();
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_div(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left / right));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_pre_dec(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) - 1);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+int Interpreter::cti_op_jless(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_not(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr result = jsBoolean(!src.toBoolean(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+int Interpreter::cti_op_jtrue(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ bool result = src1.toBoolean(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+VoidPtrPair Interpreter::cti_op_post_inc(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr number = v.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() + 1)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_eq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
+ JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_lshift(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr val = ARG_src1;
+ JSValuePtr shift = ARG_src2;
+
+ int32_t left;
+ uint32_t right;
+ if (JSValuePtr::areBothInt32Fast(val, shift))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
+ if (val.numberToInt32(left) && shift.numberToUInt32(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left << (right & 0x1f)));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_bitand(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ int32_t left;
+ int32_t right;
+ if (src1.numberToInt32(left) && src2.numberToInt32(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left & right));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_rshift(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr val = ARG_src1;
+ JSValuePtr shift = ARG_src2;
+
+ int32_t left;
+ uint32_t right;
+ if (JSFastMath::canDoFastRshift(val, shift))
+ return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ if (val.numberToInt32(left) && shift.numberToUInt32(right))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, left >> (right & 0x1f)));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_bitnot(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src = ARG_src1;
+
+ int value;
+ if (src.numberToInt32(value))
+ return JSValuePtr::encode(jsNumber(ARG_globalData, ~value));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsNumber(ARG_globalData, ~src.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+VoidPtrPair Interpreter::cti_op_resolve_with_base(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+
+ // FIXME: add scopeDepthIsZero optimization
+
+ ASSERT(iter != end);
+
+ Identifier& ident = *ARG_id1;
+ JSObject* base;
+ do {
+ base = *iter;
+ PropertySlot slot(base);
+ if (base->getPropertySlot(callFrame, ident, slot)) {
+ JSValuePtr result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ RETURN_PAIR(base, JSValuePtr::encode(result));
+ }
+ ++iter;
+ } while (iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION_2();
+}
+
+JSObject* Interpreter::cti_op_new_func_exp(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return ARG_funcexp1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_mod(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr dividendValue = ARG_src1;
+ JSValuePtr divisorValue = ARG_src2;
+
+ CallFrame* callFrame = ARG_callFrame;
+ double d = dividendValue.toNumber(callFrame);
+ JSValuePtr result = jsNumber(ARG_globalData, fmod(d, divisorValue.toNumber(callFrame)));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_less(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_neq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+VoidPtrPair Interpreter::cti_op_post_dec(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v = ARG_src1;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr number = v.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() - 1)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_urshift(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr val = ARG_src1;
+ JSValuePtr shift = ARG_src2;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ if (JSFastMath::canDoFastUrshift(val, shift))
+ return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ else {
+ JSValuePtr result = jsNumber(ARG_globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+ }
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_bitxor(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSObject* Interpreter::cti_op_new_regexp(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return new (ARG_globalData) RegExpObject(ARG_callFrame->lexicalGlobalObject()->regExpStructure(), ARG_regexp1);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_bitor(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_call_eval(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ RegisterFile* registerFile = ARG_registerFile;
+
+ Interpreter* interpreter = ARG_globalData->interpreter;
+
+ JSValuePtr funcVal = ARG_src1;
+ int registerOffset = ARG_int2;
+ int argCount = ARG_int3;
+
+ Register* newCallFrame = callFrame->registers() + registerOffset;
+ Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
+ JSValuePtr thisValue = argv[0].jsValue(callFrame);
+ JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
+
+ if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
+ JSValuePtr exceptionValue = noValue();
+ JSValuePtr result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
+ if (UNLIKELY(exceptionValue != noValue())) {
+ ARG_globalData->exception = exceptionValue;
+ VM_THROW_EXCEPTION_AT_END();
+ }
+ return JSValuePtr::encode(result);
+ }
+
+ return JSValuePtr::encode(jsImpossibleValue());
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_throw(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+
+ JSValuePtr exceptionValue = ARG_src1;
+ ASSERT(exceptionValue);
+
+ HandlerInfo* handler = ARG_globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
+
+ if (!handler) {
+ *ARG_exception = exceptionValue;
+ return JSValuePtr::encode(jsNull());
+ }
+
+ ARG_setCallFrame(callFrame);
+ void* catchRoutine = handler->nativeCode;
+ ASSERT(catchRoutine);
+ STUB_SET_RETURN_ADDRESS(catchRoutine);
+ return JSValuePtr::encode(exceptionValue);
+}
+
+JSPropertyNameIterator* Interpreter::cti_op_get_pnames(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSPropertyNameIterator::create(ARG_callFrame, ARG_src1);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_next_pname(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSPropertyNameIterator* it = ARG_pni1;
+ JSValuePtr temp = it->next(ARG_callFrame);
+ if (!temp)
+ it->invalidate();
+ return JSValuePtr::encode(temp);
+}
+
+JSObject* Interpreter::cti_op_push_scope(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSObject* o = ARG_src1.toObject(ARG_callFrame);
+ CHECK_FOR_EXCEPTION();
+ ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o));
+ return o;
+}
+
+void Interpreter::cti_op_pop_scope(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->pop());
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_typeof(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsTypeStringForValue(ARG_callFrame, ARG_src1));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_undefined(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr v = ARG_src1;
+ return JSValuePtr::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_boolean(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsBoolean(ARG_src1.isBoolean()));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_number(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsBoolean(ARG_src1.isNumber()));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_string(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsBoolean(ARG_globalData->interpreter->isJSString(ARG_src1)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_object(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsBoolean(jsIsObjectType(ARG_src1)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_is_function(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ return JSValuePtr::encode(jsBoolean(jsIsFunctionType(ARG_src1)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_stricteq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ return JSValuePtr::encode(jsBoolean(JSValuePtr::strictEqual(src1, src2)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_nstricteq(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src1 = ARG_src1;
+ JSValuePtr src2 = ARG_src2;
+
+ return JSValuePtr::encode(jsBoolean(!JSValuePtr::strictEqual(src1, src2)));
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_to_jsnumber(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr src = ARG_src1;
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr result = src.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_in(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ JSValuePtr baseVal = ARG_src2;
+
+ if (!baseVal.isObject()) {
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+
+ JSValuePtr propName = ARG_src1;
+ JSObject* baseObj = asObject(baseVal);
+
+ uint32_t i;
+ if (propName.getUInt32(i))
+ return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
+
+ Identifier property(callFrame, propName.toString(callFrame));
+ CHECK_FOR_EXCEPTION();
+ return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
+}
+
+JSObject* Interpreter::cti_op_push_new_scope(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSObject* scope = new (ARG_globalData) JSStaticScopeObject(ARG_callFrame, *ARG_id1, ARG_src2, DontDelete);
+
+ CallFrame* callFrame = ARG_callFrame;
+ callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
+ return scope;
+}
+
+void Interpreter::cti_op_jmp_scopes(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ unsigned count = ARG_int1;
+ CallFrame* callFrame = ARG_callFrame;
+
+ ScopeChainNode* tmp = callFrame->scopeChain();
+ while (count--)
+ tmp = tmp->pop();
+ callFrame->setScopeChain(tmp);
+}
+
+void Interpreter::cti_op_put_by_index(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ unsigned property = ARG_int2;
+
+ ARG_src1.put(callFrame, property, ARG_src3);
+}
+
+void* Interpreter::cti_op_switch_imm(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr scrutinee = ARG_src1;
+ unsigned tableIndex = ARG_int2;
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ if (scrutinee.isInt32Fast())
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.getInt32Fast());
+ else {
+ int32_t value;
+ if (scrutinee.numberToInt32(value))
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(value);
+ else
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault;
+ }
+}
+
+void* Interpreter::cti_op_switch_char(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr scrutinee = ARG_src1;
+ unsigned tableIndex = ARG_int2;
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault;
+
+ if (scrutinee.isString()) {
+ UString::Rep* value = asString(scrutinee)->value().rep();
+ if (value->size() == 1)
+ result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]);
+ }
+
+ return result;
+}
+
+void* Interpreter::cti_op_switch_string(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ JSValuePtr scrutinee = ARG_src1;
+ unsigned tableIndex = ARG_int2;
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault;
+
+ if (scrutinee.isString()) {
+ UString::Rep* value = asString(scrutinee)->value().rep();
+ result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value);
+ }
+
+ return result;
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_op_del_by_val(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ JSValuePtr baseValue = ARG_src1;
+ JSObject* baseObj = baseValue.toObject(callFrame); // may throw
+
+ JSValuePtr subscript = ARG_src2;
+ JSValuePtr result;
+ uint32_t i;
+ if (subscript.getUInt32(i))
+ result = jsBoolean(baseObj->deleteProperty(callFrame, i));
+ else {
+ CHECK_FOR_EXCEPTION();
+ Identifier property(callFrame, subscript.toString(callFrame));
+ CHECK_FOR_EXCEPTION();
+ result = jsBoolean(baseObj->deleteProperty(callFrame, property));
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValuePtr::encode(result);
+}
+
+void Interpreter::cti_op_put_getter(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ ASSERT(ARG_src1.isObject());
+ JSObject* baseObj = asObject(ARG_src1);
+ ASSERT(ARG_src3.isObject());
+ baseObj->defineGetter(callFrame, *ARG_id2, asObject(ARG_src3));
+}
+
+void Interpreter::cti_op_put_setter(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ ASSERT(ARG_src1.isObject());
+ JSObject* baseObj = asObject(ARG_src1);
+ ASSERT(ARG_src3.isObject());
+ baseObj->defineSetter(callFrame, *ARG_id2, asObject(ARG_src3));
+}
+
+JSObject* Interpreter::cti_op_new_error(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned type = ARG_int1;
+ JSValuePtr message = ARG_src2;
+ unsigned bytecodeOffset = ARG_int3;
+
+ unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+ return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+}
+
+void Interpreter::cti_op_debug(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+
+ int debugHookID = ARG_int1;
+ int firstLine = ARG_int2;
+ int lastLine = ARG_int3;
+
+ ARG_globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+}
+
+JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS)
+{
+ BEGIN_STUB_FUNCTION();
+
+ CallFrame* callFrame = ARG_callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ JSGlobalData* globalData = ARG_globalData;
+
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
+
+ JSValuePtr exceptionValue = globalData->exception;
+ ASSERT(exceptionValue);
+ globalData->exception = noValue();
+
+ HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
+
+ if (!handler) {
+ *ARG_exception = exceptionValue;
+ return JSValuePtr::encode(jsNull());
+ }
+
+ ARG_setCallFrame(callFrame);
+ void* catchRoutine = handler->nativeCode;
+ ASSERT(catchRoutine);
+ STUB_SET_RETURN_ADDRESS(catchRoutine);
+ return JSValuePtr::encode(exceptionValue);
+}
+
+#undef STUB_RETURN_ADDRESS
+#undef STUB_SET_RETURN_ADDRESS
+#undef BEGIN_STUB_FUNCTION
+#undef CHECK_FOR_EXCEPTION
+#undef CHECK_FOR_EXCEPTION_AT_END
+#undef CHECK_FOR_EXCEPTION_VOID
+#undef VM_THROW_EXCEPTION
+#undef VM_THROW_EXCEPTION_2
+#undef VM_THROW_EXCEPTION_AT_END
+
+#endif // ENABLE(JIT)
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Interpreter_h
+#define Interpreter_h
+
+#include "ArgList.h"
+#include "JSCell.h"
+#include "JSValue.h"
+#include "Opcode.h"
+#include "RegisterFile.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+
+ class CodeBlock;
+ class EvalNode;
+ class FunctionBodyNode;
+ class Instruction;
+ class InternalFunction;
+ class AssemblerBuffer;
+ class JSFunction;
+ class JSGlobalObject;
+ class ProgramNode;
+ class Register;
+ class ScopeChainNode;
+ class SamplingTool;
+ struct HandlerInfo;
+
+#if ENABLE(JIT)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+ #define STUB_ARGS void* args, ...
+ #define ARGS (reinterpret_cast<void**>(vl_args) - 1)
+#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK
+ #define STUB_ARGS void** args
+ #define ARGS (args)
+#endif
+
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+ #if PLATFORM(X86_64)
+ #define JIT_STUB
+ #elif COMPILER(MSVC)
+ #define JIT_STUB __fastcall
+ #elif COMPILER(GCC)
+ #define JIT_STUB __attribute__ ((fastcall))
+ #else
+ #error Need to support register calling convention in this compiler
+ #endif
+#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK
+ #if COMPILER(MSVC)
+ #define JIT_STUB __cdecl
+ #else
+ #define JIT_STUB
+ #endif
+#endif
+
+// The Mac compilers are fine with this,
+#if PLATFORM(MAC)
+ struct VoidPtrPair {
+ void* first;
+ void* second;
+ };
+#define RETURN_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
+#else
+ typedef uint64_t VoidPtrPair;
+ union VoidPtrPairValue {
+ struct { void* first; void* second; } s;
+ VoidPtrPair i;
+ };
+#define RETURN_PAIR(a,b) VoidPtrPairValue pair = {{ a, b }}; return pair.i
+#endif
+
+#endif // ENABLE(JIT)
+
+ enum DebugHookID {
+ WillExecuteProgram,
+ DidExecuteProgram,
+ DidEnterCallFrame,
+ DidReachBreakpoint,
+ WillLeaveCallFrame,
+ WillExecuteStatement
+ };
+
+ enum { MaxReentryDepth = 128 };
+
+ class Interpreter {
+ friend class JIT;
+ public:
+ Interpreter();
+ ~Interpreter();
+
+ void initialize(JSGlobalData*);
+
+ RegisterFile& registerFile() { return m_registerFile; }
+
+ Opcode getOpcode(OpcodeID id)
+ {
+ #if HAVE(COMPUTED_GOTO)
+ return m_opcodeTable[id];
+ #else
+ return id;
+ #endif
+ }
+
+ OpcodeID getOpcodeID(Opcode opcode)
+ {
+ #if HAVE(COMPUTED_GOTO)
+ ASSERT(isOpcode(opcode));
+ return m_opcodeIDTable.get(opcode);
+ #else
+ return opcode;
+ #endif
+ }
+
+ bool isOpcode(Opcode);
+
+ JSValuePtr execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValuePtr* exception);
+ JSValuePtr execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValuePtr* exception);
+ JSValuePtr execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception);
+
+ JSValuePtr retrieveArguments(CallFrame*, JSFunction*) const;
+ JSValuePtr retrieveCaller(CallFrame*, InternalFunction*) const;
+ void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const;
+
+ void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
+ void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
+
+ void startTimeoutCheck()
+ {
+ if (!m_timeoutCheckCount)
+ resetTimeoutCheck();
+
+ ++m_timeoutCheckCount;
+ }
+
+ void stopTimeoutCheck()
+ {
+ ASSERT(m_timeoutCheckCount);
+ --m_timeoutCheckCount;
+ }
+
+ inline void initTimeout()
+ {
+ ASSERT(!m_timeoutCheckCount);
+ resetTimeoutCheck();
+ m_timeoutTime = 0;
+ m_timeoutCheckCount = 0;
+ }
+
+ void setSampler(SamplingTool* sampler) { m_sampler = sampler; }
+ SamplingTool* sampler() { return m_sampler; }
+
+#if ENABLE(JIT)
+
+ static int JIT_STUB cti_timeout_check(STUB_ARGS);
+ static void JIT_STUB cti_register_file_check(STUB_ARGS);
+
+ static JSObject* JIT_STUB cti_op_convert_this(STUB_ARGS);
+ static void JIT_STUB cti_op_end(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_add(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_inc(STUB_ARGS);
+ static int JIT_STUB cti_op_loop_if_less(STUB_ARGS);
+ static int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_object(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_id(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_id_second(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_second(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_generic(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_id(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_instanceof(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_mul(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_func(STUB_ARGS);
+ static void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS);
+ static VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS);
+ static void JIT_STUB cti_op_create_arguments(STUB_ARGS);
+ static void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS);
+ static void JIT_STUB cti_op_tear_off_activation(STUB_ARGS);
+ static void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS);
+ static void JIT_STUB cti_op_profile_will_call(STUB_ARGS);
+ static void JIT_STUB cti_op_profile_did_call(STUB_ARGS);
+ static void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_array(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_global(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS);
+ static VoidPtrPair JIT_STUB cti_op_resolve_func(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_sub(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_val(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_val_array(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_lesseq(STUB_ARGS);
+ static int JIT_STUB cti_op_loop_if_true(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_base(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_negate(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_skip(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_div(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_dec(STUB_ARGS);
+ static int JIT_STUB cti_op_jless(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_not(STUB_ARGS);
+ static int JIT_STUB cti_op_jtrue(STUB_ARGS);
+ static VoidPtrPair JIT_STUB cti_op_post_inc(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_eq(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_lshift(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_bitand(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_rshift(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_bitnot(STUB_ARGS);
+ static VoidPtrPair JIT_STUB cti_op_resolve_with_base(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_mod(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_less(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_neq(STUB_ARGS);
+ static VoidPtrPair JIT_STUB cti_op_post_dec(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_urshift(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_bitxor(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_bitor(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_call_eval(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_throw(STUB_ARGS);
+ static JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_next_pname(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS);
+ static void JIT_STUB cti_op_pop_scope(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_typeof(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_undefined(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_boolean(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_number(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_string(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_object(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_is_function(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_stricteq(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_nstricteq(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_to_jsnumber(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_in(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS);
+ static void JIT_STUB cti_op_jmp_scopes(STUB_ARGS);
+ static void JIT_STUB cti_op_put_by_index(STUB_ARGS);
+ static void* JIT_STUB cti_op_switch_imm(STUB_ARGS);
+ static void* JIT_STUB cti_op_switch_char(STUB_ARGS);
+ static void* JIT_STUB cti_op_switch_string(STUB_ARGS);
+ static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_val(STUB_ARGS);
+ static void JIT_STUB cti_op_put_getter(STUB_ARGS);
+ static void JIT_STUB cti_op_put_setter(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_new_error(STUB_ARGS);
+ static void JIT_STUB cti_op_debug(STUB_ARGS);
+
+ static JSValueEncodedAsPointer* JIT_STUB cti_vm_throw(STUB_ARGS);
+ static void* JIT_STUB cti_vm_dontLazyLinkCall(STUB_ARGS);
+ static void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS);
+
+#endif // ENABLE(JIT)
+
+ // Default number of ticks before a timeout check should be done.
+ static const int initialTickCountThreshold = 1024;
+
+ bool isJSArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsArrayVptr; }
+ bool isJSString(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsStringVptr; }
+ bool isJSByteArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsByteArrayVptr; }
+
+ private:
+ enum ExecutionFlag { Normal, InitializeAndReturn };
+
+ NEVER_INLINE JSValuePtr callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue);
+ JSValuePtr execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValuePtr* exception);
+
+ NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
+
+ NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
+ NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
+
+ NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValuePtr, unsigned& bytecodeOffset, CodeBlock*&);
+ NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValuePtr&, unsigned bytecodeOffset, bool);
+ NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+
+ static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
+
+ static CallFrame* findFunctionCallFrame(CallFrame*, InternalFunction*);
+
+ JSValuePtr privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValuePtr* exception);
+
+ void dumpCallFrame(CallFrame*);
+ void dumpRegisters(CallFrame*);
+
+ bool checkTimeout(JSGlobalObject*);
+ void resetTimeoutCheck();
+
+ void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&);
+ void uncacheGetByID(CodeBlock*, Instruction* vPC);
+ void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const PutPropertySlot&);
+ void uncachePutByID(CodeBlock*, Instruction* vPC);
+
+ bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
+
+#if ENABLE(JIT)
+ static void throwStackOverflowPreviousFrame(CallFrame**, JSGlobalData*, void*& returnAddress);
+
+ void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&);
+ void tryCTICachePutByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot&);
+#endif
+
+ SamplingTool* m_sampler;
+
+#if ENABLE(JIT)
+ RefPtr<ExecutablePool> m_executablePool;
+ void* m_ctiArrayLengthTrampoline;
+ void* m_ctiStringLengthTrampoline;
+ void* m_ctiVirtualCallPreLink;
+ void* m_ctiVirtualCallLink;
+ void* m_ctiVirtualCall;
+#endif
+
+ int m_reentryDepth;
+ unsigned m_timeoutTime;
+ unsigned m_timeAtLastCheckTimeout;
+ unsigned m_timeExecuting;
+ unsigned m_timeoutCheckCount;
+ unsigned m_ticksUntilNextTimeoutCheck;
+
+ RegisterFile m_registerFile;
+
+ void* m_jsArrayVptr;
+ void* m_jsByteArrayVptr;
+ void* m_jsStringVptr;
+ void* m_jsFunctionVptr;
+
+#if HAVE(COMPUTED_GOTO)
+ Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
+ HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
+#endif
+ };
+
+} // namespace JSC
+
+#endif // Interpreter_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Register_h
+#define Register_h
+
+#include "JSValue.h"
+#include <wtf/VectorTraits.h>
+
+namespace JSC {
+
+ class Arguments;
+ class CodeBlock;
+ class ExecState;
+ class JSActivation;
+ class JSFunction;
+ class JSPropertyNameIterator;
+ class ScopeChainNode;
+
+ struct Instruction;
+
+ typedef ExecState CallFrame;
+
+ class Register {
+ public:
+ Register();
+ Register(JSValuePtr);
+
+ JSValuePtr jsValue(CallFrame*) const;
+ JSValuePtr getJSValue() const;
+
+ bool marked() const;
+ void mark();
+
+ private:
+ friend class ExecState;
+ friend class Interpreter;
+
+ // Only CallFrame and Interpreter should use these functions.
+
+ Register(intptr_t);
+
+ Register(JSActivation*);
+ Register(Arguments*);
+ Register(CallFrame*);
+ Register(CodeBlock*);
+ Register(JSFunction*);
+ Register(JSPropertyNameIterator*);
+ Register(ScopeChainNode*);
+ Register(Instruction*);
+
+ intptr_t i() const;
+ void* v() const;
+
+ JSActivation* activation() const;
+ Arguments* arguments() const;
+ CallFrame* callFrame() const;
+ CodeBlock* codeBlock() const;
+ JSFunction* function() const;
+ JSPropertyNameIterator* propertyNameIterator() const;
+ ScopeChainNode* scopeChain() const;
+ Instruction* vPC() const;
+
+ union {
+ intptr_t i;
+ void* v;
+ JSValueEncodedAsPointer* value;
+
+ JSActivation* activation;
+ Arguments* arguments;
+ CallFrame* callFrame;
+ CodeBlock* codeBlock;
+ JSFunction* function;
+ JSPropertyNameIterator* propertyNameIterator;
+ ScopeChainNode* scopeChain;
+ Instruction* vPC;
+ } u;
+
+#ifndef NDEBUG
+ enum {
+ EmptyType,
+
+ IntType,
+ ValueType,
+
+ ActivationType,
+ ArgumentsType,
+ CallFrameType,
+ CodeBlockType,
+ FunctionType,
+ InstructionType,
+ PropertyNameIteratorType,
+ RegisterType,
+ ScopeChainNodeType
+ } m_type;
+#endif
+ };
+
+#ifndef NDEBUG
+ #define SET_TYPE(type) m_type = (type)
+ // FIXME: The CTI code to put value into registers doesn't set m_type.
+ // Once it does, we can turn this assertion back on.
+ #define ASSERT_TYPE(type)
+#else
+ #define SET_TYPE(type)
+ #define ASSERT_TYPE(type)
+#endif
+
+ ALWAYS_INLINE Register::Register()
+ {
+#ifndef NDEBUG
+ SET_TYPE(EmptyType);
+ u.value = JSValuePtr::encode(noValue());
+#endif
+ }
+
+ ALWAYS_INLINE Register::Register(JSValuePtr v)
+ {
+ SET_TYPE(ValueType);
+ u.value = JSValuePtr::encode(v);
+ }
+
+ // This function is scaffolding for legacy clients. It will eventually go away.
+ ALWAYS_INLINE JSValuePtr Register::jsValue(CallFrame*) const
+ {
+ // Once registers hold doubles, this function will allocate a JSValue*
+ // if the register doesn't hold one already.
+ ASSERT_TYPE(ValueType);
+ return JSValuePtr::decode(u.value);
+ }
+
+ ALWAYS_INLINE JSValuePtr Register::getJSValue() const
+ {
+ ASSERT_TYPE(JSValueType);
+ return JSValuePtr::decode(u.value);
+ }
+
+ ALWAYS_INLINE bool Register::marked() const
+ {
+ return getJSValue().marked();
+ }
+
+ ALWAYS_INLINE void Register::mark()
+ {
+ getJSValue().mark();
+ }
+
+ // Interpreter functions
+
+ ALWAYS_INLINE Register::Register(Arguments* arguments)
+ {
+ SET_TYPE(ArgumentsType);
+ u.arguments = arguments;
+ }
+
+ ALWAYS_INLINE Register::Register(JSActivation* activation)
+ {
+ SET_TYPE(ActivationType);
+ u.activation = activation;
+ }
+
+ ALWAYS_INLINE Register::Register(CallFrame* callFrame)
+ {
+ SET_TYPE(CallFrameType);
+ u.callFrame = callFrame;
+ }
+
+ ALWAYS_INLINE Register::Register(CodeBlock* codeBlock)
+ {
+ SET_TYPE(CodeBlockType);
+ u.codeBlock = codeBlock;
+ }
+
+ ALWAYS_INLINE Register::Register(JSFunction* function)
+ {
+ SET_TYPE(FunctionType);
+ u.function = function;
+ }
+
+ ALWAYS_INLINE Register::Register(Instruction* vPC)
+ {
+ SET_TYPE(InstructionType);
+ u.vPC = vPC;
+ }
+
+ ALWAYS_INLINE Register::Register(ScopeChainNode* scopeChain)
+ {
+ SET_TYPE(ScopeChainNodeType);
+ u.scopeChain = scopeChain;
+ }
+
+ ALWAYS_INLINE Register::Register(JSPropertyNameIterator* propertyNameIterator)
+ {
+ SET_TYPE(PropertyNameIteratorType);
+ u.propertyNameIterator = propertyNameIterator;
+ }
+
+ ALWAYS_INLINE Register::Register(intptr_t i)
+ {
+ SET_TYPE(IntType);
+ u.i = i;
+ }
+
+ ALWAYS_INLINE intptr_t Register::i() const
+ {
+ ASSERT_TYPE(IntType);
+ return u.i;
+ }
+
+ ALWAYS_INLINE void* Register::v() const
+ {
+ return u.v;
+ }
+
+ ALWAYS_INLINE JSActivation* Register::activation() const
+ {
+ ASSERT_TYPE(ActivationType);
+ return u.activation;
+ }
+
+ ALWAYS_INLINE Arguments* Register::arguments() const
+ {
+ ASSERT_TYPE(ArgumentsType);
+ return u.arguments;
+ }
+
+ ALWAYS_INLINE CallFrame* Register::callFrame() const
+ {
+ ASSERT_TYPE(CallFrameType);
+ return u.callFrame;
+ }
+
+ ALWAYS_INLINE CodeBlock* Register::codeBlock() const
+ {
+ ASSERT_TYPE(CodeBlockType);
+ return u.codeBlock;
+ }
+
+ ALWAYS_INLINE JSFunction* Register::function() const
+ {
+ ASSERT_TYPE(FunctionType);
+ return u.function;
+ }
+
+ ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
+ {
+ ASSERT_TYPE(PropertyNameIteratorType);
+ return u.propertyNameIterator;
+ }
+
+ ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
+ {
+ ASSERT_TYPE(ScopeChainNodeType);
+ return u.scopeChain;
+ }
+
+ ALWAYS_INLINE Instruction* Register::vPC() const
+ {
+ ASSERT_TYPE(InstructionType);
+ return u.vPC;
+ }
+
+ #undef SET_TYPE
+ #undef ASSERT_TYPE
+
+} // namespace JSC
+
+namespace WTF {
+
+ template<> struct VectorTraits<JSC::Register> : VectorTraitsBase<true, JSC::Register> { };
+
+} // namespace WTF
+
+#endif // Register_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RegisterFile.h"
+
+namespace JSC {
+
+RegisterFile::~RegisterFile()
+{
+#if HAVE(MMAP)
+ munmap(m_buffer, ((m_max - m_start) + m_maxGlobals) * sizeof(Register));
+#elif HAVE(VIRTUALALLOC)
+ VirtualFree(m_buffer, 0, MEM_RELEASE);
+#else
+ #error "Don't know how to release virtual memory on this platform."
+#endif
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RegisterFile_h
+#define RegisterFile_h
+
+#include "Register.h"
+#include "Collector.h"
+#include <wtf/Noncopyable.h>
+
+#if HAVE(MMAP)
+#include <errno.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#endif
+
+namespace JSC {
+
+/*
+ A register file is a stack of register frames. We represent a register
+ frame by its offset from "base", the logical first entry in the register
+ file. The bottom-most register frame's offset from base is 0.
+
+ In a program where function "a" calls function "b" (global code -> a -> b),
+ the register file might look like this:
+
+ | global frame | call frame | call frame | spare capacity |
+ -----------------------------------------------------------------------------------------------------
+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | | | | | <-- index in buffer
+ -----------------------------------------------------------------------------------------------------
+ | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | | | | | | <-- index relative to base
+ -----------------------------------------------------------------------------------------------------
+ | <-globals | temps-> | <-vars | temps-> | <-vars |
+ ^ ^ ^ ^
+ | | | |
+ buffer base (frame 0) frame 1 frame 2
+
+ Since all variables, including globals, are accessed by negative offsets
+ from their register frame pointers, to keep old global offsets correct, new
+ globals must appear at the beginning of the register file, shifting base
+ to the right.
+
+ If we added one global variable to the register file depicted above, it
+ would look like this:
+
+ | global frame |< >
+ -------------------------------> <
+ | 0 | 1 | 2 | 3 | 4 | 5 |< >snip< > <-- index in buffer
+ -------------------------------> <
+ | -4 | -3 | -2 | -1 | 0 | 1 |< > <-- index relative to base
+ -------------------------------> <
+ | <-globals | temps-> |
+ ^ ^
+ | |
+ buffer base (frame 0)
+
+ As you can see, global offsets relative to base have stayed constant,
+ but base itself has moved. To keep up with possible changes to base,
+ clients keep an indirect pointer, so their calculations update
+ automatically when base changes.
+
+ For client simplicity, the RegisterFile measures size and capacity from
+ "base", not "buffer".
+*/
+
+ class JSGlobalObject;
+
+ class RegisterFile : Noncopyable {
+ friend class JIT;
+ public:
+ enum CallFrameHeaderEntry {
+ CallFrameHeaderSize = 8,
+
+ CodeBlock = -8,
+ ScopeChain = -7,
+ CallerFrame = -6,
+ ReturnPC = -5, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
+ ReturnValueRegister = -4,
+ ArgumentCount = -3,
+ Callee = -2,
+ OptionalCalleeArguments = -1,
+ };
+
+ enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };
+ enum { ArgumentsRegister = 0 };
+
+ static const size_t defaultCapacity = 524288;
+ static const size_t defaultMaxGlobals = 8192;
+ static const size_t allocationSize = 1 << 14;
+ static const size_t allocationSizeMask = allocationSize - 1;
+
+ RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals)
+ : m_numGlobals(0)
+ , m_maxGlobals(maxGlobals)
+ , m_start(0)
+ , m_end(0)
+ , m_max(0)
+ , m_buffer(0)
+ , m_globalObject(0)
+ {
+ size_t bufferLength = (capacity + maxGlobals) * sizeof(Register);
+#if HAVE(MMAP)
+ m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0));
+ if (m_buffer == MAP_FAILED) {
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+ CRASH();
+ }
+#elif HAVE(VIRTUALALLOC)
+ // Ensure bufferLength is a multiple of allocation size
+ bufferLength = (bufferLength + allocationSizeMask) & ~allocationSizeMask;
+ m_buffer = static_cast<Register*>(VirtualAlloc(0, bufferLength, MEM_RESERVE, PAGE_READWRITE));
+ if (!m_buffer) {
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+ CRASH();
+ }
+ int initialAllocation = (maxGlobals * sizeof(Register) + allocationSizeMask) & ~allocationSizeMask;
+ void* commitCheck = VirtualAlloc(m_buffer, initialAllocation, MEM_COMMIT, PAGE_READWRITE);
+ if (commitCheck != m_buffer) {
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+ CRASH();
+ }
+ m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + initialAllocation);
+#else
+ #error "Don't know how to reserve virtual memory on this platform."
+#endif
+ m_start = m_buffer + maxGlobals;
+ m_end = m_start;
+ m_max = m_start + capacity;
+ }
+
+ ~RegisterFile();
+
+ Register* start() const { return m_start; }
+ Register* end() const { return m_end; }
+ size_t size() const { return m_end - m_start; }
+
+ void setGlobalObject(JSGlobalObject* globalObject) { m_globalObject = globalObject; }
+ JSGlobalObject* globalObject() { return m_globalObject; }
+
+ void shrink(Register* newEnd)
+ {
+ if (newEnd < m_end)
+ m_end = newEnd;
+ }
+
+ bool grow(Register* newEnd)
+ {
+ if (newEnd > m_end) {
+ if (newEnd > m_max)
+ return false;
+#if !HAVE(MMAP) && HAVE(VIRTUALALLOC)
+ if (newEnd > m_maxCommitted) {
+ ptrdiff_t additionalAllocation = ((reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_maxCommitted)) + allocationSizeMask) & ~allocationSizeMask;
+ if (!VirtualAlloc(m_maxCommitted, additionalAllocation, MEM_COMMIT, PAGE_READWRITE)) {
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+ CRASH();
+ }
+ m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_maxCommitted) + additionalAllocation);
+ }
+#endif
+ m_end = newEnd;
+ }
+ return true;
+ }
+
+ void setNumGlobals(size_t numGlobals) { m_numGlobals = numGlobals; }
+ int numGlobals() const { return m_numGlobals; }
+ size_t maxGlobals() const { return m_maxGlobals; }
+
+ Register* lastGlobal() const { return m_start - m_numGlobals; }
+
+ void markGlobals(Heap* heap) { heap->markConservatively(lastGlobal(), m_start); }
+ void markCallFrames(Heap* heap) { heap->markConservatively(m_start, m_end); }
+
+ private:
+ size_t m_numGlobals;
+ const size_t m_maxGlobals;
+ Register* m_start;
+ Register* m_end;
+ Register* m_max;
+ Register* m_buffer;
+#if HAVE(VIRTUALALLOC)
+ Register* m_maxCommitted;
+#endif
+
+ JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file.
+ };
+
+} // namespace JSC
+
+#endif // RegisterFile_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+namespace JSC {
+
+size_t ExecutableAllocator::pageSize = 0;
+
+}
+
+#endif // HAVE(ASSEMBLER)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ExecutableAllocator_h
+#define ExecutableAllocator_h
+
+#if ENABLE(ASSEMBLER)
+
+#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+#include <limits>
+
+#define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
+#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
+
+namespace JSC {
+
+class ExecutablePool : public RefCounted<ExecutablePool> {
+private:
+ struct Allocation {
+ char* pages;
+ size_t size;
+ };
+ typedef Vector<Allocation, 2> AllocationList;
+
+public:
+ static PassRefPtr<ExecutablePool> create(size_t n)
+ {
+ return adoptRef(new ExecutablePool(n));
+ }
+
+ void* alloc(size_t n)
+ {
+ ASSERT(m_freePtr <= m_end);
+
+ // Round 'n' up to a multiple of word size; if all allocations are of
+ // word sized quantities, then all subsequent allocations will be aligned.
+ n = roundUpAllocationSize(n, sizeof(void*));
+
+ if (static_cast<ptrdiff_t>(n) < (m_end - m_freePtr)) {
+ void* result = m_freePtr;
+ m_freePtr += n;
+ return result;
+ }
+
+ // Insufficient space to allocate in the existing pool
+ // so we need allocate into a new pool
+ return poolAllocate(n);
+ }
+
+ ~ExecutablePool()
+ {
+ AllocationList::const_iterator end = m_pools.end();
+ for (AllocationList::const_iterator ptr = m_pools.begin(); ptr != end; ++ptr)
+ ExecutablePool::systemRelease(*ptr);
+ }
+
+ size_t available() const { return (m_pools.size() > 1) ? 0 : m_end - m_freePtr; }
+
+private:
+ static Allocation systemAlloc(size_t n);
+ static void systemRelease(const Allocation& alloc);
+
+ inline size_t roundUpAllocationSize(size_t request, size_t granularity)
+ {
+ if ((std::numeric_limits<size_t>::max() - granularity) <= request)
+ CRASH(); // Allocation is too large
+
+ // Round up to next page boundary
+ size_t size = request + (granularity - 1);
+ size = size & ~(granularity - 1);
+ ASSERT(size >= request);
+ return size;
+ }
+
+ ExecutablePool(size_t n);
+
+ void* poolAllocate(size_t n);
+
+ char* m_freePtr;
+ char* m_end;
+ AllocationList m_pools;
+};
+
+class ExecutableAllocator {
+public:
+ static size_t pageSize;
+ ExecutableAllocator()
+ {
+ if (!pageSize)
+ intializePageSize();
+ m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+ }
+
+ PassRefPtr<ExecutablePool> poolForSize(size_t n)
+ {
+ // Try to fit in the existing small allocator
+ if (n < m_smallAllocationPool->available())
+ return m_smallAllocationPool;
+
+ // If the request is large, we just provide a unshared allocator
+ if (n > JIT_ALLOCATOR_LARGE_ALLOC_SIZE)
+ return ExecutablePool::create(n);
+
+ // Create a new allocator
+ RefPtr<ExecutablePool> pool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+
+ // If the new allocator will result in more free space than in
+ // the current small allocator, then we will use it instead
+ if ((pool->available() - n) > m_smallAllocationPool->available())
+ m_smallAllocationPool = pool;
+ return pool.release();
+ }
+
+private:
+ RefPtr<ExecutablePool> m_smallAllocationPool;
+ static void intializePageSize();
+};
+
+inline ExecutablePool::ExecutablePool(size_t n)
+{
+ size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
+ Allocation mem = systemAlloc(allocSize);
+ m_pools.append(mem);
+ m_freePtr = mem.pages;
+ if (!m_freePtr)
+ CRASH(); // Failed to allocate
+ m_end = m_freePtr + allocSize;
+}
+
+inline void* ExecutablePool::poolAllocate(size_t n)
+{
+ size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
+
+ Allocation result = systemAlloc(allocSize);
+ if (!result.pages)
+ CRASH(); // Failed to allocate
+
+ ASSERT(m_end >= m_freePtr);
+ if ((allocSize - n) > static_cast<size_t>(m_end - m_freePtr)) {
+ // Replace allocation pool
+ m_freePtr = result.pages + n;
+ m_end = result.pages + allocSize;
+ }
+
+ m_pools.append(result);
+ return result.pages;
+}
+
+}
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // !defined(ExecutableAllocator)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+namespace JSC {
+
+void ExecutableAllocator::intializePageSize()
+{
+ ExecutableAllocator::pageSize = getpagesize();
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
+{
+ ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(mmap(NULL, n, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0)), n};
+ return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+{
+ int result = munmap(alloc.pages, alloc.size);
+ ASSERT_UNUSED(result, !result);
+}
+
+}
+
+#endif // HAVE(ASSEMBLER)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER)
+
+#include "windows.h"
+
+namespace JSC {
+
+void ExecutableAllocator::intializePageSize()
+{
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ ExecutableAllocator::pageSize = system_info.dwPageSize;
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
+{
+ ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)), n};
+ return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+{
+ VirtualFree(alloc.pages, 0, MEM_RELEASE);
+}
+
+}
+
+#endif // HAVE(ASSEMBLER)
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JIT.h"
+
+#if ENABLE(JIT)
+
+#include "CodeBlock.h"
+#include "JITInlineMethods.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace std;
+
+namespace JSC {
+
+#if COMPILER(GCC) && PLATFORM(X86)
+
+COMPILE_ASSERT(STUB_ARGS_code == 0x0C, STUB_ARGS_code_is_0x0C);
+COMPILE_ASSERT(STUB_ARGS_callFrame == 0x0E, STUB_ARGS_callFrame_is_0x0E);
+
+#if PLATFORM(DARWIN)
+#define SYMBOL_STRING(name) "_" #name
+#else
+#define SYMBOL_STRING(name) #name
+#endif
+
+asm(
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+ "pushl %ebp" "\n"
+ "movl %esp, %ebp" "\n"
+ "pushl %esi" "\n"
+ "pushl %edi" "\n"
+ "pushl %ebx" "\n"
+ "subl $0x1c, %esp" "\n"
+ "movl $512, %esi" "\n"
+ "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = STUB_ARGS_callFrame (see assertion above)
+ "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above)
+ "addl $0x1c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+asm(
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+ "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPvz) "\n"
+#else
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+ "movl %esp, %ecx" "\n"
+#else // JIT_STUB_ARGUMENT_STACK
+ "movl %esp, 0(%esp)" "\n"
+#endif
+ "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n"
+#endif
+ "addl $0x1c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+#elif COMPILER(GCC) && PLATFORM(X86_64)
+
+COMPILE_ASSERT(STUB_ARGS_code == 0x10, STUB_ARGS_code_is_0x10);
+COMPILE_ASSERT(STUB_ARGS_callFrame == 0x12, STUB_ARGS_callFrame_is_0x12);
+
+#if PLATFORM(DARWIN)
+#define SYMBOL_STRING(name) "_" #name
+#else
+#define SYMBOL_STRING(name) #name
+#endif
+
+asm(
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+ "pushq %rbp" "\n"
+ "movq %rsp, %rbp" "\n"
+ "pushq %r12" "\n"
+ "pushq %r13" "\n"
+ "pushq %r14" "\n"
+ "pushq %r15" "\n"
+ "pushq %rbx" "\n"
+ "subq $0x48, %rsp" "\n"
+ "movq $512, %r12" "\n"
+ "movq $0xFFFF000000000000, %r14" "\n"
+ "movq $0xFFFF000000000002, %r15" "\n"
+ "movq 0x90(%rsp), %r13" "\n" // Ox90 = 0x12 * 8, 0x12 = STUB_ARGS_callFrame (see assertion above)
+ "call *0x80(%rsp)" "\n" // Ox80 = 0x10 * 8, 0x10 = STUB_ARGS_code (see assertion above)
+ "addq $0x48, %rsp" "\n"
+ "popq %rbx" "\n"
+ "popq %r15" "\n"
+ "popq %r14" "\n"
+ "popq %r13" "\n"
+ "popq %r12" "\n"
+ "popq %rbp" "\n"
+ "ret" "\n"
+);
+
+asm(
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+ "movq %rsp, %rdi" "\n"
+ "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n"
+#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK
+#error "JIT_STUB_ARGUMENT configuration not supported."
+#endif
+ "addq $0x48, %rsp" "\n"
+ "popq %rbx" "\n"
+ "popq %r15" "\n"
+ "popq %r14" "\n"
+ "popq %r13" "\n"
+ "popq %r12" "\n"
+ "popq %rbp" "\n"
+ "ret" "\n"
+);
+
+#elif COMPILER(MSVC)
+
+extern "C" {
+
+ __declspec(naked) JSValueEncodedAsPointer* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*)
+ {
+ __asm {
+ push ebp;
+ mov ebp, esp;
+ push esi;
+ push edi;
+ push ebx;
+ sub esp, 0x1c;
+ mov esi, 512;
+ mov ecx, esp;
+ mov edi, [esp + 0x38];
+ call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above)
+ add esp, 0x1c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+ __declspec(naked) void ctiVMThrowTrampoline()
+ {
+ __asm {
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+ mov ecx, esp;
+#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK
+#error "JIT_STUB_ARGUMENT configuration not supported."
+#endif
+ call JSC::Interpreter::cti_vm_throw;
+ add esp, 0x1c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+}
+
+#endif
+
+void ctiSetReturnAddress(void** where, void* what)
+{
+ *where = what;
+}
+
+void ctiPatchCallByReturnAddress(void* where, void* what)
+{
+ MacroAssembler::Jump::patch(where, what);
+}
+
+JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
+ : m_interpreter(globalData->interpreter)
+ , m_globalData(globalData)
+ , m_codeBlock(codeBlock)
+ , m_labels(codeBlock ? codeBlock->instructions().size() : 0)
+ , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
+ , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
+ , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
+ , m_jumpTargetsPosition(0)
+{
+}
+
+void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+ unsigned src2 = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ // Jump to a slow case if either operand is a number, or if both are JSCell*s.
+ move(X86::eax, X86::ecx);
+ orPtr(X86::edx, X86::ecx);
+ addSlowCase(emitJumpIfJSCell(X86::ecx));
+ addSlowCase(emitJumpIfImmediateNumber(X86::ecx));
+
+ if (type == OpStrictEq)
+ sete32(X86::edx, X86::eax);
+ else
+ setne32(X86::edx, X86::eax);
+ emitTagAsBoolImmediate(X86::eax);
+#else
+ bool negated = (type == OpNStrictEq);
+
+ // Check that both are immediates, if so check if they're equal
+ Jump firstNotImmediate = emitJumpIfJSCell(X86::eax);
+ Jump secondNotImmediate = emitJumpIfJSCell(X86::edx);
+ Jump bothWereImmediatesButNotEqual = jnePtr(X86::edx, X86::eax);
+
+ // They are equal - set the result to true. (Or false, if negated).
+ move(ImmPtr(JSValuePtr::encode(jsBoolean(!negated))), X86::eax);
+ Jump bothWereImmediatesAndEqual = jump();
+
+ // eax was not an immediate, we haven't yet checked edx.
+ // If edx is also a JSCell, or is 0, then jump to a slow case,
+ // otherwise these values are not equal.
+ firstNotImmediate.link(this);
+ emitJumpSlowCaseIfJSCell(X86::edx);
+ addSlowCase(jePtr(X86::edx, ImmPtr(JSValuePtr::encode(js0()))));
+ Jump firstWasNotImmediate = jump();
+
+ // eax was an immediate, but edx wasn't.
+ // If eax is 0 jump to a slow case, otherwise these values are not equal.
+ secondNotImmediate.link(this);
+ addSlowCase(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0()))));
+
+ // We get here if the two values are different immediates, or one is 0 and the other is a JSCell.
+ // Vaelues are not equal, set the result to false.
+ bothWereImmediatesButNotEqual.link(this);
+ firstWasNotImmediate.link(this);
+ move(ImmPtr(JSValuePtr::encode(jsBoolean(negated))), X86::eax);
+
+ bothWereImmediatesAndEqual.link(this);
+#endif
+
+ emitPutVirtualRegister(dst);
+}
+
+void JIT::emitSlowScriptCheck()
+{
+ Jump skipTimeout = jnzSub32(Imm32(1), timeoutCheckRegister);
+ emitCTICall(Interpreter::cti_timeout_check);
+ move(X86::eax, timeoutCheckRegister);
+ skipTimeout.link(this);
+
+ killLastResultRegister();
+}
+
+
+#define NEXT_OPCODE(name) \
+ m_bytecodeIndex += OPCODE_LENGTH(name); \
+ break;
+
+#define CTI_COMPILE_BINARY_OP(name) \
+ case name: { \
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); \
+ emitCTICall(Interpreter::cti_##name); \
+ emitPutVirtualRegister(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+
+#define CTI_COMPILE_UNARY_OP(name) \
+ case name: { \
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \
+ emitCTICall(Interpreter::cti_##name); \
+ emitPutVirtualRegister(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+
+void JIT::privateCompileMainPass()
+{
+ Instruction* instructionsBegin = m_codeBlock->instructions().begin();
+ unsigned instructionCount = m_codeBlock->instructions().size();
+ unsigned propertyAccessInstructionIndex = 0;
+ unsigned globalResolveInfoIndex = 0;
+ unsigned callLinkInfoIndex = 0;
+
+ for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) {
+ Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
+ ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex);
+
+#if ENABLE(OPCODE_SAMPLING)
+ if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice.
+ sampleInstruction(currentInstruction);
+#endif
+
+ m_labels[m_bytecodeIndex] = label();
+ OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode);
+
+ switch (opcodeID) {
+ case op_mov: {
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_mov);
+ }
+ case op_add: {
+ compileFastArith_op_add(currentInstruction);
+ NEXT_OPCODE(op_add);
+ }
+ case op_end: {
+ if (m_codeBlock->needsFullScopeChain())
+ emitCTICall(Interpreter::cti_op_end);
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+ push(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
+ ret();
+ NEXT_OPCODE(op_end);
+ }
+ case op_jmp: {
+ unsigned target = currentInstruction[1].u.operand;
+ addJump(jump(), target + 1);
+ NEXT_OPCODE(op_jmp);
+ }
+ case op_pre_inc: {
+ compileFastArith_op_pre_inc(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_pre_inc);
+ }
+ case op_loop: {
+ emitSlowScriptCheck();
+
+ unsigned target = currentInstruction[1].u.operand;
+ addJump(jump(), target + 1);
+ NEXT_OPCODE(op_end);
+ }
+ case op_loop_if_less: {
+ emitSlowScriptCheck();
+
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(jl32(X86::eax, Imm32(op2imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ addJump(jl32(X86::eax, X86::edx), target + 3);
+ }
+ NEXT_OPCODE(op_loop_if_less);
+ }
+ case op_loop_if_lesseq: {
+ emitSlowScriptCheck();
+
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(jle32(X86::eax, Imm32(op2imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ addJump(jle32(X86::eax, X86::edx), target + 3);
+ }
+ NEXT_OPCODE(op_loop_if_less);
+ }
+ case op_new_object: {
+ emitCTICall(Interpreter::cti_op_new_object);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_object);
+ }
+ case op_put_by_id: {
+ compilePutByIdHotPath(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, propertyAccessInstructionIndex++);
+ NEXT_OPCODE(op_put_by_id);
+ }
+ case op_get_by_id: {
+ compileGetByIdHotPath(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), propertyAccessInstructionIndex++);
+ NEXT_OPCODE(op_get_by_id);
+ }
+ case op_instanceof: {
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); // value
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx); // baseVal
+ emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // proto
+
+ // check if any are immediates
+ move(X86::eax, X86::ebx);
+ orPtr(X86::ecx, X86::ebx);
+ orPtr(X86::edx, X86::ebx);
+ emitJumpSlowCaseIfNotJSCell(X86::ebx);
+
+ // check that all are object type - this is a bit of a bithack to avoid excess branching;
+ // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType,
+ // this works because NumberType and StringType are smaller
+ move(Imm32(3 * ObjectType), X86::ebx);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::eax);
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ loadPtr(Address(X86::edx, FIELD_OFFSET(JSCell, m_structure)), X86::edx);
+ sub32(Address(X86::eax, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx);
+ sub32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx);
+ addSlowCase(jne32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx));
+
+ // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance
+ load32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), X86::ecx);
+ and32(Imm32(ImplementsHasInstance | OverridesHasInstance), X86::ecx);
+ addSlowCase(jne32(X86::ecx, Imm32(ImplementsHasInstance)));
+
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::ecx); // reload value
+ emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // reload proto
+
+ // optimistically load true result
+ move(ImmPtr(JSValuePtr::encode(jsBoolean(true))), X86::eax);
+
+ Label loop(this);
+
+ // load value's prototype
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
+
+ Jump exit = jePtr(X86::ecx, X86::edx);
+
+ jnePtr(X86::ecx, ImmPtr(JSValuePtr::encode(jsNull())), loop);
+
+ move(ImmPtr(JSValuePtr::encode(jsBoolean(false))), X86::eax);
+
+ exit.link(this);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+
+ NEXT_OPCODE(op_instanceof);
+ }
+ case op_del_by_id: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+ emitPutJITStubArgConstant(ident, 2);
+ emitCTICall(Interpreter::cti_op_del_by_id);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_del_by_id);
+ }
+ case op_mul: {
+ compileFastArith_op_mul(currentInstruction);
+ NEXT_OPCODE(op_mul);
+ }
+ case op_new_func: {
+ FuncDeclNode* func = m_codeBlock->function(currentInstruction[2].u.operand);
+ emitPutJITStubArgConstant(func, 1);
+ emitCTICall(Interpreter::cti_op_new_func);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_func);
+ }
+ case op_call: {
+ compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
+ NEXT_OPCODE(op_call);
+ }
+ case op_call_eval: {
+ compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
+ NEXT_OPCODE(op_call_eval);
+ }
+ case op_construct: {
+ compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
+ NEXT_OPCODE(op_construct);
+ }
+ case op_get_global_var: {
+ JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);
+ move(ImmPtr(globalObject), X86::eax);
+ emitGetVariableObjectRegister(X86::eax, currentInstruction[3].u.operand, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_get_global_var);
+ }
+ case op_put_global_var: {
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::edx);
+ JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);
+ move(ImmPtr(globalObject), X86::eax);
+ emitPutVariableObjectRegister(X86::edx, X86::eax, currentInstruction[2].u.operand);
+ NEXT_OPCODE(op_put_global_var);
+ }
+ case op_get_scoped_var: {
+ int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
+
+ emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::eax);
+ while (skip--)
+ loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, next)), X86::eax);
+
+ loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, object)), X86::eax);
+ emitGetVariableObjectRegister(X86::eax, currentInstruction[2].u.operand, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_get_scoped_var);
+ }
+ case op_put_scoped_var: {
+ int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
+
+ emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::edx);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax);
+ while (skip--)
+ loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, next)), X86::edx);
+
+ loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, object)), X86::edx);
+ emitPutVariableObjectRegister(X86::eax, X86::edx, currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_put_scoped_var);
+ }
+ case op_tear_off_activation: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ emitCTICall(Interpreter::cti_op_tear_off_activation);
+ NEXT_OPCODE(op_tear_off_activation);
+ }
+ case op_tear_off_arguments: {
+ emitCTICall(Interpreter::cti_op_tear_off_arguments);
+ NEXT_OPCODE(op_tear_off_arguments);
+ }
+ case op_ret: {
+ // We could JIT generate the deref, only calling out to C when the refcount hits zero.
+ if (m_codeBlock->needsFullScopeChain())
+ emitCTICall(Interpreter::cti_op_ret_scopeChain);
+
+ // Return the result in %eax.
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ // Grab the return address.
+ emitGetFromCallFrameHeader(RegisterFile::ReturnPC, X86::edx);
+
+ // Restore our caller's "r".
+ emitGetFromCallFrameHeader(RegisterFile::CallerFrame, callFrameRegister);
+
+ // Return.
+ push(X86::edx);
+ ret();
+
+ NEXT_OPCODE(op_ret);
+ }
+ case op_new_array: {
+ emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1);
+ emitPutJITStubArgConstant(currentInstruction[3].u.operand, 2);
+ emitCTICall(Interpreter::cti_op_new_array);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_array);
+ }
+ case op_resolve: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitCTICall(Interpreter::cti_op_resolve);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_resolve);
+ }
+ case op_construct_verify: {
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ emitJumpSlowCaseIfNotJSCell(X86::eax);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
+
+ NEXT_OPCODE(op_construct_verify);
+ }
+ case op_get_by_val: {
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
+ // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if
+ // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation
+ // size is always less than 4Gb). As such zero extending wil have been correct (and extending the value
+ // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
+ // extending since it makes it easier to re-tag the value in the slow case.
+ zeroExtend32ToPtr(X86::edx, X86::edx);
+#else
+ emitFastArithImmToInt(X86::edx);
+#endif
+ emitJumpSlowCaseIfNotJSCell(X86::eax);
+ addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
+
+ // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
+ addSlowCase(jae32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff))));
+
+ // Get the value from the vector
+ loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_get_by_val);
+ }
+ case op_resolve_func: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitCTICall(Interpreter::cti_op_resolve_func);
+ emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_resolve_func);
+ }
+ case op_sub: {
+ compileFastArith_op_sub(currentInstruction);
+ NEXT_OPCODE(op_sub);
+ }
+ case op_put_by_val: {
+ emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ // See comment in op_get_by_val.
+ zeroExtend32ToPtr(X86::edx, X86::edx);
+#else
+ emitFastArithImmToInt(X86::edx);
+#endif
+ emitJumpSlowCaseIfNotJSCell(X86::eax);
+ addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
+
+ // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
+ Jump inFastVector = jb32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff)));
+ // No; oh well, check if the access if within the vector - if so, we may still be okay.
+ addSlowCase(jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength))));
+
+ // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
+ // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff.
+ addSlowCase(jzPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0]))));
+
+ // All good - put the value into the array.
+ inFastVector.link(this);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax);
+ storePtr(X86::eax, BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])));
+ NEXT_OPCODE(op_put_by_val);
+ }
+ CTI_COMPILE_BINARY_OP(op_lesseq)
+ case op_loop_if_true: {
+ emitSlowScriptCheck();
+
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0())));
+ addJump(emitJumpIfImmediateInteger(X86::eax), target + 2);
+
+ addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2);
+ addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))));
+
+ isZero.link(this);
+ NEXT_OPCODE(op_loop_if_true);
+ };
+ case op_resolve_base: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitCTICall(Interpreter::cti_op_resolve_base);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_resolve_base);
+ }
+ case op_negate: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ emitCTICall(Interpreter::cti_op_negate);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_negate);
+ }
+ case op_resolve_skip: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitPutJITStubArgConstant(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain(), 2);
+ emitCTICall(Interpreter::cti_op_resolve_skip);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_resolve_skip);
+ }
+ case op_resolve_global: {
+ // Fast case
+ void* globalObject = currentInstruction[2].u.jsCell;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ unsigned currentIndex = globalResolveInfoIndex++;
+ void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
+ void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
+
+ // Check Structure of global object
+ move(ImmPtr(globalObject), X86::eax);
+ loadPtr(structureAddress, X86::edx);
+ Jump noMatch = jnePtr(X86::edx, Address(X86::eax, FIELD_OFFSET(JSCell, m_structure))); // Structures don't match
+
+ // Load cached property
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSGlobalObject, m_propertyStorage)), X86::eax);
+ load32(offsetAddr, X86::edx);
+ loadPtr(BaseIndex(X86::eax, X86::edx, ScalePtr), X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ Jump end = jump();
+
+ // Slow case
+ noMatch.link(this);
+ emitPutJITStubArgConstant(globalObject, 1);
+ emitPutJITStubArgConstant(ident, 2);
+ emitPutJITStubArgConstant(currentIndex, 3);
+ emitCTICall(Interpreter::cti_op_resolve_global);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ end.link(this);
+ NEXT_OPCODE(op_resolve_global);
+ }
+ CTI_COMPILE_BINARY_OP(op_div)
+ case op_pre_dec: {
+ compileFastArith_op_pre_dec(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_pre_dec);
+ }
+ case op_jnless: {
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(jge32(X86::eax, Imm32(op2imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ addJump(jge32(X86::eax, X86::edx), target + 3);
+ }
+ NEXT_OPCODE(op_jnless);
+ }
+ case op_not: {
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax);
+ addSlowCase(jnzPtr(X86::eax, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_not);
+ }
+ case op_jfalse: {
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0()))), target + 2);
+ Jump isNonZero = emitJumpIfImmediateInteger(X86::eax);
+
+ addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))), target + 2);
+ addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))));
+
+ isNonZero.link(this);
+ NEXT_OPCODE(op_jfalse);
+ };
+ case op_jeq_null: {
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src, X86::eax);
+ Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ addJump(jnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+ Jump wasNotImmediate = jump();
+
+ // Now handle the immediate cases - undefined & null
+ isImmediate.link(this);
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
+ addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2);
+
+ wasNotImmediate.link(this);
+ NEXT_OPCODE(op_jeq_null);
+ };
+ case op_jneq_null: {
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src, X86::eax);
+ Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ addJump(jz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+ Jump wasNotImmediate = jump();
+
+ // Now handle the immediate cases - undefined & null
+ isImmediate.link(this);
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
+ addJump(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsNull()))), target + 2);
+
+ wasNotImmediate.link(this);
+ NEXT_OPCODE(op_jneq_null);
+ }
+ case op_post_inc: {
+ compileFastArith_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand);
+ NEXT_OPCODE(op_post_inc);
+ }
+ case op_unexpected_load: {
+ JSValuePtr v = m_codeBlock->unexpectedConstant(currentInstruction[2].u.operand);
+ move(ImmPtr(JSValuePtr::encode(v)), X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_unexpected_load);
+ }
+ case op_jsr: {
+ int retAddrDst = currentInstruction[1].u.operand;
+ int target = currentInstruction[2].u.operand;
+ DataLabelPtr storeLocation = storePtrWithPatch(Address(callFrameRegister, sizeof(Register) * retAddrDst));
+ addJump(jump(), target + 2);
+ m_jsrSites.append(JSRInfo(storeLocation, label()));
+ NEXT_OPCODE(op_jsr);
+ }
+ case op_sret: {
+ jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
+ NEXT_OPCODE(op_sret);
+ }
+ case op_eq: {
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+ sete32(X86::edx, X86::eax);
+ emitTagAsBoolImmediate(X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_eq);
+ }
+ case op_lshift: {
+ compileFastArith_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
+ NEXT_OPCODE(op_lshift);
+ }
+ case op_bitand: {
+ compileFastArith_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
+ NEXT_OPCODE(op_bitand);
+ }
+ case op_rshift: {
+ compileFastArith_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
+ NEXT_OPCODE(op_rshift);
+ }
+ case op_bitnot: {
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ not32(X86::eax);
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ xorPtr(Imm32(~JSImmediate::TagTypeNumber), X86::eax);
+#endif
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitnot);
+ }
+ case op_resolve_with_base: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitCTICall(Interpreter::cti_op_resolve_with_base);
+ emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_resolve_with_base);
+ }
+ case op_new_func_exp: {
+ FuncExprNode* func = m_codeBlock->functionExpression(currentInstruction[2].u.operand);
+ emitPutJITStubArgConstant(func, 1);
+ emitCTICall(Interpreter::cti_op_new_func_exp);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_func_exp);
+ }
+ case op_mod: {
+ compileFastArith_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand);
+ NEXT_OPCODE(op_mod);
+ }
+ case op_jtrue: {
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ Jump isZero = jePtr(X86::eax, ImmPtr(JSValuePtr::encode(js0())));
+ addJump(emitJumpIfImmediateInteger(X86::eax), target + 2);
+
+ addJump(jePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(true)))), target + 2);
+ addSlowCase(jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsBoolean(false)))));
+
+ isZero.link(this);
+ NEXT_OPCODE(op_jtrue);
+ }
+ CTI_COMPILE_BINARY_OP(op_less)
+ case op_neq: {
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+ setne32(X86::edx, X86::eax);
+ emitTagAsBoolImmediate(X86::eax);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+
+ NEXT_OPCODE(op_neq);
+ }
+ case op_post_dec: {
+ compileFastArith_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand);
+ NEXT_OPCODE(op_post_dec);
+ }
+ CTI_COMPILE_BINARY_OP(op_urshift)
+ case op_bitxor: {
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+ xorPtr(X86::edx, X86::eax);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitxor);
+ }
+ case op_new_regexp: {
+ RegExp* regExp = m_codeBlock->regexp(currentInstruction[2].u.operand);
+ emitPutJITStubArgConstant(regExp, 1);
+ emitCTICall(Interpreter::cti_op_new_regexp);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_regexp);
+ }
+ case op_bitor: {
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
+ emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+ orPtr(X86::edx, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitor);
+ }
+ case op_throw: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ emitCTICall(Interpreter::cti_op_throw);
+#if PLATFORM(X86_64)
+ addPtr(Imm32(0x48), X86::esp);
+ pop(X86::ebx);
+ pop(X86::r15);
+ pop(X86::r14);
+ pop(X86::r13);
+ pop(X86::r12);
+ pop(X86::ebp);
+ ret();
+#else
+ addPtr(Imm32(0x1c), X86::esp);
+ pop(X86::ebx);
+ pop(X86::edi);
+ pop(X86::esi);
+ pop(X86::ebp);
+ ret();
+#endif
+ NEXT_OPCODE(op_throw);
+ }
+ case op_get_pnames: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ emitCTICall(Interpreter::cti_op_get_pnames);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_get_pnames);
+ }
+ case op_next_pname: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ unsigned target = currentInstruction[3].u.operand;
+ emitCTICall(Interpreter::cti_op_next_pname);
+ Jump endOfIter = jzPtr(X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ addJump(jump(), target + 3);
+ endOfIter.link(this);
+ NEXT_OPCODE(op_next_pname);
+ }
+ case op_push_scope: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ emitCTICall(Interpreter::cti_op_push_scope);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_push_scope);
+ }
+ case op_pop_scope: {
+ emitCTICall(Interpreter::cti_op_pop_scope);
+ NEXT_OPCODE(op_pop_scope);
+ }
+ CTI_COMPILE_UNARY_OP(op_typeof)
+ CTI_COMPILE_UNARY_OP(op_is_undefined)
+ CTI_COMPILE_UNARY_OP(op_is_boolean)
+ CTI_COMPILE_UNARY_OP(op_is_number)
+ CTI_COMPILE_UNARY_OP(op_is_string)
+ CTI_COMPILE_UNARY_OP(op_is_object)
+ CTI_COMPILE_UNARY_OP(op_is_function)
+ case op_stricteq: {
+ compileOpStrictEq(currentInstruction, OpStrictEq);
+ NEXT_OPCODE(op_stricteq);
+ }
+ case op_nstricteq: {
+ compileOpStrictEq(currentInstruction, OpNStrictEq);
+ NEXT_OPCODE(op_nstricteq);
+ }
+ case op_to_jsnumber: {
+ int srcVReg = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(srcVReg, X86::eax);
+
+ Jump wasImmediate = emitJumpIfImmediateInteger(X86::eax);
+
+ emitJumpSlowCaseIfNotJSCell(X86::eax, srcVReg);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), Imm32(NumberType)));
+
+ wasImmediate.link(this);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_to_jsnumber);
+ }
+ CTI_COMPILE_BINARY_OP(op_in)
+ case op_push_new_scope: {
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 1);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_push_new_scope);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_push_new_scope);
+ }
+ case op_catch: {
+ emitGetCTIParam(STUB_ARGS_callFrame, callFrameRegister);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_catch);
+ }
+ case op_jmp_scopes: {
+ unsigned count = currentInstruction[1].u.operand;
+ emitPutJITStubArgConstant(count, 1);
+ emitCTICall(Interpreter::cti_op_jmp_scopes);
+ unsigned target = currentInstruction[2].u.operand;
+ addJump(jump(), target + 2);
+ NEXT_OPCODE(op_jmp_scopes);
+ }
+ case op_put_by_index: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
+ emitCTICall(Interpreter::cti_op_put_by_index);
+ NEXT_OPCODE(op_put_by_index);
+ }
+ case op_switch_imm: {
+ unsigned tableIndex = currentInstruction[1].u.operand;
+ unsigned defaultOffset = currentInstruction[2].u.operand;
+ unsigned scrutinee = currentInstruction[3].u.operand;
+
+ // create jump table for switch destinations, track this switch statement.
+ SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
+ m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
+ jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+
+ emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
+ emitPutJITStubArgConstant(tableIndex, 2);
+ emitCTICall(Interpreter::cti_op_switch_imm);
+ jump(X86::eax);
+ NEXT_OPCODE(op_switch_imm);
+ }
+ case op_switch_char: {
+ unsigned tableIndex = currentInstruction[1].u.operand;
+ unsigned defaultOffset = currentInstruction[2].u.operand;
+ unsigned scrutinee = currentInstruction[3].u.operand;
+
+ // create jump table for switch destinations, track this switch statement.
+ SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
+ m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
+ jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
+
+ emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
+ emitPutJITStubArgConstant(tableIndex, 2);
+ emitCTICall(Interpreter::cti_op_switch_char);
+ jump(X86::eax);
+ NEXT_OPCODE(op_switch_char);
+ }
+ case op_switch_string: {
+ unsigned tableIndex = currentInstruction[1].u.operand;
+ unsigned defaultOffset = currentInstruction[2].u.operand;
+ unsigned scrutinee = currentInstruction[3].u.operand;
+
+ // create jump table for switch destinations, track this switch statement.
+ StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
+ m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
+
+ emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
+ emitPutJITStubArgConstant(tableIndex, 2);
+ emitCTICall(Interpreter::cti_op_switch_string);
+ jump(X86::eax);
+ NEXT_OPCODE(op_switch_string);
+ }
+ case op_del_by_val: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_del_by_val);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_del_by_val);
+ }
+ case op_put_getter: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 2);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
+ emitCTICall(Interpreter::cti_op_put_getter);
+ NEXT_OPCODE(op_put_getter);
+ }
+ case op_put_setter: {
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ emitPutJITStubArgConstant(ident, 2);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
+ emitCTICall(Interpreter::cti_op_put_setter);
+ NEXT_OPCODE(op_put_setter);
+ }
+ case op_new_error: {
+ JSValuePtr message = m_codeBlock->unexpectedConstant(currentInstruction[3].u.operand);
+ emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1);
+ emitPutJITStubArgConstant(JSValuePtr::encode(message), 2);
+ emitPutJITStubArgConstant(m_bytecodeIndex, 3);
+ emitCTICall(Interpreter::cti_op_new_error);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_new_error);
+ }
+ case op_debug: {
+ emitPutJITStubArgConstant(currentInstruction[1].u.operand, 1);
+ emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2);
+ emitPutJITStubArgConstant(currentInstruction[3].u.operand, 3);
+ emitCTICall(Interpreter::cti_op_debug);
+ NEXT_OPCODE(op_debug);
+ }
+ case op_eq_null: {
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src1, X86::eax);
+ Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
+
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ setnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
+ sete32(Imm32(JSImmediate::FullTagTypeNull), X86::eax);
+
+ wasNotImmediate.link(this);
+
+ emitTagAsBoolImmediate(X86::eax);
+ emitPutVirtualRegister(dst);
+
+ NEXT_OPCODE(op_eq_null);
+ }
+ case op_neq_null: {
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src1, X86::eax);
+ Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
+
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ setz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
+ setne32(Imm32(JSImmediate::FullTagTypeNull), X86::eax);
+
+ wasNotImmediate.link(this);
+
+ emitTagAsBoolImmediate(X86::eax);
+ emitPutVirtualRegister(dst);
+
+ NEXT_OPCODE(op_neq_null);
+ }
+ case op_enter: {
+ // Even though CTI doesn't use them, we initialize our constant
+ // registers to zap stale pointers, to avoid unnecessarily prolonging
+ // object lifetime and increasing GC pressure.
+ size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters();
+ for (size_t j = 0; j < count; ++j)
+ emitInitRegister(j);
+
+ NEXT_OPCODE(op_enter);
+ }
+ case op_enter_with_activation: {
+ // Even though CTI doesn't use them, we initialize our constant
+ // registers to zap stale pointers, to avoid unnecessarily prolonging
+ // object lifetime and increasing GC pressure.
+ size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters();
+ for (size_t j = 0; j < count; ++j)
+ emitInitRegister(j);
+
+ emitCTICall(Interpreter::cti_op_push_activation);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+
+ NEXT_OPCODE(op_enter_with_activation);
+ }
+ case op_create_arguments: {
+ if (m_codeBlock->m_numParameters == 1)
+ emitCTICall(Interpreter::cti_op_create_arguments_no_params);
+ else
+ emitCTICall(Interpreter::cti_op_create_arguments);
+ NEXT_OPCODE(op_create_arguments);
+ }
+ case op_convert_this: {
+ emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ emitJumpSlowCaseIfNotJSCell(X86::eax);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::edx);
+ addSlowCase(jnz32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
+
+ NEXT_OPCODE(op_convert_this);
+ }
+ case op_profile_will_call: {
+ emitGetCTIParam(STUB_ARGS_profilerReference, X86::eax);
+ Jump noProfiler = jzPtr(Address(X86::eax));
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax);
+ emitCTICall(Interpreter::cti_op_profile_will_call);
+ noProfiler.link(this);
+
+ NEXT_OPCODE(op_profile_will_call);
+ }
+ case op_profile_did_call: {
+ emitGetCTIParam(STUB_ARGS_profilerReference, X86::eax);
+ Jump noProfiler = jzPtr(Address(X86::eax));
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax);
+ emitCTICall(Interpreter::cti_op_profile_did_call);
+ noProfiler.link(this);
+
+ NEXT_OPCODE(op_profile_did_call);
+ }
+ case op_get_array_length:
+ case op_get_by_id_chain:
+ case op_get_by_id_generic:
+ case op_get_by_id_proto:
+ case op_get_by_id_proto_list:
+ case op_get_by_id_self:
+ case op_get_by_id_self_list:
+ case op_get_string_length:
+ case op_put_by_id_generic:
+ case op_put_by_id_replace:
+ case op_put_by_id_transition:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
+ ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
+
+#ifndef NDEBUG
+ // reset this, in order to guard it's use with asserts
+ m_bytecodeIndex = (unsigned)-1;
+#endif
+}
+
+
+void JIT::privateCompileLinkPass()
+{
+ unsigned jmpTableCount = m_jmpTable.size();
+ for (unsigned i = 0; i < jmpTableCount; ++i)
+ m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeIndex], this);
+ m_jmpTable.clear();
+}
+
+void JIT::privateCompileSlowCases()
+{
+ Instruction* instructionsBegin = m_codeBlock->instructions().begin();
+ unsigned propertyAccessInstructionIndex = 0;
+ unsigned callLinkInfoIndex = 0;
+
+ for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
+ // FIXME: enable peephole optimizations for slow cases when applicable
+ killLastResultRegister();
+
+ m_bytecodeIndex = iter->to;
+#ifndef NDEBUG
+ unsigned firstTo = m_bytecodeIndex;
+#endif
+ Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
+
+ switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
+ case op_convert_this: {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_convert_this);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_convert_this);
+ }
+ case op_add: {
+ compileFastArithSlow_op_add(currentInstruction, iter);
+ NEXT_OPCODE(op_add);
+ }
+ case op_construct_verify: {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+
+ NEXT_OPCODE(op_construct_verify);
+ }
+ case op_get_by_val: {
+ // The slow case that handles accesses to arrays (below) may jump back up to here.
+ Label beginGetByValSlow(this);
+
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
+ notImm.link(this);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_get_by_val);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
+
+ // This is slow case that handles accesses to arrays above the fast cut-off.
+ // First, check if this is an access to the vector
+ linkSlowCase(iter);
+ jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength)), beginGetByValSlow);
+
+ // okay, missed the fast region, but it is still in the vector. Get the value.
+ loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::ecx);
+ // Check whether the value loaded is zero; if so we need to return undefined.
+ jzPtr(X86::ecx, beginGetByValSlow);
+ move(X86::ecx, X86::eax);
+ emitPutVirtualRegister(currentInstruction[1].u.operand, X86::eax);
+
+ NEXT_OPCODE(op_get_by_val);
+ }
+ case op_sub: {
+ compileFastArithSlow_op_sub(currentInstruction, iter);
+ NEXT_OPCODE(op_sub);
+ }
+ case op_rshift: {
+ compileFastArithSlow_op_rshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
+ NEXT_OPCODE(op_rshift);
+ }
+ case op_lshift: {
+ compileFastArithSlow_op_lshift(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
+ NEXT_OPCODE(op_lshift);
+ }
+ case op_loop_if_less: {
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_loop_if_less);
+ emitJumpSlowToHot(jnz32(X86::eax), target + 3);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_loop_if_less);
+ emitJumpSlowToHot(jnz32(X86::eax), target + 3);
+ }
+ NEXT_OPCODE(op_loop_if_less);
+ }
+ case op_put_by_id: {
+ compilePutByIdSlowCase(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, iter, propertyAccessInstructionIndex++);
+ NEXT_OPCODE(op_put_by_id);
+ }
+ case op_get_by_id: {
+ compileGetByIdSlowCase(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), iter, propertyAccessInstructionIndex++);
+ NEXT_OPCODE(op_get_by_id);
+ }
+ case op_loop_if_lesseq: {
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_loop_if_lesseq);
+ emitJumpSlowToHot(jnz32(X86::eax), target + 3);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_loop_if_lesseq);
+ emitJumpSlowToHot(jnz32(X86::eax), target + 3);
+ }
+ NEXT_OPCODE(op_loop_if_lesseq);
+ }
+ case op_pre_inc: {
+ compileFastArithSlow_op_pre_inc(currentInstruction[1].u.operand, iter);
+ NEXT_OPCODE(op_pre_inc);
+ }
+ case op_put_by_val: {
+ // Normal slow cases - either is not an immediate imm, or is an array.
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
+ notImm.link(this);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitPutJITStubArg(X86::ecx, 3);
+ emitCTICall(Interpreter::cti_op_put_by_val);
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val));
+
+ // slow cases for immediate int accesses to arrays
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitPutJITStubArg(X86::ecx, 3);
+ emitCTICall(Interpreter::cti_op_put_by_val_array);
+
+ NEXT_OPCODE(op_put_by_val);
+ }
+ case op_loop_if_true: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_jtrue);
+ unsigned target = currentInstruction[2].u.operand;
+ emitJumpSlowToHot(jnz32(X86::eax), target + 2);
+ NEXT_OPCODE(op_loop_if_true);
+ }
+ case op_pre_dec: {
+ compileFastArithSlow_op_pre_dec(currentInstruction[1].u.operand, iter);
+ NEXT_OPCODE(op_pre_dec);
+ }
+ case op_jnless: {
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_jless);
+ emitJumpSlowToHot(jz32(X86::eax), target + 3);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_jless);
+ emitJumpSlowToHot(jz32(X86::eax), target + 3);
+ }
+ NEXT_OPCODE(op_jnless);
+ }
+ case op_not: {
+ linkSlowCase(iter);
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), X86::eax);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_not);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_not);
+ }
+ case op_jfalse: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_jtrue);
+ unsigned target = currentInstruction[2].u.operand;
+ emitJumpSlowToHot(jz32(X86::eax), target + 2); // inverted!
+ NEXT_OPCODE(op_jfalse);
+ }
+ case op_post_inc: {
+ compileFastArithSlow_op_post_inc(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);
+ NEXT_OPCODE(op_post_inc);
+ }
+ case op_bitnot: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_bitnot);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitnot);
+ }
+ case op_bitand: {
+ compileFastArithSlow_op_bitand(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
+ NEXT_OPCODE(op_bitand);
+ }
+ case op_jtrue: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_jtrue);
+ unsigned target = currentInstruction[2].u.operand;
+ emitJumpSlowToHot(jnz32(X86::eax), target + 2);
+ NEXT_OPCODE(op_jtrue);
+ }
+ case op_post_dec: {
+ compileFastArithSlow_op_post_dec(currentInstruction[1].u.operand, currentInstruction[2].u.operand, iter);
+ NEXT_OPCODE(op_post_dec);
+ }
+ case op_bitxor: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_bitxor);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitxor);
+ }
+ case op_bitor: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_bitor);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_bitor);
+ }
+ case op_eq: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_eq);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_eq);
+ }
+ case op_neq: {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_neq);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_neq);
+ }
+ case op_stricteq: {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ linkSlowCase(iter);
+#endif
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_stricteq);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_stricteq);
+ }
+ case op_nstricteq: {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ linkSlowCase(iter);
+#endif
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ emitCTICall(Interpreter::cti_op_nstricteq);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_nstricteq);
+ }
+ case op_instanceof: {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(currentInstruction[4].u.operand, 3, X86::ecx);
+ emitCTICall(Interpreter::cti_op_instanceof);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_instanceof);
+ }
+ case op_mod: {
+ compileFastArithSlow_op_mod(currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, iter);
+ NEXT_OPCODE(op_mod);
+ }
+ case op_mul: {
+ compileFastArithSlow_op_mul(currentInstruction, iter);
+ NEXT_OPCODE(op_mul);
+ }
+
+ case op_call: {
+ compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
+ NEXT_OPCODE(op_call);
+ }
+ case op_call_eval: {
+ compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
+ NEXT_OPCODE(op_call_eval);
+ }
+ case op_construct: {
+ compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
+ NEXT_OPCODE(op_construct);
+ }
+ case op_to_jsnumber: {
+ linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand);
+ linkSlowCase(iter);
+
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_to_jsnumber);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ NEXT_OPCODE(op_to_jsnumber);
+ }
+
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen.");
+ ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen.");
+
+ emitJumpSlowToHot(jump(), 0);
+ }
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
+#endif
+ ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
+
+#ifndef NDEBUG
+ // reset this, in order to guard it's use with asserts
+ m_bytecodeIndex = (unsigned)-1;
+#endif
+}
+
+void JIT::privateCompile()
+{
+ sampleCodeBlock(m_codeBlock);
+#if ENABLE(OPCODE_SAMPLING)
+ sampleInstruction(m_codeBlock->instructions().begin());
+#endif
+
+ // Could use a pop_m, but would need to offset the following instruction if so.
+ pop(X86::ecx);
+ emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
+
+ Jump slowRegisterFileCheck;
+ Label afterRegisterFileCheck;
+ if (m_codeBlock->codeType() == FunctionCode) {
+ // In the case of a fast linked call, we do not set this up in the caller.
+ emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
+
+ emitGetCTIParam(STUB_ARGS_registerFile, X86::eax);
+ addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, X86::edx);
+
+ slowRegisterFileCheck = jg32(X86::edx, Address(X86::eax, FIELD_OFFSET(RegisterFile, m_end)));
+ afterRegisterFileCheck = label();
+ }
+
+ privateCompileMainPass();
+ privateCompileLinkPass();
+ privateCompileSlowCases();
+
+ if (m_codeBlock->codeType() == FunctionCode) {
+ slowRegisterFileCheck.link(this);
+ m_bytecodeIndex = 0; // emitCTICall will add to the map, but doesn't actually need this...
+ emitCTICall(Interpreter::cti_register_file_check);
+#ifndef NDEBUG
+ // reset this, in order to guard it's use with asserts
+ m_bytecodeIndex = (unsigned)-1;
+#endif
+ jump(afterRegisterFileCheck);
+ }
+
+ ASSERT(m_jmpTable.isEmpty());
+
+ RefPtr<ExecutablePool> allocator = m_globalData->poolForSize(m_assembler.size());
+ void* code = m_assembler.executableCopy(allocator.get());
+ JITCodeRef codeRef(code, allocator);
+#ifndef NDEBUG
+ codeRef.codeSize = m_assembler.size();
+#endif
+
+ PatchBuffer patchBuffer(code);
+
+ // Translate vPC offsets into addresses in JIT generated code, for switch tables.
+ for (unsigned i = 0; i < m_switches.size(); ++i) {
+ SwitchRecord record = m_switches[i];
+ unsigned bytecodeIndex = record.bytecodeIndex;
+
+ if (record.type != SwitchRecord::String) {
+ ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character);
+ ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
+
+ record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]);
+
+ for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
+ unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
+ record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
+ }
+ } else {
+ ASSERT(record.type == SwitchRecord::String);
+
+ record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]);
+
+ StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();
+ for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
+ unsigned offset = it->second.branchOffset;
+ it->second.ctiOffset = offset ? patchBuffer.addressOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < m_codeBlock->numberOfExceptionHandlers(); ++i) {
+ HandlerInfo& handler = m_codeBlock->exceptionHandler(i);
+ handler.nativeCode = patchBuffer.addressOf(m_labels[handler.target]);
+ }
+
+ for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
+ if (iter->to)
+ patchBuffer.link(iter->from, iter->to);
+ }
+
+ if (m_codeBlock->hasExceptionInfo()) {
+ m_codeBlock->pcVector().reserveCapacity(m_calls.size());
+ for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter)
+ m_codeBlock->pcVector().append(PC(reinterpret_cast<void**>(patchBuffer.addressOf(iter->from)) - reinterpret_cast<void**>(code), iter->bytecodeIndex));
+ }
+
+ // Link absolute addresses for jsr
+ for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
+ patchBuffer.setPtr(iter->storeLocation, patchBuffer.addressOf(iter->target));
+
+ for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) {
+ StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ info.callReturnLocation = patchBuffer.addressOf(m_propertyAccessCompilationInfo[i].callReturnLocation);
+ info.hotPathBegin = patchBuffer.addressOf(m_propertyAccessCompilationInfo[i].hotPathBegin);
+#else
+ info.callReturnLocation = 0;
+ info.hotPathBegin = 0;
+#endif
+ }
+ for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
+ CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
+#if ENABLE(JIT_OPTIMIZE_CALL)
+ info.callReturnLocation = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].callReturnLocation);
+ info.hotPathBegin = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
+ info.hotPathOther = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].hotPathOther);
+ info.coldPathOther = patchBuffer.addressOf(m_callStructureStubCompilationInfo[i].coldPathOther);
+#else
+ info.callReturnLocation = 0;
+ info.hotPathBegin = 0;
+ info.hotPathOther = 0;
+ info.coldPathOther = 0;
+#endif
+ }
+
+ m_codeBlock->setJITCode(codeRef);
+}
+
+void JIT::privateCompileCTIMachineTrampolines()
+{
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ // (1) The first function provides fast property access for array length
+ Label arrayLengthBegin = align();
+
+ // Check eax is an array
+ Jump array_failureCases1 = emitJumpIfNotJSCell(X86::eax);
+ Jump array_failureCases2 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr));
+
+ // Checks out okay! - get the length from the storage
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::eax);
+ load32(Address(X86::eax, FIELD_OFFSET(ArrayStorage, m_length)), X86::eax);
+
+ Jump array_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
+
+ // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+
+ ret();
+
+ // (2) The second function provides fast property access for string length
+ Label stringLengthBegin = align();
+
+ // Check eax is a string
+ Jump string_failureCases1 = emitJumpIfNotJSCell(X86::eax);
+ Jump string_failureCases2 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsStringVptr));
+
+ // Checks out okay! - get the length from the Ustring.
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep)), X86::eax);
+ load32(Address(X86::eax, FIELD_OFFSET(UString::Rep, len)), X86::eax);
+
+ Jump string_failureCases3 = ja32(X86::eax, Imm32(JSImmediate::maxImmediateInt));
+
+ // X86::eax contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+
+ ret();
+#endif
+
+ // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
+
+ Label virtualCallPreLinkBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax);
+ Jump hasCodeBlock1 = jnzPtr(X86::eax);
+ pop(X86::ebx);
+ restoreArgumentReference();
+ Jump callJSFunction1 = call();
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ hasCodeBlock1.link(this);
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay1 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx);
+ pop(X86::ebx);
+ emitPutJITStubArg(X86::ebx, 2);
+ emitPutJITStubArg(X86::eax, 4);
+ restoreArgumentReference();
+ Jump callArityCheck1 = call();
+ move(X86::edx, callFrameRegister);
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ arityCheckOkay1.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ pop(X86::ebx);
+ emitPutJITStubArg(X86::ebx, 2);
+ restoreArgumentReference();
+ Jump callDontLazyLinkCall = call();
+ push(X86::ebx);
+
+ jump(X86::eax);
+
+ Label virtualCallLinkBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax);
+ Jump hasCodeBlock2 = jnzPtr(X86::eax);
+ pop(X86::ebx);
+ restoreArgumentReference();
+ Jump callJSFunction2 = call();
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ hasCodeBlock2.link(this);
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay2 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx);
+ pop(X86::ebx);
+ emitPutJITStubArg(X86::ebx, 2);
+ emitPutJITStubArg(X86::eax, 4);
+ restoreArgumentReference();
+ Jump callArityCheck2 = call();
+ move(X86::edx, callFrameRegister);
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ arityCheckOkay2.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ pop(X86::ebx);
+ emitPutJITStubArg(X86::ebx, 2);
+ restoreArgumentReference();
+ Jump callLazyLinkCall = call();
+ push(X86::ebx);
+
+ jump(X86::eax);
+
+ Label virtualCallBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_body)), X86::eax);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(FunctionBodyNode, m_code)), X86::eax);
+ Jump hasCodeBlock3 = jnzPtr(X86::eax);
+ pop(X86::ebx);
+ restoreArgumentReference();
+ Jump callJSFunction3 = call();
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ hasCodeBlock3.link(this);
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay3 = je32(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_numParameters)), X86::edx);
+ pop(X86::ebx);
+ emitPutJITStubArg(X86::ebx, 2);
+ emitPutJITStubArg(X86::eax, 4);
+ restoreArgumentReference();
+ Jump callArityCheck3 = call();
+ move(X86::edx, callFrameRegister);
+ emitGetJITStubArg(1, X86::ecx);
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ arityCheckOkay3.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ // load ctiCode from the new codeBlock.
+ loadPtr(Address(X86::eax, FIELD_OFFSET(CodeBlock, m_jitCode)), X86::eax);
+
+ jump(X86::eax);
+
+ // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
+ m_interpreter->m_executablePool = m_globalData->poolForSize(m_assembler.size());
+ void* code = m_assembler.executableCopy(m_interpreter->m_executablePool.get());
+ PatchBuffer patchBuffer(code);
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ patchBuffer.link(array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
+ patchBuffer.link(array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
+ patchBuffer.link(array_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
+ patchBuffer.link(string_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
+
+ m_interpreter->m_ctiArrayLengthTrampoline = patchBuffer.addressOf(arrayLengthBegin);
+ m_interpreter->m_ctiStringLengthTrampoline = patchBuffer.addressOf(stringLengthBegin);
+#endif
+ patchBuffer.link(callArityCheck1, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
+ patchBuffer.link(callArityCheck2, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
+ patchBuffer.link(callArityCheck3, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
+ patchBuffer.link(callJSFunction1, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
+ patchBuffer.link(callJSFunction2, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
+ patchBuffer.link(callJSFunction3, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
+ patchBuffer.link(callDontLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_dontLazyLinkCall));
+ patchBuffer.link(callLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_lazyLinkCall));
+
+ m_interpreter->m_ctiVirtualCallPreLink = patchBuffer.addressOf(virtualCallPreLinkBegin);
+ m_interpreter->m_ctiVirtualCallLink = patchBuffer.addressOf(virtualCallLinkBegin);
+ m_interpreter->m_ctiVirtualCall = patchBuffer.addressOf(virtualCallBegin);
+}
+
+void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
+{
+ loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), dst);
+ loadPtr(Address(dst, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), dst);
+ loadPtr(Address(dst, index * sizeof(Register)), dst);
+}
+
+void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
+{
+ loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), variableObject);
+ loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), variableObject);
+ storePtr(src, Address(variableObject, index * sizeof(Register)));
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JIT_h
+#define JIT_h
+
+#include <wtf/Platform.h>
+#include <bytecode/SamplingTool.h>
+
+#if ENABLE(JIT)
+
+#define WTF_USE_CTI_REPATCH_PIC 1
+
+#include "Interpreter.h"
+#include "Opcode.h"
+#include "RegisterFile.h"
+#include "MacroAssembler.h"
+#include "Profiler.h"
+#include <wtf/AlwaysInline.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(X86_64)
+#define STUB_ARGS_offset 0x10
+#else
+#define STUB_ARGS_offset 0x0C
+#endif
+
+#define STUB_ARGS_code (STUB_ARGS_offset)
+#define STUB_ARGS_registerFile (STUB_ARGS_offset + 1)
+#define STUB_ARGS_callFrame (STUB_ARGS_offset + 2)
+#define STUB_ARGS_exception (STUB_ARGS_offset + 3)
+#define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4)
+#define STUB_ARGS_globalData (STUB_ARGS_offset + 5)
+
+#define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame])
+#define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile])
+#define ARG_exception static_cast<JSValuePtr*>(ARGS[STUB_ARGS_exception])
+#define ARG_profilerReference static_cast<Profiler**>(ARGS[STUB_ARGS_profilerReference])
+#define ARG_globalData static_cast<JSGlobalData*>(ARGS[STUB_ARGS_globalData])
+
+#define ARG_setCallFrame(newCallFrame) (ARGS[STUB_ARGS_callFrame] = (newCallFrame))
+
+#define ARG_src1 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[1]))
+#define ARG_src2 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[2]))
+#define ARG_src3 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[3]))
+#define ARG_src4 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[4]))
+#define ARG_src5 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[5]))
+#define ARG_id1 static_cast<Identifier*>(ARGS[1])
+#define ARG_id2 static_cast<Identifier*>(ARGS[2])
+#define ARG_id3 static_cast<Identifier*>(ARGS[3])
+#define ARG_id4 static_cast<Identifier*>(ARGS[4])
+#define ARG_int1 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[1]))
+#define ARG_int2 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[2]))
+#define ARG_int3 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[3]))
+#define ARG_int4 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[4]))
+#define ARG_int5 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[5]))
+#define ARG_int6 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[6]))
+#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])
+#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])
+#define ARG_regexp1 static_cast<RegExp*>(ARGS[1])
+#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])
+#define ARG_returnAddress2 static_cast<void*>(ARGS[2])
+#define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4])
+
+#define STUB_RETURN_ADDRESS_SLOT (ARGS[-1])
+
+namespace JSC {
+
+ class CodeBlock;
+ class JSPropertyNameIterator;
+ class Interpreter;
+ class Register;
+ class RegisterFile;
+ class ScopeChainNode;
+ class SimpleJumpTable;
+ class StringJumpTable;
+ class StructureChain;
+
+ struct CallLinkInfo;
+ struct Instruction;
+ struct OperandTypes;
+ struct PolymorphicAccessStructureList;
+ struct StructureStubInfo;
+
+ typedef JSValueEncodedAsPointer* (JIT_STUB *CTIHelper_j)(STUB_ARGS);
+ typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS);
+ typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS);
+ typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS);
+ typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS);
+ typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS);
+ typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS);
+
+ struct CallRecord {
+ MacroAssembler::Jump from;
+ unsigned bytecodeIndex;
+ void* to;
+
+ CallRecord()
+ {
+ }
+
+ CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0)
+ : from(from)
+ , bytecodeIndex(bytecodeIndex)
+ , to(to)
+ {
+ }
+ };
+
+ struct JumpTable {
+ MacroAssembler::Jump from;
+ unsigned toBytecodeIndex;
+
+ JumpTable(MacroAssembler::Jump f, unsigned t)
+ : from(f)
+ , toBytecodeIndex(t)
+ {
+ }
+ };
+
+ struct SlowCaseEntry {
+ MacroAssembler::Jump from;
+ unsigned to;
+ unsigned hint;
+
+ SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0)
+ : from(f)
+ , to(t)
+ , hint(h)
+ {
+ }
+ };
+
+ struct SwitchRecord {
+ enum Type {
+ Immediate,
+ Character,
+ String
+ };
+
+ Type type;
+
+ union {
+ SimpleJumpTable* simpleJumpTable;
+ StringJumpTable* stringJumpTable;
+ } jumpTable;
+
+ unsigned bytecodeIndex;
+ unsigned defaultOffset;
+
+ SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type)
+ : type(type)
+ , bytecodeIndex(bytecodeIndex)
+ , defaultOffset(defaultOffset)
+ {
+ this->jumpTable.simpleJumpTable = jumpTable;
+ }
+
+ SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset)
+ : type(String)
+ , bytecodeIndex(bytecodeIndex)
+ , defaultOffset(defaultOffset)
+ {
+ this->jumpTable.stringJumpTable = jumpTable;
+ }
+ };
+
+ struct PropertyStubCompilationInfo {
+ MacroAssembler::Jump callReturnLocation;
+ MacroAssembler::Label hotPathBegin;
+ };
+
+ struct StructureStubCompilationInfo {
+ MacroAssembler::DataLabelPtr hotPathBegin;
+ MacroAssembler::Jump hotPathOther;
+ MacroAssembler::Jump callReturnLocation;
+ MacroAssembler::Label coldPathOther;
+ };
+
+ extern "C" {
+ JSValueEncodedAsPointer* ctiTrampoline(
+#if PLATFORM(X86_64)
+ // FIXME: (bug #22910) this will force all arguments onto the stack (regparm(0) does not appear to have any effect).
+ // We can allow register passing here, and move the writes of these values into the trampoline.
+ void*, void*, void*, void*, void*, void*,
+#endif
+ void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*);
+ void ctiVMThrowTrampoline();
+ };
+
+ void ctiSetReturnAddress(void** where, void* what);
+ void ctiPatchCallByReturnAddress(void* where, void* what);
+
+ class JIT : private MacroAssembler {
+ using MacroAssembler::Jump;
+ using MacroAssembler::JumpList;
+ using MacroAssembler::Label;
+
+#if PLATFORM(X86_64)
+ static const RegisterID timeoutCheckRegister = X86::r12;
+ static const RegisterID callFrameRegister = X86::r13;
+ static const RegisterID tagTypeNumberRegister = X86::r14;
+ static const RegisterID tagMaskRegister = X86::r15;
+#else
+ static const RegisterID timeoutCheckRegister = X86::esi;
+ static const RegisterID callFrameRegister = X86::edi;
+#endif
+
+ static const int patchGetByIdDefaultStructure = -1;
+ // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
+ // will compress the displacement, and we may not be able to fit a patched offset.
+ static const int patchGetByIdDefaultOffset = 256;
+
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+#if PLATFORM(X86_64)
+ static const int ctiArgumentInitSize = 6;
+#else
+ static const int ctiArgumentInitSize = 2;
+#endif
+#elif USE(JIT_STUB_ARGUMENT_STACK)
+ static const int ctiArgumentInitSize = 4;
+#else // JIT_STUB_ARGUMENT_VA_LIST
+ static const int ctiArgumentInitSize = 0;
+#endif
+
+#if PLATFORM(X86_64)
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 10;
+ static const int patchOffsetPutByIdPropertyMapOffset = 31;
+ // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+ static const int patchOffsetGetByIdStructure = 10;
+ static const int patchOffsetGetByIdBranchToSlowCase = 20;
+ static const int patchOffsetGetByIdPropertyMapOffset = 31;
+ static const int patchOffsetGetByIdPutResult = 31;
+#if ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 53 + ctiArgumentInitSize;
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 30 + ctiArgumentInitSize;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 9;
+#else
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 7;
+ static const int patchOffsetPutByIdPropertyMapOffset = 22;
+ // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+ static const int patchOffsetGetByIdStructure = 7;
+ static const int patchOffsetGetByIdBranchToSlowCase = 13;
+ static const int patchOffsetGetByIdPropertyMapOffset = 22;
+ static const int patchOffsetGetByIdPutResult = 22;
+#if ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 31 + ctiArgumentInitSize;
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 21 + ctiArgumentInitSize;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 6;
+#endif
+
+ public:
+ static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompile();
+ }
+
+ static void compileGetByIdSelf(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdSelf(stubInfo, structure, cachedOffset, returnAddress);
+ }
+
+ static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, cachedOffset, returnAddress, callFrame);
+ }
+
+#if USE(CTI_REPATCH_PIC)
+ static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset);
+ }
+ static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, cachedOffset, callFrame);
+ }
+ static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame);
+ }
+#endif
+
+ static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, cachedOffset, returnAddress, callFrame);
+ }
+
+ static void compilePutByIdReplace(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompilePutByIdReplace(stubInfo, structure, cachedOffset, returnAddress);
+ }
+
+ static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
+ }
+
+ static void compileCTIMachineTrampolines(JSGlobalData* globalData)
+ {
+ JIT jit(globalData);
+ jit.privateCompileCTIMachineTrampolines();
+ }
+
+ static void patchGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
+ static void patchPutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
+
+ static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress)
+ {
+ JIT jit(globalData, codeBlock);
+ return jit.privateCompilePatchGetArrayLength(returnAddress);
+ }
+
+ static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount);
+ static void unlinkCall(CallLinkInfo*);
+
+ inline static JSValuePtr execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValuePtr* exception)
+ {
+ return JSValuePtr::decode(ctiTrampoline(
+#if PLATFORM(X86_64)
+ 0, 0, 0, 0, 0, 0,
+#endif
+ code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
+ }
+
+ private:
+ JIT(JSGlobalData*, CodeBlock* = 0);
+
+ void privateCompileMainPass();
+ void privateCompileLinkPass();
+ void privateCompileSlowCases();
+ void privateCompile();
+ void privateCompileGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
+ void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
+#if USE(CTI_REPATCH_PIC)
+ void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
+ void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
+ void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame);
+#endif
+ void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
+ void privateCompilePutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
+ void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, void* returnAddress);
+
+ void privateCompileCTIMachineTrampolines();
+ void privateCompilePatchGetArrayLength(void* returnAddress);
+
+ void addSlowCase(Jump);
+ void addJump(Jump, int);
+ void emitJumpSlowToHot(Jump, int);
+
+ void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
+ void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
+ void compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned propertyAccessInstructionIndex);
+ void compilePutByIdSlowCase(int baseVReg, Identifier* ident, int valueVReg, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
+ void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex);
+ void compileOpCallInitializeCallFrame();
+ void compileOpCallSetupArgs(Instruction*);
+ void compileOpCallEvalSetupArgs(Instruction*);
+ void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
+ void compileOpConstructSetupArgs(Instruction*);
+ enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
+ void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
+ void putDoubleResultToJSNumberCellOrJSImmediate(X86Assembler::XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86Assembler::XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2);
+
+ void compileFastArith_op_add(Instruction*);
+ void compileFastArith_op_sub(Instruction*);
+ void compileFastArith_op_mul(Instruction*);
+ void compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2);
+ void compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2);
+ void compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2);
+ void compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2);
+ void compileFastArith_op_pre_inc(unsigned srcDst);
+ void compileFastArith_op_pre_dec(unsigned srcDst);
+ void compileFastArith_op_post_inc(unsigned result, unsigned srcDst);
+ void compileFastArith_op_post_dec(unsigned result, unsigned srcDst);
+ void compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_mod(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_rshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
+ void compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
+#if ENABLE(JIT_OPTIMIZE_ARITHMETIC)
+ void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
+ void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
+#endif
+
+ void emitGetVirtualRegister(int src, RegisterID dst);
+ void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
+ void emitPutVirtualRegister(unsigned dst, RegisterID from = X86::eax);
+
+ void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
+ void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
+ void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber);
+ void emitPutJITStubArgConstant(void* value, unsigned argumentNumber);
+ void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst);
+
+ void emitInitRegister(unsigned dst);
+
+ void emitPutCTIParam(void* value, unsigned name);
+ void emitPutCTIParam(RegisterID from, unsigned name);
+ void emitGetCTIParam(unsigned name, RegisterID to);
+
+ void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
+ void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
+ void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to);
+
+ JSValuePtr getConstantOperand(unsigned src);
+ int32_t getConstantOperandImmediateInt(unsigned src);
+ bool isOperandConstantImmediateInt(unsigned src);
+
+ Jump emitJumpIfJSCell(RegisterID);
+ Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID);
+ void emitJumpSlowCaseIfJSCell(RegisterID);
+ Jump emitJumpIfNotJSCell(RegisterID);
+ void emitJumpSlowCaseIfNotJSCell(RegisterID);
+ void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ JIT::Jump emitJumpIfImmediateNumber(RegisterID);
+ JIT::Jump emitJumpIfNotImmediateNumber(RegisterID);
+#endif
+
+ Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
+ {
+ return iter++->from;
+ }
+ void linkSlowCase(Vector<SlowCaseEntry>::iterator& iter)
+ {
+ iter->from.link(this);
+ ++iter;
+ }
+ void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
+
+ JIT::Jump emitJumpIfImmediateInteger(RegisterID);
+ JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
+ JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
+ void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
+ void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
+
+ Jump checkStructure(RegisterID reg, Structure* structure);
+
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ void emitFastArithDeTagImmediate(RegisterID);
+ Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
+#endif
+ void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
+ void emitFastArithImmToInt(RegisterID);
+ void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
+
+ void emitTagAsBoolImmediate(RegisterID reg);
+
+ void restoreArgumentReference();
+ void restoreArgumentReferenceForTrampoline();
+
+ Jump emitNakedCall(RegisterID);
+ Jump emitNakedCall(void* function);
+ Jump emitCTICall_internal(void*);
+ Jump emitCTICall(CTIHelper_j helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+ Jump emitCTICall(CTIHelper_2 helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
+
+ void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
+ void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
+
+ void emitSlowScriptCheck();
+#ifndef NDEBUG
+ void printBytecodeOperandTypes(unsigned src1, unsigned src2);
+#endif
+
+ void killLastResultRegister();
+
+#if ENABLE(CODEBLOCK_SAMPLING)
+ void sampleCodeBlock(CodeBlock* codeBlock)
+ {
+#if PLATFORM(X86_64)
+ move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86::ecx);
+ storePtr(ImmPtr(codeBlock), X86::ecx);
+#else
+ storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
+#endif
+ }
+#else
+ void sampleCodeBlock(CodeBlock*) {}
+#endif
+
+#if ENABLE(OPCODE_SAMPLING)
+ void sampleInstruction(Instruction* instruction, bool inHostFunction=false)
+ {
+#if PLATFORM(X86_64)
+ move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86::ecx);
+ storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86::ecx);
+#else
+ storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
+#endif
+ }
+#else
+ void sampleInstruction(Instruction*, bool) {}
+#endif
+
+ Interpreter* m_interpreter;
+ JSGlobalData* m_globalData;
+ CodeBlock* m_codeBlock;
+
+ Vector<CallRecord> m_calls;
+ Vector<Label> m_labels;
+ Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo;
+ Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
+ Vector<JumpTable> m_jmpTable;
+
+ struct JSRInfo {
+ DataLabelPtr storeLocation;
+ Label target;
+
+ JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
+ : storeLocation(storeLocation)
+ , target(targetLocation)
+ {
+ }
+ };
+
+ unsigned m_bytecodeIndex;
+ Vector<JSRInfo> m_jsrSites;
+ Vector<SlowCaseEntry> m_slowCases;
+ Vector<SwitchRecord> m_switches;
+
+ int m_lastResultBytecodeRegister;
+ unsigned m_jumpTargetsPosition;
+ };
+}
+
+#endif // ENABLE(JIT)
+
+#endif // JIT_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JIT.h"
+
+#if ENABLE(JIT)
+
+#include "CodeBlock.h"
+#include "JITInlineMethods.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+#define __ m_assembler.
+
+using namespace std;
+
+namespace JSC {
+
+void JIT::compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2)
+{
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
+ // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
+ emitFastArithImmToInt(X86::eax);
+ emitFastArithImmToInt(X86::ecx);
+#if !PLATFORM(X86)
+ // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+ // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
+ and32(Imm32(0x1f), X86::ecx);
+#endif
+ lshift32(X86::ecx, X86::eax);
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(joAdd32(X86::eax, X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+#endif
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ UNUSED_PARAM(op1);
+ UNUSED_PARAM(op2);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#else
+ // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
+ Jump notImm1 = getSlowCase(iter);
+ Jump notImm2 = getSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
+ notImm1.link(this);
+ notImm2.link(this);
+#endif
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::ecx, 2);
+ emitCTICall(Interpreter::cti_op_lshift);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2)
+{
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+#if USE(ALTERNATE_JSIMMEDIATE)
+ rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax);
+#else
+ rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax);
+#endif
+ } else {
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
+ emitFastArithImmToInt(X86::ecx);
+#if !PLATFORM(X86)
+ // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+ // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
+ and32(Imm32(0x1f), X86::ecx);
+#endif
+#if USE(ALTERNATE_JSIMMEDIATE)
+ rshift32(X86::ecx, X86::eax);
+#else
+ rshiftPtr(X86::ecx, X86::eax);
+#endif
+ }
+#if USE(ALTERNATE_JSIMMEDIATE)
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ orPtr(Imm32(JSImmediate::TagTypeNumber), X86::eax);
+#endif
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_rshift(unsigned result, unsigned, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ if (isOperandConstantImmediateInt(op2))
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ else {
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::ecx, 2);
+ }
+
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_rshift);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2)
+{
+ if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ int32_t imm = getConstantOperandImmediateInt(op1);
+ andPtr(Imm32(imm), X86::eax);
+ if (imm >= 0)
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax);
+#endif
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ int32_t imm = getConstantOperandImmediateInt(op2);
+ andPtr(Imm32(imm), X86::eax);
+ if (imm >= 0)
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax);
+#endif
+ } else {
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
+ andPtr(X86::edx, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ }
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ if (isOperandConstantImmediateInt(op1)) {
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArg(X86::eax, 2);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ } else {
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArg(X86::edx, 2);
+ }
+ emitCTICall(Interpreter::cti_op_bitand);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2)
+{
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(js0()))));
+ mod32(X86::ecx, X86::eax, X86::edx);
+#else
+ emitFastArithDeTagImmediate(X86::eax);
+ addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
+ mod32(X86::ecx, X86::eax, X86::edx);
+ signExtend32ToPtr(X86::edx, X86::edx);
+#endif
+ emitFastArithReTagImmediate(X86::edx, X86::eax);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_mod(unsigned result, unsigned, unsigned, Vector<SlowCaseEntry>::iterator& iter)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#else
+ Jump notImm1 = getSlowCase(iter);
+ Jump notImm2 = getSlowCase(iter);
+ linkSlowCase(iter);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ emitFastArithReTagImmediate(X86::ecx, X86::ecx);
+ notImm1.link(this);
+ notImm2.link(this);
+#endif
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::ecx, 2);
+ emitCTICall(Interpreter::cti_op_mod);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_post_inc(unsigned result, unsigned srcDst)
+{
+ emitGetVirtualRegister(srcDst, X86::eax);
+ move(X86::eax, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(joAdd32(Imm32(1), X86::edx));
+ emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
+#else
+ addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
+ signExtend32ToPtr(X86::edx, X86::edx);
+#endif
+ emitPutVirtualRegister(srcDst, X86::edx);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_post_inc);
+ emitPutVirtualRegister(srcDst, X86::edx);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst)
+{
+ emitGetVirtualRegister(srcDst, X86::eax);
+ move(X86::eax, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(joSub32(Imm32(1), X86::edx));
+ emitFastArithIntToImmNoCheck(X86::edx, X86::edx);
+#else
+ addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
+ signExtend32ToPtr(X86::edx, X86::edx);
+#endif
+ emitPutVirtualRegister(srcDst, X86::edx);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_post_dec);
+ emitPutVirtualRegister(srcDst, X86::edx);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_pre_inc(unsigned srcDst)
+{
+ emitGetVirtualRegister(srcDst, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(joAdd32(Imm32(1), X86::eax));
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+#endif
+ emitPutVirtualRegister(srcDst);
+}
+void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+{
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegister(srcDst, X86::eax);
+ notImm.link(this);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_pre_inc);
+ emitPutVirtualRegister(srcDst);
+}
+
+void JIT::compileFastArith_op_pre_dec(unsigned srcDst)
+{
+ emitGetVirtualRegister(srcDst, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+#if USE(ALTERNATE_JSIMMEDIATE)
+ addSlowCase(joSub32(Imm32(1), X86::eax));
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+#else
+ addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+#endif
+ emitPutVirtualRegister(srcDst);
+}
+void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+{
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegister(srcDst, X86::eax);
+ notImm.link(this);
+ emitPutJITStubArg(X86::eax, 1);
+ emitCTICall(Interpreter::cti_op_pre_dec);
+ emitPutVirtualRegister(srcDst);
+}
+
+
+#if !ENABLE(JIT_OPTIMIZE_ARITHMETIC)
+
+void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_mul);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_sub);
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+#elif USE(ALTERNATE_JSIMMEDIATE) // *AND* ENABLE(JIT_OPTIMIZE_ARITHMETIC)
+
+void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
+{
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ if (opcodeID == op_add)
+ addSlowCase(joAdd32(X86::edx, X86::eax));
+ else if (opcodeID == op_sub)
+ addSlowCase(joSub32(X86::edx, X86::eax));
+ else {
+ ASSERT(opcodeID == op_mul);
+ addSlowCase(joMul32(X86::edx, X86::eax));
+ addSlowCase(jz32(X86::eax));
+ }
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+}
+
+void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned, unsigned op1, unsigned, OperandTypes types)
+{
+ // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
+ COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
+
+ Jump notImm1 = getSlowCase(iter);
+ Jump notImm2 = getSlowCase(iter);
+
+ linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
+ if (opcodeID == op_mul) // op_mul has an extra slow case to handle 0 * negative number.
+ linkSlowCase(iter);
+ emitGetVirtualRegister(op1, X86::eax);
+
+ Label stubFunctionCall(this);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 2);
+ if (opcodeID == op_add)
+ emitCTICall(Interpreter::cti_op_add);
+ else if (opcodeID == op_sub)
+ emitCTICall(Interpreter::cti_op_sub);
+ else {
+ ASSERT(opcodeID == op_mul);
+ emitCTICall(Interpreter::cti_op_mul);
+ }
+ Jump end = jump();
+
+ // if we get here, eax is not an int32, edx not yet checked.
+ notImm1.link(this);
+ if (!types.first().definitelyIsNumber())
+ emitJumpIfNotImmediateNumber(X86::eax).linkTo(stubFunctionCall, this);
+ if (!types.second().definitelyIsNumber())
+ emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this);
+ addPtr(tagTypeNumberRegister, X86::eax);
+ m_assembler.movq_rr(X86::eax, X86::xmm1);
+ Jump op2isDouble = emitJumpIfNotImmediateInteger(X86::edx);
+ m_assembler.cvtsi2sd_rr(X86::edx, X86::xmm2);
+ Jump op2wasInteger = jump();
+
+ // if we get here, eax IS an int32, edx is not.
+ notImm2.link(this);
+ if (!types.second().definitelyIsNumber())
+ emitJumpIfNotImmediateNumber(X86::edx).linkTo(stubFunctionCall, this);
+ m_assembler.cvtsi2sd_rr(X86::eax, X86::xmm1);
+ op2isDouble.link(this);
+ addPtr(tagTypeNumberRegister, X86::edx);
+ m_assembler.movq_rr(X86::edx, X86::xmm2);
+ op2wasInteger.link(this);
+
+ if (opcodeID == op_add)
+ m_assembler.addsd_rr(X86::xmm2, X86::xmm1);
+ else if (opcodeID == op_sub)
+ m_assembler.subsd_rr(X86::xmm2, X86::xmm1);
+ else {
+ ASSERT(opcodeID == op_mul);
+ m_assembler.mulsd_rr(X86::xmm2, X86::xmm1);
+ }
+ m_assembler.movq_rr(X86::xmm1, X86::eax);
+ subPtr(tagTypeNumberRegister, X86::eax);
+
+ end.link(this);
+}
+
+void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ emitPutVirtualRegister(result);
+ return;
+ }
+
+ if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax));
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax));
+ emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ } else
+ compileBinaryArithOp(op_add, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ if (isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ } else
+ compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ // For now, only plant a fast int case if the constant operand is greater than zero.
+ int32_t value;
+ if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
+ emitGetVirtualRegister(op2, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ } else
+ compileBinaryArithOp(op_mul, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
+ || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_mul);
+ } else
+ compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+
+void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ compileBinaryArithOp(op_sub, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types);
+
+ emitPutVirtualRegister(result);
+}
+
+#else
+
+typedef X86Assembler::JmpSrc JmpSrc;
+typedef X86Assembler::JmpDst JmpDst;
+typedef X86Assembler::XMMRegisterID XMMRegisterID;
+
+#if PLATFORM(MAC)
+
+static inline bool isSSE2Present()
+{
+ return true; // All X86 Macs are guaranteed to support at least SSE2
+}
+
+#else
+
+static bool isSSE2Present()
+{
+ static const int SSE2FeatureBit = 1 << 26;
+ struct SSE2Check {
+ SSE2Check()
+ {
+ int flags;
+#if COMPILER(MSVC)
+ _asm {
+ mov eax, 1 // cpuid function 1 gives us the standard feature set
+ cpuid;
+ mov flags, edx;
+ }
+#else
+ flags = 0;
+ // FIXME: Add GCC code to do above asm
+#endif
+ present = (flags & SSE2FeatureBit) != 0;
+ }
+ bool present;
+ };
+ static SSE2Check check;
+ return check.present;
+}
+
+#endif
+
+/*
+ This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell.
+
+ In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell'
+ is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell).
+
+ However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow
+ control will fall through from the code planted.
+*/
+void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2)
+{
+ // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate.
+ __ cvttsd2si_rr(xmmSource, tempReg1);
+ __ addl_rr(tempReg1, tempReg1);
+ __ sarl_i8r(1, tempReg1);
+ __ cvtsi2sd_rr(tempReg1, tempXmm);
+ // Compare & branch if immediate.
+ __ ucomisd_rr(tempXmm, xmmSource);
+ JmpSrc resultIsImm = __ je();
+ JmpDst resultLookedLikeImmButActuallyIsnt = __ label();
+
+ // Store the result to the JSNumberCell and jump.
+ __ movsd_rm(xmmSource, FIELD_OFFSET(JSNumberCell, m_value), jsNumberCell);
+ if (jsNumberCell != X86::eax)
+ __ movl_rr(jsNumberCell, X86::eax);
+ emitPutVirtualRegister(dst);
+ *wroteJSNumberCell = __ jmp();
+
+ __ link(resultIsImm, __ label());
+ // value == (double)(JSImmediate)value... or at least, it looks that way...
+ // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered).
+ __ link(__ jp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN
+ __ pextrw_irr(3, xmmSource, tempReg2);
+ __ cmpl_ir(0x8000, tempReg2);
+ __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
+ // Yes it really really really is representable as a JSImmediate.
+ emitFastArithIntToImmNoCheck(tempReg1, X86::eax);
+ emitPutVirtualRegister(dst);
+}
+
+void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
+{
+ Structure* numberStructure = m_globalData->numberStructure.get();
+ JmpSrc wasJSNumberCell1;
+ JmpSrc wasJSNumberCell1b;
+ JmpSrc wasJSNumberCell2;
+ JmpSrc wasJSNumberCell2b;
+
+ emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
+
+ if (types.second().isReusable() && isSSE2Present()) {
+ ASSERT(types.second().mightBeNumber());
+
+ // Check op2 is a number
+ __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);
+ JmpSrc op2imm = __ jne();
+ if (!types.second().definitelyIsNumber()) {
+ emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
+ __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
+ addSlowCase(__ jne());
+ }
+
+ // (1) In this case src2 is a reusable number cell.
+ // Slow case if src1 is not a number type.
+ __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);
+ JmpSrc op1imm = __ jne();
+ if (!types.first().definitelyIsNumber()) {
+ emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
+ __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
+ addSlowCase(__ jne());
+ }
+
+ // (1a) if we get here, src1 is also a number cell
+ __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
+ JmpSrc loadedDouble = __ jmp();
+ // (1b) if we get here, src1 is an immediate
+ __ link(op1imm, __ label());
+ emitFastArithImmToInt(X86::eax);
+ __ cvtsi2sd_rr(X86::eax, X86::xmm0);
+ // (1c)
+ __ link(loadedDouble, __ label());
+ if (opcodeID == op_add)
+ __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ else if (opcodeID == op_sub)
+ __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ else {
+ ASSERT(opcodeID == op_mul);
+ __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ }
+
+ putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax);
+ wasJSNumberCell2b = __ jmp();
+
+ // (2) This handles cases where src2 is an immediate number.
+ // Two slow cases - either src1 isn't an immediate, or the subtract overflows.
+ __ link(op2imm, __ label());
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ } else if (types.first().isReusable() && isSSE2Present()) {
+ ASSERT(types.first().mightBeNumber());
+
+ // Check op1 is a number
+ __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);
+ JmpSrc op1imm = __ jne();
+ if (!types.first().definitelyIsNumber()) {
+ emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
+ __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
+ addSlowCase(__ jne());
+ }
+
+ // (1) In this case src1 is a reusable number cell.
+ // Slow case if src2 is not a number type.
+ __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);
+ JmpSrc op2imm = __ jne();
+ if (!types.second().definitelyIsNumber()) {
+ emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
+ __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
+ addSlowCase(__ jne());
+ }
+
+ // (1a) if we get here, src2 is also a number cell
+ __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1);
+ JmpSrc loadedDouble = __ jmp();
+ // (1b) if we get here, src2 is an immediate
+ __ link(op2imm, __ label());
+ emitFastArithImmToInt(X86::edx);
+ __ cvtsi2sd_rr(X86::edx, X86::xmm1);
+ // (1c)
+ __ link(loadedDouble, __ label());
+ __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
+ if (opcodeID == op_add)
+ __ addsd_rr(X86::xmm1, X86::xmm0);
+ else if (opcodeID == op_sub)
+ __ subsd_rr(X86::xmm1, X86::xmm0);
+ else {
+ ASSERT(opcodeID == op_mul);
+ __ mulsd_rr(X86::xmm1, X86::xmm0);
+ }
+ __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);
+ emitPutVirtualRegister(dst);
+
+ putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx);
+ wasJSNumberCell1b = __ jmp();
+
+ // (2) This handles cases where src1 is an immediate number.
+ // Two slow cases - either src2 isn't an immediate, or the subtract overflows.
+ __ link(op1imm, __ label());
+ emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ } else
+ emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+
+ if (opcodeID == op_add) {
+ emitFastArithDeTagImmediate(X86::eax);
+ __ addl_rr(X86::edx, X86::eax);
+ addSlowCase(__ jo());
+ } else if (opcodeID == op_sub) {
+ __ subl_rr(X86::edx, X86::eax);
+ addSlowCase(__ jo());
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ } else {
+ ASSERT(opcodeID == op_mul);
+ // convert eax & edx from JSImmediates to ints, and check if either are zero
+ emitFastArithImmToInt(X86::edx);
+ JmpSrc op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax);
+ __ testl_rr(X86::edx, X86::edx);
+ JmpSrc op2NonZero = __ jne();
+ __ link(op1Zero, __ label());
+ // if either input is zero, add the two together, and check if the result is < 0.
+ // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
+ __ movl_rr(X86::eax, X86::ecx);
+ __ addl_rr(X86::edx, X86::ecx);
+ addSlowCase(__ js());
+ // Skip the above check if neither input is zero
+ __ link(op2NonZero, __ label());
+ __ imull_rr(X86::edx, X86::eax);
+ addSlowCase(__ jo());
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ }
+ emitPutVirtualRegister(dst);
+
+ if (types.second().isReusable() && isSSE2Present()) {
+ __ link(wasJSNumberCell2, __ label());
+ __ link(wasJSNumberCell2b, __ label());
+ }
+ else if (types.first().isReusable() && isSSE2Present()) {
+ __ link(wasJSNumberCell1, __ label());
+ __ link(wasJSNumberCell1b, __ label());
+ }
+}
+
+void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
+{
+ linkSlowCase(iter);
+ if (types.second().isReusable() && isSSE2Present()) {
+ if (!types.first().definitelyIsNumber()) {
+ linkSlowCaseIfNotJSCell(iter, src1);
+ linkSlowCase(iter);
+ }
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCaseIfNotJSCell(iter, src2);
+ linkSlowCase(iter);
+ }
+ } else if (types.first().isReusable() && isSSE2Present()) {
+ if (!types.first().definitelyIsNumber()) {
+ linkSlowCaseIfNotJSCell(iter, src1);
+ linkSlowCase(iter);
+ }
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCaseIfNotJSCell(iter, src2);
+ linkSlowCase(iter);
+ }
+ }
+ linkSlowCase(iter);
+
+ // additional entry point to handle -0 cases.
+ if (opcodeID == op_mul)
+ linkSlowCase(iter);
+
+ emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
+ if (opcodeID == op_add)
+ emitCTICall(Interpreter::cti_op_add);
+ else if (opcodeID == op_sub)
+ emitCTICall(Interpreter::cti_op_sub);
+ else {
+ ASSERT(opcodeID == op_mul);
+ emitCTICall(Interpreter::cti_op_mul);
+ }
+ emitPutVirtualRegister(dst);
+}
+
+void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitPutVirtualRegister(result);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitPutVirtualRegister(result);
+ } else {
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+ if (types.first().mightBeNumber() && types.second().mightBeNumber())
+ compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
+ else {
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ emitPutVirtualRegister(result);
+ }
+ }
+}
+void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op1)) {
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax);
+ notImm.link(this);
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArg(X86::eax, 2);
+ emitCTICall(Interpreter::cti_op_add);
+ emitPutVirtualRegister(result);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax);
+ notImm.link(this);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_add);
+ emitPutVirtualRegister(result);
+ } else {
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+ ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
+ compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
+ }
+}
+
+void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ // For now, only plant a fast int case if the constant operand is greater than zero.
+ int32_t value;
+ if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
+ emitGetVirtualRegister(op2, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitFastArithDeTagImmediate(X86::eax);
+ addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ emitPutVirtualRegister(result);
+ } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
+ emitGetVirtualRegister(op1, X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitFastArithDeTagImmediate(X86::eax);
+ addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
+ signExtend32ToPtr(X86::eax, X86::eax);
+ emitFastArithReTagImmediate(X86::eax, X86::eax);
+ emitPutVirtualRegister(result);
+ } else
+ compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
+}
+void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
+ || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
+ emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
+ emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ emitCTICall(Interpreter::cti_op_mul);
+ emitPutVirtualRegister(result);
+ } else
+ compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
+}
+
+void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+{
+ compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
+}
+void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
+}
+
+#endif
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JIT.h"
+
+#if ENABLE(JIT)
+
+#include "CodeBlock.h"
+#include "JITInlineMethods.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace std;
+
+namespace JSC {
+
+void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
+{
+ // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
+ // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
+ // match). Reset the check so it no longer matches.
+ DataLabelPtr::patch(callLinkInfo->hotPathBegin, JSValuePtr::encode(jsImpossibleValue()));
+}
+
+void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount)
+{
+ // Currently we only link calls with the exact number of arguments.
+ if (callerArgCount == calleeCodeBlock->m_numParameters) {
+ ASSERT(!callLinkInfo->isLinked());
+
+ calleeCodeBlock->addCaller(callLinkInfo);
+
+ DataLabelPtr::patch(callLinkInfo->hotPathBegin, callee);
+ Jump::patch(callLinkInfo->hotPathOther, ctiCode);
+ }
+
+ // patch the instruction that jumps out to the cold path, so that we only try to link once.
+ void* patchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + patchOffsetOpCallCompareToJump);
+ Jump::patch(patchCheck, callLinkInfo->coldPathOther);
+}
+
+void JIT::compileOpCallInitializeCallFrame()
+{
+ store32(X86::edx, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
+
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain
+
+ storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register))));
+ storePtr(X86::ecx, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
+ storePtr(X86::edx, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register))));
+}
+
+void JIT::compileOpCallSetupArgs(Instruction* instruction)
+{
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ // ecx holds func
+ emitPutJITStubArg(X86::ecx, 1);
+ emitPutJITStubArgConstant(registerOffset, 2);
+ emitPutJITStubArgConstant(argCount, 3);
+}
+
+void JIT::compileOpCallEvalSetupArgs(Instruction* instruction)
+{
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ // ecx holds func
+ emitPutJITStubArg(X86::ecx, 1);
+ emitPutJITStubArgConstant(registerOffset, 2);
+ emitPutJITStubArgConstant(argCount, 3);
+}
+
+void JIT::compileOpConstructSetupArgs(Instruction* instruction)
+{
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+ int proto = instruction[5].u.operand;
+ int thisRegister = instruction[6].u.operand;
+
+ // ecx holds func
+ emitPutJITStubArg(X86::ecx, 1);
+ emitPutJITStubArgConstant(registerOffset, 2);
+ emitPutJITStubArgConstant(argCount, 3);
+ emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax);
+ emitPutJITStubArgConstant(thisRegister, 5);
+}
+
+#if !ENABLE(JIT_OPTIMIZE_CALL)
+
+void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ // Handle eval
+ Jump wasEval;
+ if (opcodeID == op_call_eval) {
+ emitGetVirtualRegister(callee, X86::ecx);
+ compileOpCallEvalSetupArgs(instruction);
+
+ emitCTICall(Interpreter::cti_op_call_eval);
+ wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue())));
+ }
+
+ emitGetVirtualRegister(callee, X86::ecx);
+ // The arguments have been set up on the hot path for op_call_eval
+ if (opcodeID == op_call)
+ compileOpCallSetupArgs(instruction);
+ else if (opcodeID == op_construct)
+ compileOpConstructSetupArgs(instruction);
+
+ // Check for JSFunctions.
+ emitJumpSlowCaseIfNotJSCell(X86::ecx);
+ addSlowCase(jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)));
+
+ // First, in the case of a construct, allocate the new object.
+ if (opcodeID == op_construct) {
+ emitCTICall(Interpreter::cti_op_construct_JSConstruct);
+ emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitGetVirtualRegister(callee, X86::ecx);
+ }
+
+ // Speculatively roll the callframe, assuming argCount will match the arity.
+ storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
+ addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
+ move(Imm32(argCount), X86::edx);
+
+ emitNakedCall(m_interpreter->m_ctiVirtualCall);
+
+ if (opcodeID == op_call_eval)
+ wasEval.link(this);
+
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ emitPutVirtualRegister(dst);
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
+{
+ int dst = instruction[1].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+
+ // This handles host functions
+ emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction));
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ emitPutVirtualRegister(dst);
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+#else
+
+static NO_RETURN void unreachable()
+{
+ ASSERT_NOT_REACHED();
+ exit(1);
+}
+
+void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ // Handle eval
+ Jump wasEval;
+ if (opcodeID == op_call_eval) {
+ emitGetVirtualRegister(callee, X86::ecx);
+ compileOpCallEvalSetupArgs(instruction);
+
+ emitCTICall(Interpreter::cti_op_call_eval);
+ wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue())));
+ }
+
+ // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
+ // This deliberately leaves the callee in ecx, used when setting up the stack frame below
+ emitGetVirtualRegister(callee, X86::ecx);
+ DataLabelPtr addressOfLinkedFunctionCheck;
+ Jump jumpToSlow = jnePtrWithPatch(X86::ecx, addressOfLinkedFunctionCheck, ImmPtr(JSValuePtr::encode(jsImpossibleValue())));
+ addSlowCase(jumpToSlow);
+ ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
+
+ // The following is the fast case, only used whan a callee can be linked.
+
+ // In the case of OpConstruct, call out to a cti_ function to create the new object.
+ if (opcodeID == op_construct) {
+ int proto = instruction[5].u.operand;
+ int thisRegister = instruction[6].u.operand;
+
+ emitPutJITStubArg(X86::ecx, 1);
+ emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax);
+ emitCTICall(Interpreter::cti_op_construct_JSConstruct);
+ emitPutVirtualRegister(thisRegister);
+ emitGetVirtualRegister(callee, X86::ecx);
+ }
+
+ // Fast version of stack frame initialization, directly relative to edi.
+ // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
+ storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register))));
+ storePtr(X86::ecx, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain
+ store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register))));
+ storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
+ storePtr(X86::edx, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
+ addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister);
+
+ // Call to the callee
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(reinterpret_cast<void*>(unreachable));
+
+ if (opcodeID == op_call_eval)
+ wasEval.link(this);
+
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ emitPutVirtualRegister(dst);
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ linkSlowCase(iter);
+
+ // The arguments have been set up on the hot path for op_call_eval
+ if (opcodeID == op_call)
+ compileOpCallSetupArgs(instruction);
+ else if (opcodeID == op_construct)
+ compileOpConstructSetupArgs(instruction);
+
+ // Fast check for JS function.
+ Jump callLinkFailNotObject = emitJumpIfNotJSCell(X86::ecx);
+ Jump callLinkFailNotJSFunction = jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr));
+
+ // First, in the case of a construct, allocate the new object.
+ if (opcodeID == op_construct) {
+ emitCTICall(Interpreter::cti_op_construct_JSConstruct);
+ emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitGetVirtualRegister(callee, X86::ecx);
+ }
+
+ move(Imm32(argCount), X86::edx);
+
+ // Speculatively roll the callframe, assuming argCount will match the arity.
+ storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
+ addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
+
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation =
+ emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink);
+
+ Jump storeResultForFirstRun = jump();
+
+// FIXME: this label can be removed, since it is a fixed offset from 'callReturnLocation'.
+ // This is the address for the cold path *after* the first run (which tries to link the call).
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = MacroAssembler::Label(this);
+
+ // The arguments have been set up on the hot path for op_call_eval
+ if (opcodeID == op_call)
+ compileOpCallSetupArgs(instruction);
+ else if (opcodeID == op_construct)
+ compileOpConstructSetupArgs(instruction);
+
+ // Check for JSFunctions.
+ Jump isNotObject = emitJumpIfNotJSCell(X86::ecx);
+ Jump isJSFunction = jePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr));
+
+ // This handles host functions
+ isNotObject.link(this);
+ callLinkFailNotObject.link(this);
+ callLinkFailNotJSFunction.link(this);
+ emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction));
+ Jump wasNotJSFunction = jump();
+
+ // Next, handle JSFunctions...
+ isJSFunction.link(this);
+
+ // First, in the case of a construct, allocate the new object.
+ if (opcodeID == op_construct) {
+ emitCTICall(Interpreter::cti_op_construct_JSConstruct);
+ emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitGetVirtualRegister(callee, X86::ecx);
+ }
+
+ // Speculatively roll the callframe, assuming argCount will match the arity.
+ storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
+ addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
+ move(Imm32(argCount), X86::edx);
+
+ emitNakedCall(m_interpreter->m_ctiVirtualCall);
+
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ wasNotJSFunction.link(this);
+ storeResultForFirstRun.link(this);
+ emitPutVirtualRegister(dst);
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+#endif
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JITInlineMethods_h
+#define JITInlineMethods_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#if PLATFORM(WIN)
+#undef FIELD_OFFSET // Fix conflict with winnt.h.
+#endif
+
+// FIELD_OFFSET: Like the C++ offsetof macro, but you can use it with classes.
+// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
+// NULL can cause compiler problems, especially in cases of multiple inheritance.
+#define FIELD_OFFSET(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
+
+namespace JSC {
+
+ALWAYS_INLINE void JIT::killLastResultRegister()
+{
+ m_lastResultBytecodeRegister = std::numeric_limits<int>::max();
+}
+
+// get arg puts an arg from the SF register array into a h/w register
+ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ JSValuePtr value = m_codeBlock->getConstant(src);
+ move(ImmPtr(JSValuePtr::encode(value)), dst);
+ killLastResultRegister();
+ return;
+ }
+
+ if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src)) {
+ bool atJumpTarget = false;
+ while (m_jumpTargetsPosition < m_codeBlock->numberOfJumpTargets() && m_codeBlock->jumpTarget(m_jumpTargetsPosition) <= m_bytecodeIndex) {
+ if (m_codeBlock->jumpTarget(m_jumpTargetsPosition) == m_bytecodeIndex)
+ atJumpTarget = true;
+ ++m_jumpTargetsPosition;
+ }
+
+ if (!atJumpTarget) {
+ // The argument we want is already stored in eax
+ if (dst != X86::eax)
+ move(X86::eax, dst);
+ killLastResultRegister();
+ return;
+ }
+ }
+
+ loadPtr(Address(callFrameRegister, src * sizeof(Register)), dst);
+ killLastResultRegister();
+}
+
+ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2)
+{
+ if (src2 == m_lastResultBytecodeRegister) {
+ emitGetVirtualRegister(src2, dst2);
+ emitGetVirtualRegister(src1, dst1);
+ } else {
+ emitGetVirtualRegister(src1, dst1);
+ emitGetVirtualRegister(src2, dst2);
+ }
+}
+
+// puts an arg onto the stack, as an arg to a context threaded function.
+ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
+{
+ poke(src, argumentNumber);
+}
+
+ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
+{
+ poke(Imm32(value), argumentNumber);
+}
+
+ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
+{
+ poke(ImmPtr(value), argumentNumber);
+}
+
+ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
+{
+ peek(dst, argumentNumber);
+}
+
+ALWAYS_INLINE JSValuePtr JIT::getConstantOperand(unsigned src)
+{
+ ASSERT(m_codeBlock->isConstantRegisterIndex(src));
+ return m_codeBlock->getConstant(src);
+}
+
+ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src)
+{
+ return getConstantOperand(src).getInt32Fast();
+}
+
+ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
+{
+ return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32Fast();
+}
+
+// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
+ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
+{
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ JSValuePtr value = m_codeBlock->getConstant(src);
+ emitPutJITStubArgConstant(JSValuePtr::encode(value), argumentNumber);
+ } else {
+ loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
+ emitPutJITStubArg(scratch, argumentNumber);
+ }
+
+ killLastResultRegister();
+}
+
+ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name)
+{
+ poke(ImmPtr(value), name);
+}
+
+ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name)
+{
+ poke(from, name);
+}
+
+ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to)
+{
+ peek(to, name);
+ killLastResultRegister();
+}
+
+ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
+{
+ storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));
+}
+
+ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
+{
+ storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
+}
+
+ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to)
+{
+ loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to);
+ killLastResultRegister();
+}
+
+ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
+{
+ storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));
+ m_lastResultBytecodeRegister = (from == X86::eax) ? dst : std::numeric_limits<int>::max();
+ // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
+}
+
+ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
+{
+ storePtr(ImmPtr(JSValuePtr::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
+ // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(X86::RegisterID r)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ Jump nakedCall = call(r);
+ m_calls.append(CallRecord(nakedCall, m_bytecodeIndex));
+ return nakedCall;
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(void* function)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ Jump nakedCall = call();
+ m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function));
+ return nakedCall;
+}
+
+#if USE(JIT_STUB_ARGUMENT_REGISTER)
+ALWAYS_INLINE void JIT::restoreArgumentReference()
+{
+#if PLATFORM(X86_64)
+ move(X86::esp, X86::edi);
+#else
+ move(X86::esp, X86::ecx);
+#endif
+ emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+}
+ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
+{
+ // In the trampoline on x86-64, the first argument register is not overwritten.
+#if !PLATFORM(X86_64)
+ move(X86::esp, X86::ecx);
+ addPtr(Imm32(sizeof(void*)), X86::ecx);
+#endif
+}
+#elif USE(JIT_STUB_ARGUMENT_STACK)
+ALWAYS_INLINE void JIT::restoreArgumentReference()
+{
+ storePtr(X86::esp, X86::esp);
+ emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+}
+ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
+#else // JIT_STUB_ARGUMENT_VA_LIST
+ALWAYS_INLINE void JIT::restoreArgumentReference()
+{
+ emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+}
+ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
+#endif
+
+ALWAYS_INLINE JIT::Jump JIT::emitCTICall_internal(void* helper)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+#if ENABLE(OPCODE_SAMPLING)
+ sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, true);
+#endif
+ restoreArgumentReference();
+ Jump ctiCall = call();
+ m_calls.append(CallRecord(ctiCall, m_bytecodeIndex, helper));
+#if ENABLE(OPCODE_SAMPLING)
+ sampleInstruction(m_codeBlock->instructions().begin() + m_bytecodeIndex, false);
+#endif
+ killLastResultRegister();
+
+ return ctiCall;
+}
+
+ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
+{
+ return jnePtr(Address(reg, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(structure));
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return jzPtr(reg, tagMaskRegister);
+#else
+ return jz32(reg, Imm32(JSImmediate::TagMask));
+#endif
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch)
+{
+ move(reg1, scratch);
+ orPtr(reg2, scratch);
+ return emitJumpIfJSCell(scratch);
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg)
+{
+ addSlowCase(emitJumpIfJSCell(reg));
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return jnzPtr(reg, tagMaskRegister);
+#else
+ return jnz32(reg, Imm32(JSImmediate::TagMask));
+#endif
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg)
+{
+ addSlowCase(emitJumpIfNotJSCell(reg));
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg)
+{
+ if (!m_codeBlock->isKnownNotImmediate(vReg))
+ emitJumpSlowCaseIfNotJSCell(reg);
+}
+
+ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
+{
+ if (!m_codeBlock->isKnownNotImmediate(vReg))
+ linkSlowCase(iter);
+}
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg)
+{
+ return jnzPtr(reg, tagTypeNumberRegister);
+}
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg)
+{
+ return jzPtr(reg, tagTypeNumberRegister);
+}
+#endif
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return jaePtr(reg, tagTypeNumberRegister);
+#else
+ return jnz32(reg, Imm32(JSImmediate::TagTypeNumber));
+#endif
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return jbPtr(reg, tagTypeNumberRegister);
+#else
+ return jz32(reg, Imm32(JSImmediate::TagTypeNumber));
+#endif
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
+{
+ move(reg1, scratch);
+ andPtr(reg2, scratch);
+ return emitJumpIfNotImmediateInteger(scratch);
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg)
+{
+ addSlowCase(emitJumpIfNotImmediateInteger(reg));
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch)
+{
+ addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
+}
+
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
+{
+ subPtr(Imm32(JSImmediate::TagTypeNumber), reg);
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
+{
+ return jzSubPtr(Imm32(JSImmediate::TagTypeNumber), reg);
+}
+#endif
+
+ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ emitFastArithIntToImmNoCheck(src, dest);
+#else
+ if (src != dest)
+ move(src, dest);
+ addPtr(Imm32(JSImmediate::TagTypeNumber), dest);
+#endif
+}
+
+ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ UNUSED_PARAM(reg);
+#else
+ rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
+#endif
+}
+
+// operand is int32_t, must have been zero-extended if register is 64-bit.
+ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest)
+{
+#if USE(ALTERNATE_JSIMMEDIATE)
+ if (src != dest)
+ move(src, dest);
+ orPtr(tagTypeNumberRegister, dest);
+#else
+ signExtend32ToPtr(src, dest);
+ addPtr(dest, dest);
+ emitFastArithReTagImmediate(dest, dest);
+#endif
+}
+
+ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
+{
+ lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg);
+ or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg);
+}
+
+ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));
+}
+
+ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));
+}
+
+ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);
+}
+
+}
+
+#endif // ENABLE(JIT)
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JIT.h"
+
+#if ENABLE(JIT)
+
+#include "CodeBlock.h"
+#include "JITInlineMethods.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace std;
+
+namespace JSC {
+
+#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned)
+{
+ // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.
+ // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
+ // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
+ // to jump back to if one of these trampolies finds a match.
+
+ emitGetVirtualRegister(baseVReg, X86::eax);
+
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgConstant(ident, 2);
+ emitCTICall(Interpreter::cti_op_get_by_id_generic);
+ emitPutVirtualRegister(resultVReg);
+}
+
+
+void JIT::compileGetByIdSlowCase(int, int, Identifier*, Vector<SlowCaseEntry>::iterator&, unsigned)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned)
+{
+ // In order to be able to patch both the Structure, and the object offset, we store one pointer,
+ // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
+ // such that the Structure & offset are always at the same distance from this.
+
+ emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx);
+
+ emitPutJITStubArgConstant(ident, 2);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 3);
+ emitCTICall(Interpreter::cti_op_put_by_id_generic);
+}
+
+void JIT::compilePutByIdSlowCase(int, Identifier*, int, Vector<SlowCaseEntry>::iterator&, unsigned)
+{
+ ASSERT_NOT_REACHED();
+}
+
+#else
+
+void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex)
+{
+ // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.
+ // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
+ // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
+ // to jump back to if one of these trampolies finds a match.
+
+ emitGetVirtualRegister(baseVReg, X86::eax);
+
+ emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg);
+
+ Label hotPathBegin(this);
+ m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
+
+ DataLabelPtr structureToCompare;
+ Jump structureCheck = jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+ addSlowCase(structureCheck);
+ ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
+ ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
+
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(X86::eax, patchGetByIdDefaultOffset), X86::eax);
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);
+
+ Label putResult(this);
+ ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+ emitPutVirtualRegister(resultVReg);
+}
+
+
+void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
+{
+ // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset
+ // so that we only need track one pointer into the slow case code - we track a pointer to the location
+ // of the call (which we can use to look up the patch information), but should a array-length or
+ // prototype access trampoline fail we want to bail out back to here. To do so we can subtract back
+ // the distance from the call to the head of the slow case.
+
+ linkSlowCaseIfNotJSCell(iter, baseVReg);
+ linkSlowCase(iter);
+
+#ifndef NDEBUG
+ Label coldPathBegin(this);
+#endif
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArgConstant(ident, 2);
+ Jump call = emitCTICall(Interpreter::cti_op_get_by_id);
+ emitPutVirtualRegister(resultVReg);
+
+ ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
+
+ // Track the location of the call; this will be used to recover patch information.
+ m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
+}
+
+void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsigned propertyAccessInstructionIndex)
+{
+ // In order to be able to patch both the Structure, and the object offset, we store one pointer,
+ // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
+ // such that the Structure & offset are always at the same distance from this.
+
+ emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx);
+
+ // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
+ emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg);
+
+ Label hotPathBegin(this);
+ m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
+
+ // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
+ DataLabelPtr structureToCompare;
+ addSlowCase(jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
+ ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);
+
+ // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(X86::edx, Address(X86::eax, patchGetByIdDefaultOffset));
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
+}
+
+void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
+{
+ linkSlowCaseIfNotJSCell(iter, baseVReg);
+ linkSlowCase(iter);
+
+ emitPutJITStubArgConstant(ident, 2);
+ emitPutJITStubArg(X86::eax, 1);
+ emitPutJITStubArg(X86::edx, 3);
+ Jump call = emitCTICall(Interpreter::cti_op_put_by_id);
+
+ // Track the location of the call; this will be used to recover patch information.
+ m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
+}
+
+static JSObject* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize)
+{
+ baseObject->allocatePropertyStorage(oldSize, newSize);
+ return baseObject;
+}
+
+static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure)
+{
+ return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
+}
+
+void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
+{
+ JumpList failureCases;
+ // Check eax is an object of the right Structure.
+ failureCases.append(emitJumpIfNotJSCell(X86::eax));
+ failureCases.append(jnePtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(oldStructure)));
+ JumpList successCases;
+
+ // ecx = baseObject
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ // proto(ecx) = baseObject->structure()->prototype()
+ failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
+
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
+
+ // ecx = baseObject->m_structure
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
+ // null check the prototype
+ successCases.append(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(jsNull()))));
+
+ // Check the structure id
+ failureCases.append(jnePtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(it->get())));
+
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
+ loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
+ }
+
+ successCases.link(this);
+
+ Jump callTarget;
+
+ // emit a call only if storage realloc is needed
+ if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) {
+ pop(X86::ebx);
+#if PLATFORM(X86_64)
+ move(Imm32(newStructure->propertyStorageCapacity()), X86::edx);
+ move(Imm32(oldStructure->propertyStorageCapacity()), X86::esi);
+ move(X86::eax, X86::edi);
+ callTarget = call();
+#else
+ push(Imm32(newStructure->propertyStorageCapacity()));
+ push(Imm32(oldStructure->propertyStorageCapacity()));
+ push(X86::eax);
+ callTarget = call();
+ addPtr(Imm32(3 * sizeof(void*)), X86::esp);
+#endif
+ emitGetJITStubArg(3, X86::edx);
+ push(X86::ebx);
+ }
+
+ // Assumes m_refCount can be decremented easily, refcount decrement is safe as
+ // codeblock should ensure oldStructure->m_refCount > 0
+ sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount()));
+ add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
+ storePtr(ImmPtr(newStructure), Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)));
+
+ // write the value
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr)));
+
+ ret();
+
+ Jump failureJump;
+ bool plantedFailureJump = false;
+ if (!failureCases.empty()) {
+ failureCases.link(this);
+ restoreArgumentReferenceForTrampoline();
+ failureJump = jump();
+ plantedFailureJump = true;
+ }
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ if (plantedFailureJump)
+ patchBuffer.link(failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
+
+ if (transitionWillNeedStorageRealloc(oldStructure, newStructure))
+ patchBuffer.link(callTarget, reinterpret_cast<void*>(resizePropertyStorage));
+
+ stubInfo->stubRoutine = code;
+
+ Jump::patch(returnAddress, code);
+}
+
+void JIT::patchGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+{
+ // We don't want to patch more than once - in future go to cti_op_get_by_id_generic.
+ // Should probably go to Interpreter::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
+ Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
+
+ // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
+ void* structureAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdStructure);
+ void* displacementAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPropertyMapOffset);
+ DataLabelPtr::patch(structureAddress, structure);
+ DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr));
+}
+
+void JIT::patchPutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+{
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ // Should probably go to Interpreter::cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
+ Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_generic));
+
+ // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
+ void* structureAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdStructure;
+ void* displacementAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdPropertyMapOffset;
+ DataLabelPtr::patch(structureAddress, structure);
+ DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr));
+}
+
+void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
+{
+ StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
+
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
+
+ // Check eax is an array
+ Jump failureCases1 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr));
+
+ // Checks out okay! - get the length from the storage
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
+ load32(Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_length)), X86::ecx);
+
+ Jump failureCases2 = ja32(X86::ecx, Imm32(JSImmediate::maxImmediateInt));
+
+ emitFastArithIntToImmNoCheck(X86::ecx, X86::eax);
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+ patchBuffer.link(failureCases1, slowCaseBegin);
+ patchBuffer.link(failureCases2, slowCaseBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ void* hotPathPutResult = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, hotPathPutResult);
+
+ // Track the stub we have created so that it will be deleted later.
+ stubInfo->stubRoutine = code;
+
+ // Finally patch the jump to sow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+}
+
+void JIT::privateCompileGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+{
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
+ Jump failureCases2 = checkStructure(X86::eax, structure);
+
+ // Checks out okay! - getDirectOffset
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ ret();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
+ patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
+
+ stubInfo->stubRoutine = code;
+
+ Jump::patch(returnAddress, code);
+}
+
+void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
+{
+#if USE(CTI_REPATCH_PIC)
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
+
+ // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
+ // referencing the prototype object - let's speculatively load it's table nice and early!)
+ JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(static_cast<void*>(protoPropertyStorage), X86::edx);
+
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = checkStructure(X86::eax, structure);
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(prototypeStructure), X86::ebx);
+ Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress));
+#else
+ Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+#endif
+
+ // Checks out okay! - getDirectOffset
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+ patchBuffer.link(failureCases1, slowCaseBegin);
+ patchBuffer.link(failureCases2, slowCaseBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, reinterpret_cast<void*>(successDest));
+
+ // Track the stub we have created so that it will be deleted later.
+ stubInfo->stubRoutine = code;
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+#else
+ // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
+ // referencing the prototype object - let's speculatively load it's table nice and early!)
+ JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(protoPropertyStorage, X86::edx);
+
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
+ Jump failureCases2 = checkStructure(X86::eax, structure);
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+ Jump failureCases3 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+
+ // Checks out okay! - getDirectOffset
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+
+ ret();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
+ patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
+ patchBuffer.link(failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
+
+ stubInfo->stubRoutine = code;
+
+ Jump::patch(returnAddress, code);
+#endif
+}
+
+#if USE(CTI_REPATCH_PIC)
+void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
+{
+ Jump failureCase = checkStructure(X86::eax, structure);
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ ASSERT(code);
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
+ if (!lastProtoBegin)
+ lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+
+ patchBuffer.link(failureCase, lastProtoBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, reinterpret_cast<void*>(successDest));
+
+ structure->ref();
+ polymorphicStructures->list[currentIndex].set(code, structure);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+}
+
+void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
+{
+ // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
+ // referencing the prototype object - let's speculatively load it's table nice and early!)
+ JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(protoPropertyStorage, X86::edx);
+
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = checkStructure(X86::eax, structure);
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(prototypeStructure), X86::ebx);
+ Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress));
+#else
+ Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+#endif
+
+ // Checks out okay! - getDirectOffset
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+ patchBuffer.link(failureCases1, lastProtoBegin);
+ patchBuffer.link(failureCases2, lastProtoBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, reinterpret_cast<void*>(successDest));
+
+ structure->ref();
+ prototypeStructure->ref();
+ prototypeStructures->list[currentIndex].set(code, structure, prototypeStructure);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+}
+
+void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
+{
+ ASSERT(count);
+
+ JumpList bucketsOfFail;
+
+ // Check eax is an object of the right Structure.
+ Jump baseObjectCheck = checkStructure(X86::eax, structure);
+ bucketsOfFail.append(baseObjectCheck);
+
+ Structure* currStructure = structure;
+ RefPtr<Structure>* chainEntries = chain->head();
+ JSObject* protoObject = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ protoObject = asObject(currStructure->prototypeForLookup(callFrame));
+ currStructure = chainEntries[i].get();
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(currStructure), X86::ebx);
+ bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
+#else
+ bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+#endif
+ }
+ ASSERT(protoObject);
+
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(protoPropertyStorage, X86::edx);
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+
+ patchBuffer.link(bucketsOfFail, lastProtoBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, reinterpret_cast<void*>(successDest));
+
+ // Track the stub we have created so that it will be deleted later.
+ structure->ref();
+ chain->ref();
+ prototypeStructures->list[currentIndex].set(code, structure, chain);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+}
+#endif
+
+void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
+{
+#if USE(CTI_REPATCH_PIC)
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
+
+ ASSERT(count);
+
+ JumpList bucketsOfFail;
+
+ // Check eax is an object of the right Structure.
+ bucketsOfFail.append(checkStructure(X86::eax, structure));
+
+ Structure* currStructure = structure;
+ RefPtr<Structure>* chainEntries = chain->head();
+ JSObject* protoObject = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ protoObject = asObject(currStructure->prototypeForLookup(callFrame));
+ currStructure = chainEntries[i].get();
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(currStructure), X86::ebx);
+ bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
+#else
+ bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+#endif
+ }
+ ASSERT(protoObject);
+
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(protoPropertyStorage, X86::edx);
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ Jump success = jump();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+
+ patchBuffer.link(bucketsOfFail, slowCaseBegin);
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
+ patchBuffer.link(success, reinterpret_cast<void*>(successDest));
+
+ // Track the stub we have created so that it will be deleted later.
+ stubInfo->stubRoutine = code;
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
+ Jump::patch(jumpLocation, code);
+#else
+ ASSERT(count);
+
+ JumpList bucketsOfFail;
+
+ // Check eax is an object of the right Structure.
+ bucketsOfFail.append(emitJumpIfNotJSCell(X86::eax));
+ bucketsOfFail.append(checkStructure(X86::eax, structure));
+
+ Structure* currStructure = structure;
+ RefPtr<Structure>* chainEntries = chain->head();
+ JSObject* protoObject = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ protoObject = asObject(currStructure->prototypeForLookup(callFrame));
+ currStructure = chainEntries[i].get();
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(currStructure), X86::ebx);
+ bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
+#else
+ bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+#endif
+ }
+ ASSERT(protoObject);
+
+ PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
+ loadPtr(protoPropertyStorage, X86::edx);
+ loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ ret();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+
+ patchBuffer.link(bucketsOfFail, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
+
+ stubInfo->stubRoutine = code;
+
+ Jump::patch(returnAddress, code);
+#endif
+}
+
+void JIT::privateCompilePutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+{
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
+ Jump failureCases2 = checkStructure(X86::eax, structure);
+
+ // checks out okay! - putDirectOffset
+ loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
+ storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr)));
+ ret();
+
+ void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
+ PatchBuffer patchBuffer(code);
+
+ patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
+ patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
+
+ stubInfo->stubRoutine = code;
+
+ Jump::patch(returnAddress, code);
+}
+
+#endif
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "BytecodeGenerator.h"
+#include "Completion.h"
+#include "InitializeThreading.h"
+#include "JSArray.h"
+#include "JSLock.h"
+#include "PrototypeFunction.h"
+#include "SamplingTool.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !PLATFORM(WIN_OS)
+#include <unistd.h>
+#endif
+
+#if HAVE(READLINE)
+#include <readline/history.h>
+#include <readline/readline.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if PLATFORM(UNIX)
+#include <signal.h>
+#endif
+
+#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
+#include <crtdbg.h>
+#include <windows.h>
+#endif
+
+#if PLATFORM(QT)
+#include <QCoreApplication>
+#include <QDateTime>
+#endif
+
+using namespace JSC;
+using namespace WTF;
+
+static void cleanupGlobalData(JSGlobalData*);
+static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
+
+static JSValuePtr functionPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionDebug(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionGC(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionRun(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionLoad(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionReadline(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static NO_RETURN JSValuePtr functionQuit(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+struct Options {
+ Options()
+ : interactive(false)
+ , dump(false)
+ {
+ }
+
+ bool interactive;
+ bool dump;
+ Vector<UString> fileNames;
+ Vector<UString> arguments;
+};
+
+static const char interactivePrompt[] = "> ";
+static const UString interpreterName("Interpreter");
+
+class StopWatch {
+public:
+ void start();
+ void stop();
+ long getElapsedMS(); // call stop() first
+
+private:
+#if PLATFORM(QT)
+ uint m_startTime;
+ uint m_stopTime;
+#elif PLATFORM(WIN_OS)
+ DWORD m_startTime;
+ DWORD m_stopTime;
+#else
+ // Windows does not have timeval, disabling this class for now (bug 7399)
+ timeval m_startTime;
+ timeval m_stopTime;
+#endif
+};
+
+void StopWatch::start()
+{
+#if PLATFORM(QT)
+ QDateTime t = QDateTime::currentDateTime();
+ m_startTime = t.toTime_t() * 1000 + t.time().msec();
+#elif PLATFORM(WIN_OS)
+ m_startTime = timeGetTime();
+#else
+ gettimeofday(&m_startTime, 0);
+#endif
+}
+
+void StopWatch::stop()
+{
+#if PLATFORM(QT)
+ QDateTime t = QDateTime::currentDateTime();
+ m_stopTime = t.toTime_t() * 1000 + t.time().msec();
+#elif PLATFORM(WIN_OS)
+ m_stopTime = timeGetTime();
+#else
+ gettimeofday(&m_stopTime, 0);
+#endif
+}
+
+long StopWatch::getElapsedMS()
+{
+#if PLATFORM(WIN_OS) || PLATFORM(QT)
+ return m_stopTime - m_startTime;
+#else
+ timeval elapsedTime;
+ timersub(&m_stopTime, &m_startTime, &elapsedTime);
+
+ return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
+#endif
+}
+
+class GlobalObject : public JSGlobalObject {
+public:
+ GlobalObject(const Vector<UString>& arguments);
+ virtual UString className() const { return "global"; }
+};
+COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
+ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
+
+GlobalObject::GlobalObject(const Vector<UString>& arguments)
+ : JSGlobalObject()
+{
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
+ putDirectFunction(globalExec(), new (globalExec()) PrototypeFunction(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
+
+ JSObject* array = constructEmptyArray(globalExec());
+ for (size_t i = 0; i < arguments.size(); ++i)
+ array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
+ putDirect(Identifier(globalExec(), "arguments"), array);
+}
+
+JSValuePtr functionPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ for (unsigned i = 0; i < args.size(); ++i) {
+ if (i != 0)
+ putchar(' ');
+
+ printf("%s", args.at(exec, i).toString(exec).UTF8String().c_str());
+ }
+
+ putchar('\n');
+ fflush(stdout);
+ return jsUndefined();
+}
+
+JSValuePtr functionDebug(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ fprintf(stderr, "--> %s\n", args.at(exec, 0).toString(exec).UTF8String().c_str());
+ return jsUndefined();
+}
+
+JSValuePtr functionGC(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ JSLock lock(false);
+ exec->heap()->collect();
+ return jsUndefined();
+}
+
+JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&)
+{
+ // We need this function for compatibility with the Mozilla JS tests but for now
+ // we don't actually do any version-specific handling
+ return jsUndefined();
+}
+
+JSValuePtr functionRun(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ StopWatch stopWatch;
+ UString fileName = args.at(exec, 0).toString(exec);
+ Vector<char> script;
+ if (!fillBufferWithContentsOfFile(fileName, script))
+ return throwError(exec, GeneralError, "Could not open file.");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+
+ stopWatch.start();
+ evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+ stopWatch.stop();
+
+ return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
+}
+
+JSValuePtr functionLoad(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ UString fileName = args.at(exec, 0).toString(exec);
+ Vector<char> script;
+ if (!fillBufferWithContentsOfFile(fileName, script))
+ return throwError(exec, GeneralError, "Could not open file.");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+
+ return jsUndefined();
+}
+
+JSValuePtr functionReadline(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ Vector<char, 256> line;
+ int c;
+ while ((c = getchar()) != EOF) {
+ // FIXME: Should we also break on \r?
+ if (c == '\n')
+ break;
+ line.append(c);
+ }
+ line.append('\0');
+ return jsString(exec, line.data());
+}
+
+JSValuePtr functionQuit(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ cleanupGlobalData(&exec->globalData());
+ exit(EXIT_SUCCESS);
+}
+
+// Use SEH for Release builds only to get rid of the crash report dialog
+// (luckily the same tests fail in Release and Debug builds so far). Need to
+// be in a separate main function because the jscmain function requires object
+// unwinding.
+
+#if COMPILER(MSVC) && !defined(_DEBUG)
+#define TRY __try {
+#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
+#else
+#define TRY
+#define EXCEPT(x)
+#endif
+
+int jscmain(int argc, char** argv, JSGlobalData*);
+
+int main(int argc, char** argv)
+{
+#if defined(_DEBUG) && PLATFORM(WIN_OS)
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+#endif
+
+#if PLATFORM(QT)
+ QCoreApplication app(argc, argv);
+#endif
+
+ // Initialize JSC before getting JSGlobalData.
+ JSC::initializeThreading();
+
+ // We can't use destructors in the following code because it uses Windows
+ // Structured Exception Handling
+ int res = 0;
+ JSGlobalData* globalData = JSGlobalData::create().releaseRef();
+ TRY
+ res = jscmain(argc, argv, globalData);
+ EXCEPT(res = 3)
+
+ cleanupGlobalData(globalData);
+ return res;
+}
+
+static void cleanupGlobalData(JSGlobalData* globalData)
+{
+ JSLock lock(false);
+ globalData->heap.destroy();
+ globalData->deref();
+}
+
+static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool dump)
+{
+ Vector<char> script;
+
+ if (dump)
+ BytecodeGenerator::setDumpsGeneratedCode(true);
+
+#if ENABLE(OPCODE_SAMPLING)
+ Interpreter* interpreter = globalObject->globalData()->interpreter;
+ interpreter->setSampler(new SamplingTool(interpreter));
+#endif
+
+ bool success = true;
+ for (size_t i = 0; i < fileNames.size(); i++) {
+ UString fileName = fileNames[i];
+
+ if (!fillBufferWithContentsOfFile(fileName, script))
+ return false; // fail early so we can catch missing files
+
+#if ENABLE(OPCODE_SAMPLING)
+ interpreter->sampler()->start();
+#endif
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+ success = success && completion.complType() != Throw;
+ if (dump) {
+ if (completion.complType() == Throw)
+ printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+ else
+ printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+ }
+
+ globalObject->globalExec()->clearException();
+
+#if ENABLE(OPCODE_SAMPLING)
+ interpreter->sampler()->stop();
+#endif
+ }
+
+#if ENABLE(OPCODE_SAMPLING)
+ interpreter->sampler()->dump(globalObject->globalExec());
+ delete interpreter->sampler();
+#endif
+ return success;
+}
+
+static void runInteractive(GlobalObject* globalObject)
+{
+ while (true) {
+#if HAVE(READLINE)
+ char* line = readline(interactivePrompt);
+ if (!line)
+ break;
+ if (line[0])
+ add_history(line);
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
+ free(line);
+#else
+ puts(interactivePrompt);
+ Vector<char, 256> line;
+ int c;
+ while ((c = getchar()) != EOF) {
+ // FIXME: Should we also break on \r?
+ if (c == '\n')
+ break;
+ line.append(c);
+ }
+ line.append('\0');
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
+#endif
+ if (completion.complType() == Throw)
+ printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+ else
+ printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().c_str());
+
+ globalObject->globalExec()->clearException();
+ }
+ printf("\n");
+}
+
+static NO_RETURN void printUsageStatement()
+{
+ fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
+ fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
+ fprintf(stderr, " -f Specifies a source file (deprecated)\n");
+ fprintf(stderr, " -h|--help Prints this help message\n");
+ fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
+ fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
+ exit(EXIT_FAILURE);
+}
+
+static void parseArguments(int argc, char** argv, Options& options)
+{
+ int i = 1;
+ for (; i < argc; ++i) {
+ const char* arg = argv[i];
+ if (strcmp(arg, "-f") == 0) {
+ if (++i == argc)
+ printUsageStatement();
+ options.fileNames.append(argv[i]);
+ continue;
+ }
+ if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
+ printUsageStatement();
+ }
+ if (strcmp(arg, "-i") == 0) {
+ options.interactive = true;
+ continue;
+ }
+ if (strcmp(arg, "-d") == 0) {
+ options.dump = true;
+ continue;
+ }
+ if (strcmp(arg, "-s") == 0) {
+#if PLATFORM(UNIX)
+ signal(SIGILL, _exit);
+ signal(SIGFPE, _exit);
+ signal(SIGBUS, _exit);
+ signal(SIGSEGV, _exit);
+#endif
+ continue;
+ }
+ if (strcmp(arg, "--") == 0) {
+ ++i;
+ break;
+ }
+ options.fileNames.append(argv[i]);
+ }
+
+ if (options.fileNames.isEmpty())
+ options.interactive = true;
+
+ for (; i < argc; ++i)
+ options.arguments.append(argv[i]);
+}
+
+int jscmain(int argc, char** argv, JSGlobalData* globalData)
+{
+ JSLock lock(false);
+
+ Options options;
+ parseArguments(argc, argv, options);
+
+ GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
+ bool success = runWithScripts(globalObject, options.fileNames, options.dump);
+ if (options.interactive && success)
+ runInteractive(globalObject);
+
+ return success ? 0 : 3;
+}
+
+static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
+{
+ FILE* f = fopen(fileName.UTF8String().c_str(), "r");
+ if (!f) {
+ fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str());
+ return false;
+ }
+
+ size_t buffer_size = 0;
+ size_t buffer_capacity = 1024;
+
+ buffer.resize(buffer_capacity);
+
+ while (!feof(f) && !ferror(f)) {
+ buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);
+ if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
+ buffer_capacity *= 2;
+ buffer.resize(buffer_capacity);
+ }
+ }
+ fclose(f);
+ buffer[buffer_size] = '\0';
+
+ return true;
+}
--- /dev/null
+TEMPLATE = app
+TARGET = jsc
+DESTDIR = .
+SOURCES = jsc.cpp
+QT -= gui
+INCLUDEPATH += $$PWD \
+ $$PWD/parser \
+ $$PWD/bindings \
+ $$PWD/bindings/c \
+ $$PWD/wtf \
+ $$PWD/jit \
+ $$PWD/bytecode
+CONFIG -= app_bundle
+DEFINES += BUILDING_QT__
+CONFIG += building-libs
+
+CONFIG(release) {
+ DEFINES += NDEBUG USE_SYSTEM_MALLOC
+}
+
+include($$PWD/../WebKit.pri)
+
+CONFIG += link_pkgconfig
+
+QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
+
+isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/..
+include($$OUTPUT_DIR/config.pri)
+OBJECTS_DIR = tmp
+OBJECTS_DIR_WTR = $$OBJECTS_DIR/
+win32-*: OBJECTS_DIR_WTR ~= s|/|\|
+include($$PWD/JavaScriptCore.pri)
+
+lessThan(QT_MINOR_VERSION, 4) {
+ DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
+}
+
+*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
+*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
<include file="../WebKit/wx/wxwk-settings.bkl"/>
<include file="JavaScriptCoreSources.bkl"/>
-
- <set var="BUILDDIR">obj-$(FORMAT)</set>
<template id="jscore_base" template="icu,pthreads,wxwk_build_settings">
<sources>
- $(JSCORE_SOURCES_API)
- $(JSCORE_SOURCES_BINDINGS)
- $(JSCORE_SOURCES_KJS)
- $(JSCORE_SOURCES_PCRE)
- $(WTF_SOURCES)
+ $(JSCORE_API_SOURCES)
+ $(JSCORE_BYTECOMPILER_SOURCES)
+ $(JSCORE_DEBUGGER_SOURCES)
+ $(JSCORE_JSC_SOURCES)
+ $(JSCORE_PCRE_SOURCES)
+ $(JSCORE_PARSER_SOURCES)
+ $(JSCORE_PROFILER_SOURCES)
+ $(JSCORE_RUNTIME_SOURCES)
+ $(JSCORE_VM_SOURCES)
+ $(JSCORE_WTF_SOURCES)
</sources>
<install-to>$(WKOUTPUTDIR)</install-to>
<pic>on</pic>
<include>$(SRCDIR)</include>
<include>$(SRCDIR)/..</include>
+ <include>$(SRCDIR)/API</include>
+ <include>$(SRCDIR)/bytecompiler</include>
<include>$(SRCDIR)/DerivedSources/JavaScriptCore</include>
<include>$(SRCDIR)/ForwardingHeaders</include>
- <include>$(SRCDIR)/bindings/c</include>
- <include>$(SRCDIR)/bindings/jni</include>
- <include>$(SRCDIR)/bindings</include>
- <include>$(SRCDIR)/kjs</include>
+ <include>$(SRCDIR)/debugger</include>
+ <include>$(SRCDIR)/parser</include>
<include>$(SRCDIR)/pcre</include>
+ <include>$(SRCDIR)/profiler</include>
+ <include>$(SRCDIR)/runtime</include>
+ <include>$(SRCDIR)/interpreter</include>
+ <include>$(SRCDIR)/bytecode</include>
+ <include>$(SRCDIR)/wrec</include>
+ <include>$(SRCDIR)/jit</include>
<include>$(SRCDIR)/wtf</include>
+ <include>$(SRCDIR)/wtf/unicode</include>
<define>ENABLE_XSLT=1</define>
</template>
- <exe id="testkjs" template="icu,jscore,pthreads">
+ <exe id="jsc" template="icu,jscore,pthreads,wxwk">
<cxx-rtti>off</cxx-rtti>
<cxx-exceptions>off</cxx-exceptions>
<debug-info>on</debug-info>
<depends>jscore</depends>
<include>$(SRCDIR)</include>
<include>$(WK_ROOT)/JavaScriptCore</include>
- <include>$(WK_ROOT)/JavaScriptCore/kjs</include>
+ <include>$(WK_ROOT)/JavaScriptCore/bytecompiler</include>
+ <include>$(WK_ROOT)/JavaScriptCore/debugger</include>
+ <include>$(WK_ROOT)/JavaScriptCore/parser</include>
<include>$(WK_ROOT)/JavaScriptCore/pcre</include>
+ <include>$(WK_ROOT)/JavaScriptCore/profiler</include>
+ <include>$(WK_ROOT)/JavaScriptCore/runtime</include>
+ <include>$(WK_ROOT)/JavaScriptCore/interpreter</include>
+ <include>$(WK_ROOT)/JavaScriptCore/bytecode</include>
+ <include>$(WK_ROOT)/JavaScriptCore/jit</include>
+ <include>$(WK_ROOT)/JavaScriptCore/wrec</include>
<include>$(WK_ROOT)/JavaScriptCore/wtf</include>
<dirname>$(WKOUTPUTDIR)</dirname>
- <sources>$(SRCDIR)/kjs/testkjs.cpp</sources>
+ <sources>$(SRCDIR)/jsc.cpp</sources>
<if cond="FORMAT=='gnu'">
<ldflags>$(WKOUTPUTDIR)/libjscore.a</ldflags>
</if>
+ <set var="READLINE_LIB">
+ <if cond="WX_PORT=='mac'">edit</if>
+ </set>
+ <sys-lib>$(READLINE_LIB)</sys-lib>
<if cond="FORMAT in ['msvc','msvs2005prj']">
<include>$(WK_ROOT)/WebKitLibraries/win/include</include>
<sys-lib>jscore</sys-lib>
<command>bash make-generated-sources.sh</command>
</action>
- <lib id="jscore" template="jscore_base">
+ <lib id="jscore" template="jscore_base,wx-lib">
</lib>
</makefile>
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Activation_h
-#define Activation_h
-
-#include "ExecState.h"
-#include "JSVariableObject.h"
-#include "object.h"
-
-namespace KJS {
-
- class Arguments;
- class FunctionImp;
-
- class ActivationImp : public JSVariableObject {
- friend class JSGlobalObject;
- friend struct StackActivation;
- private:
- struct ActivationData : public JSVariableObjectData {
- ActivationData() : isOnStack(true), leftRelic(false) { }
- ActivationData(const ActivationData&);
-
- ExecState* exec;
- FunctionImp* function;
- Arguments* argumentsObject;
-
- bool isOnStack : 1;
- bool leftRelic : 1;
- };
-
- public:
- ActivationImp() { }
- ActivationImp(const ActivationData&, bool);
-
- virtual ~ActivationImp();
-
- void init(ExecState*);
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValue*, int attr = None);
- virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- virtual void mark();
- void markChildren();
-
- virtual bool isActivationObject() { return true; }
-
- bool isOnStack() const { return d()->isOnStack; }
- bool needsPop() const { return d()->isOnStack || d()->leftRelic; }
-
- private:
- static PropertySlot::GetValueFunc getArgumentsGetter();
- static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- void createArgumentsObject(ExecState*);
- ActivationData* d() const { return static_cast<ActivationData*>(JSVariableObject::d); }
- };
-
- const size_t activationStackNodeSize = 32;
-
- struct StackActivation {
- StackActivation() { activationStorage.JSVariableObject::d = &activationDataStorage; }
- StackActivation(const StackActivation&);
-
- ActivationImp activationStorage;
- ActivationImp::ActivationData activationDataStorage;
- };
-
- struct ActivationStackNode {
- ActivationStackNode* prev;
- StackActivation data[activationStackNodeSize];
- };
-
-} // namespace
-
-#endif
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-// This file exists to help compile the essential code of
-// JavaScriptCore all as one file, for compilers and build systems
-// that see a significant speed gain from this.
-
-#define KDE_USE_FINAL 1
-#include "config.h"
-
-#include "function.cpp"
-#include "debugger.cpp"
-#include "array_instance.cpp"
-#include "array_object.cpp"
-#include "bool_object.cpp"
-#include "collector.cpp"
-#if PLATFORM(DARWIN)
-#include "CollectorHeapIntrospector.cpp"
-#endif
-#include "CommonIdentifiers.cpp"
-#include "date_object.cpp"
-#include "DateMath.cpp"
-#include "dtoa.cpp"
-#include "error_object.cpp"
-#include "ExecState.cpp"
-#include "function_object.cpp"
-#include "grammar.cpp"
-#include "identifier.cpp"
-#include "internal.cpp"
-#include "interpreter.cpp"
-#include "JSImmediate.cpp"
-#include "JSLock.cpp"
-#include "JSWrapperObject.cpp"
-#include "lexer.cpp"
-#include "list.cpp"
-#include "lookup.cpp"
-#include "math_object.cpp"
-#include "nodes.cpp"
-#include "nodes2string.cpp"
-#include "number_object.cpp"
-#include "object.cpp"
-#include "object_object.cpp"
-#include "operations.cpp"
-#include "Parser.cpp"
-#include "property_map.cpp"
-#include "property_slot.cpp"
-#include "PropertyNameArray.cpp"
-#include "regexp.cpp"
-#include "regexp_object.cpp"
-#include "scope_chain.cpp"
-#include "string_object.cpp"
-#include "ustring.cpp"
-#include "value.cpp"
-#include "wtf/FastMalloc.cpp"
-#include "wtf/TCSystemAlloc.cpp"
+++ /dev/null
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "CollectorHeapIntrospector.h"
-
-#include "collector.h"
-#include "MallocZoneSupport.h"
-
-namespace KJS {
-
-extern "C" {
-malloc_introspection_t jscore_collector_introspection = { &CollectorHeapIntrospector::enumerate, &CollectorHeapIntrospector::goodSize, &CollectorHeapIntrospector::check, &CollectorHeapIntrospector::print,
- &CollectorHeapIntrospector::log, &CollectorHeapIntrospector::forceLock, &CollectorHeapIntrospector::forceUnlock, &CollectorHeapIntrospector::statistics };
-}
-
-void CollectorHeapIntrospector::init(CollectorHeap* primaryHeap, CollectorHeap* numberHeap)
-{
- static CollectorHeapIntrospector zone(primaryHeap, numberHeap);
-}
-
-CollectorHeapIntrospector::CollectorHeapIntrospector(CollectorHeap* primaryHeap, CollectorHeap* numberHeap)
- : m_primaryHeap(primaryHeap)
- , m_numberHeap(numberHeap)
-{
- memset(&m_zone, 0, sizeof(m_zone));
- m_zone.zone_name = "JavaScriptCore Collector";
- m_zone.size = &CollectorHeapIntrospector::size;
- m_zone.malloc = &CollectorHeapIntrospector::zoneMalloc;
- m_zone.calloc = &CollectorHeapIntrospector::zoneCalloc;
- m_zone.realloc = &CollectorHeapIntrospector::zoneRealloc;
- m_zone.free = &CollectorHeapIntrospector::zoneFree;
- m_zone.valloc = &CollectorHeapIntrospector::zoneValloc;
- m_zone.destroy = &CollectorHeapIntrospector::zoneDestroy;
- m_zone.introspect = &jscore_collector_introspection;
- malloc_zone_register(&m_zone);
-}
-
-kern_return_t CollectorHeapIntrospector::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder)
-{
- RemoteMemoryReader memoryReader(task, reader);
- CollectorHeapIntrospector* zone = memoryReader(reinterpret_cast<CollectorHeapIntrospector*>(zoneAddress));
- CollectorHeap* heaps[2] = {memoryReader(zone->m_primaryHeap), memoryReader(zone->m_numberHeap)};
-
- if (!heaps[0]->blocks && !heaps[1]->blocks)
- return 0;
-
- for (int currentHeap = 0; currentHeap < 2; currentHeap++) {
- CollectorHeap* heap = heaps[currentHeap];
- CollectorBlock** blocks = memoryReader(heap->blocks);
- for (unsigned i = 0; i < heap->usedBlocks; i++) {
- vm_address_t remoteBlockAddress = reinterpret_cast<vm_address_t>(blocks[i]);
- vm_range_t ptrRange = { remoteBlockAddress, sizeof(CollectorBlock) };
-
- if (typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
- (*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
-
- // Recording individual cells causes frequent false-positives. Any garbage cells
- // which have yet to be collected are labeled as leaks. Recording on a per-block
- // basis provides less detail but avoids these false-positives.
- if (memoryReader(blocks[i])->usedCells && (typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE))
- (*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1);
- }
- }
-
- return 0;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CollectorHeapIntrospector_h
-#define CollectorHeapIntrospector_h
-
-#include <malloc/malloc.h>
-#include "Assertions.h"
-
-namespace KJS {
-
-struct CollectorHeap;
-
-class CollectorHeapIntrospector {
-public:
- static void init(CollectorHeap*, CollectorHeap*);
- static kern_return_t enumerate(task_t, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t);
- static size_t goodSize(malloc_zone_t*, size_t size) { return size; }
- static boolean_t check(malloc_zone_t*) { return true; }
- static void print(malloc_zone_t*, boolean_t) { }
- static void log(malloc_zone_t*, void*) { }
- static void forceLock(malloc_zone_t*) { }
- static void forceUnlock(malloc_zone_t*) { }
- static void statistics(malloc_zone_t*, malloc_statistics_t*) { }
-
-private:
- CollectorHeapIntrospector(CollectorHeap*, CollectorHeap*);
- static size_t size(malloc_zone_t*, const void*) { return 0; }
- static void* zoneMalloc(malloc_zone_t*, size_t) { LOG_ERROR("malloc is not supported"); return 0; }
- static void* zoneCalloc(malloc_zone_t*, size_t, size_t) { LOG_ERROR("calloc is not supported"); return 0; }
- static void* zoneRealloc(malloc_zone_t*, void*, size_t) { LOG_ERROR("realloc is not supported"); return 0; }
- static void* zoneValloc(malloc_zone_t*, size_t) { LOG_ERROR("valloc is not supported"); return 0; }
- static void zoneDestroy(malloc_zone_t*) { }
-
- static void zoneFree(malloc_zone_t*, void* ptr)
- {
- // Due to <rdar://problem/5671357> zoneFree may be called by the system free even if the pointer
- // is not in this zone. When this happens, the pointer being freed was not allocated by any
- // zone so we need to print a useful error for the application developer.
- malloc_printf("*** error for object %p: pointer being freed was not allocated\n", ptr);
- }
-
- malloc_zone_t m_zone;
- CollectorHeap* m_primaryHeap;
- CollectorHeap* m_numberHeap;
-};
-
-}
-
-#endif // CollectorHeapIntrospector_h
+++ /dev/null
-/*
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "CommonIdentifiers.h"
-
-namespace KJS {
-
-const char* const nullCString = 0;
-
-#define INITIALIZE_PROPERTY_NAME(name) , name ( #name )
-
-CommonIdentifiers::CommonIdentifiers()
- : nullIdentifier(nullCString)
- , underscoreProto("__proto__")
- KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
-{
-}
-
-CommonIdentifiers* CommonIdentifiers::shared()
-{
- static CommonIdentifiers* sharedInstance;
- if (!sharedInstance) {
- JSLock lock;
- sharedInstance = new CommonIdentifiers;
- }
- return sharedInstance;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 2003,2007 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_COMMON_IDENTIFIERS_H
-#define KJS_COMMON_IDENTIFIERS_H
-
-#include "identifier.h"
-#include <wtf/Noncopyable.h>
-
-// List of property names, passed to a macro so we can do set them up various
-// ways without repeating the list.
-#define KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
- macro(arguments) \
- macro(callee) \
- macro(caller) \
- macro(constructor) \
- macro(fromCharCode) \
- macro(global) \
- macro(ignoreCase) \
- macro(index) \
- macro(input) \
- macro(length) \
- macro(message) \
- macro(multiline) \
- macro(name) \
- macro(prototype) \
- macro(source) \
- macro(toExponential) \
- macro(toFixed) \
- macro(toLocaleString) \
- macro(toPrecision) \
- macro(toString) \
- macro(valueOf)
-
-namespace KJS {
-
- class CommonIdentifiers : Noncopyable {
-
- private:
- CommonIdentifiers();
-
- public:
- static CommonIdentifiers* shared();
-
- const Identifier nullIdentifier;
- const Identifier underscoreProto;
-
-#define KJS_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
- KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(KJS_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL)
-#undef KJS_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL
- };
-} // namespace KJS
-
-#endif // KJS_COMMON_IDENTIFIERS_H
-
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
- */
-
-#include "config.h"
-#include "DateMath.h"
-
-#include <math.h>
-#include <stdint.h>
-#include <value.h>
-
-#include <wtf/Assertions.h>
-
-#if PLATFORM(DARWIN)
-#include <notify.h>
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if HAVE(SYS_TIMEB_H)
-#include <sys/timeb.h>
-#endif
-
-namespace KJS {
-
-/* Constants */
-
-static const double minutesPerDay = 24.0 * 60.0;
-static const double secondsPerDay = 24.0 * 60.0 * 60.0;
-static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
-
-static const double usecPerSec = 1000000.0;
-
-static const double maxUnixTime = 2145859200.0; // 12/31/2037
-
-// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
-// First for non-leap years, then for leap years.
-static const int firstDayOfMonth[2][12] = {
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
- {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
-};
-
-static inline bool isLeapYear(int year)
-{
- if (year % 4 != 0)
- return false;
- if (year % 400 == 0)
- return true;
- if (year % 100 == 0)
- return false;
- return true;
-}
-
-static inline int daysInYear(int year)
-{
- return 365 + isLeapYear(year);
-}
-
-static inline double daysFrom1970ToYear(int year)
-{
- // The Gregorian Calendar rules for leap years:
- // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years.
- // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years.
- // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years.
-
- static const int leapDaysBefore1971By4Rule = 1970 / 4;
- static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
- static const int leapDaysBefore1971By400Rule = 1970 / 400;
-
- const double yearMinusOne = year - 1;
- const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
- const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
- const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
-
- return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
-}
-
-static inline double msToDays(double ms)
-{
- return floor(ms / msPerDay);
-}
-
-static inline int msToYear(double ms)
-{
- int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
- double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
- if (msFromApproxYearTo1970 > ms)
- return approxYear - 1;
- if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
- return approxYear + 1;
- return approxYear;
-}
-
-static inline int dayInYear(double ms, int year)
-{
- return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
-}
-
-static inline double msToMilliseconds(double ms)
-{
- double result = fmod(ms, msPerDay);
- if (result < 0)
- result += msPerDay;
- return result;
-}
-
-// 0: Sunday, 1: Monday, etc.
-static inline int msToWeekDay(double ms)
-{
- int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
- if (wd < 0)
- wd += 7;
- return wd;
-}
-
-static inline int msToSeconds(double ms)
-{
- double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
- if (result < 0)
- result += secondsPerMinute;
- return static_cast<int>(result);
-}
-
-static inline int msToMinutes(double ms)
-{
- double result = fmod(floor(ms / msPerMinute), minutesPerHour);
- if (result < 0)
- result += minutesPerHour;
- return static_cast<int>(result);
-}
-
-static inline int msToHours(double ms)
-{
- double result = fmod(floor(ms/msPerHour), hoursPerDay);
- if (result < 0)
- result += hoursPerDay;
- return static_cast<int>(result);
-}
-
-static inline int monthFromDayInYear(int dayInYear, bool leapYear)
-{
- const int d = dayInYear;
- int step;
-
- if (d < (step = 31))
- return 0;
- step += (leapYear ? 29 : 28);
- if (d < step)
- return 1;
- if (d < (step += 31))
- return 2;
- if (d < (step += 30))
- return 3;
- if (d < (step += 31))
- return 4;
- if (d < (step += 30))
- return 5;
- if (d < (step += 31))
- return 6;
- if (d < (step += 31))
- return 7;
- if (d < (step += 30))
- return 8;
- if (d < (step += 31))
- return 9;
- if (d < (step += 30))
- return 10;
- return 11;
-}
-
-static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
-{
- startDayOfThisMonth = startDayOfNextMonth;
- startDayOfNextMonth += daysInThisMonth;
- return (dayInYear <= startDayOfNextMonth);
-}
-
-static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
-{
- const int d = dayInYear;
- int step;
- int next = 30;
-
- if (d <= next)
- return d + 1;
- const int daysInFeb = (leapYear ? 29 : 28);
- if (checkMonth(d, step, next, daysInFeb))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- step = next;
- return d - step;
-}
-
-static inline int monthToDayInYear(int month, bool isLeapYear)
-{
- return firstDayOfMonth[isLeapYear][month];
-}
-
-static inline double timeToMS(double hour, double min, double sec, double ms)
-{
- return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
-}
-
-static int dateToDayInYear(int year, int month, int day)
-{
- year += month / 12;
-
- month %= 12;
- if (month < 0) {
- month += 12;
- --year;
- }
-
- int yearday = static_cast<int>(floor(daysFrom1970ToYear(year)));
- int monthday = monthToDayInYear(month, isLeapYear(year));
-
- return yearday + monthday + day - 1;
-}
-
-double getCurrentUTCTime()
-{
-#if PLATFORM(WIN_OS)
-#if COMPILER(BORLAND)
- struct timeb timebuffer;
- ftime(&timebuffer);
-#else
- struct _timeb timebuffer;
- _ftime(&timebuffer);
-#endif
- double utc = timebuffer.time * msPerSecond + timebuffer.millitm;
-#else
- struct timeval tv;
- gettimeofday(&tv, 0);
- double utc = floor(tv.tv_sec * msPerSecond + tv.tv_usec / 1000);
-#endif
- return utc;
-}
-
-// There is a hard limit at 2038 that we currently do not have a workaround
-// for (rdar://problem/5052975).
-static inline int maximumYearForDST()
-{
- return 2037;
-}
-
-// It is ok if the cached year is not the current year (e.g. Dec 31st)
-// so long as the rules for DST did not change between the two years, if it does
-// the app would need to be restarted.
-static int mimimumYearForDST()
-{
- // Because of the 2038 issue (see maximumYearForDST) if the current year is
- // greater than the max year minus 27 (2010), we want to use the max year
- // minus 27 instead, to ensure there is a range of 28 years that all years
- // can map to.
- static int minYear = std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
- return minYear;
-}
-
-/*
- * Find an equivalent year for the one given, where equivalence is deterined by
- * the two years having the same leapness and the first day of the year, falling
- * on the same day of the week.
- *
- * This function returns a year between this current year and 2037, however this
- * function will potentially return incorrect results if the current year is after
- * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after
- * 2100, (rdar://problem/5055038).
- */
-int equivalentYearForDST(int year)
-{
- static int minYear = mimimumYearForDST();
- static int maxYear = maximumYearForDST();
-
- int difference;
- if (year > maxYear)
- difference = minYear - year;
- else if (year < minYear)
- difference = maxYear - year;
- else
- return year;
-
- int quotient = difference / 28;
- int product = (quotient) * 28;
-
- year += product;
- ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN)));
- return year;
-}
-
-/*
- * Get the difference in milliseconds between this time zone and UTC (GMT)
- * NOT including DST.
- */
-double getUTCOffset()
-{
-#if PLATFORM(DARWIN)
- // Register for a notification whenever the time zone changes.
- static bool triedToRegister = false;
- static bool haveNotificationToken = false;
- static int notificationToken;
- if (!triedToRegister) {
- triedToRegister = true;
- uint32_t status = notify_register_check("com.apple.system.timezone", ¬ificationToken);
- if (status == NOTIFY_STATUS_OK)
- haveNotificationToken = true;
- }
-
- // If we can verify that we have not received a time zone notification,
- // then use the cached offset from the last time this function was called.
- static bool haveCachedOffset = false;
- static double cachedOffset;
- if (haveNotificationToken && haveCachedOffset) {
- int notified;
- uint32_t status = notify_check(notificationToken, ¬ified);
- if (status == NOTIFY_STATUS_OK && !notified)
- return cachedOffset;
- }
-#endif
-
- tm localt;
-
- memset(&localt, 0, sizeof(localt));
-
- // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
- localt.tm_mday = 1;
- localt.tm_year = 100;
- double utcOffset = 946684800.0 - mktime(&localt);
-
- utcOffset *= msPerSecond;
-
-#if PLATFORM(DARWIN)
- haveCachedOffset = true;
- cachedOffset = utcOffset;
-#endif
-
- return utcOffset;
-}
-
-/*
- * Get the DST offset for the time passed in. Takes
- * seconds (not milliseconds) and cannot handle dates before 1970
- * on some OS'
- */
-static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset)
-{
- if (localTimeSeconds > maxUnixTime)
- localTimeSeconds = maxUnixTime;
- else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0)
- localTimeSeconds += secondsPerDay;
-
- //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset()
- double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset;
-
- // Offset from UTC but doesn't include DST obviously
- int offsetHour = msToHours(offsetTime);
- int offsetMinute = msToMinutes(offsetTime);
-
- // FIXME: time_t has a potential problem in 2038
- time_t localTime = static_cast<time_t>(localTimeSeconds);
-
- tm localTM;
-#if PLATFORM(QT)
- // ### this is not threadsafe but we don't use multiple threads anyway
- // in the Qt build
-#if USE(MULTIPLE_THREADS)
-#error Mulitple threads are currently not supported in the Qt/mingw build
-#endif
- localTM = *localtime(&localTime);
-#elif PLATFORM(WIN_OS)
- #if COMPILER(MSVC7)
- localTM = *localtime(&localTime);
- #else
- localtime_s(&localTM, &localTime);
- #endif
-#else
- localtime_r(&localTime, &localTM);
-#endif
-
- double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60);
-
- if (diff < 0)
- diff += secondsPerDay;
-
- return (diff * msPerSecond);
-}
-
-// Get the DST offset, given a time in UTC
-static double getDSTOffset(double ms, double utcOffset)
-{
- // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate
- // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
- // standard explicitly dictates that historical information should not be considered when
- // determining DST. For this reason we shift away from years that localtime can handle but would
- // return historically accurate information.
- int year = msToYear(ms);
- int equivalentYear = equivalentYearForDST(year);
- if (year != equivalentYear) {
- bool leapYear = isLeapYear(year);
- int dayInYearLocal = dayInYear(ms, year);
- int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
- int month = monthFromDayInYear(dayInYearLocal, leapYear);
- int day = dateToDayInYear(equivalentYear, month, dayInMonth);
- ms = (day * msPerDay) + msToMilliseconds(ms);
- }
-
- return getDSTOffsetSimple(ms / msPerSecond, utcOffset);
-}
-
-double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
-{
- int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay);
- double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
- double result = (day * msPerDay) + ms;
-
- if (!inputIsUTC) { // convert to UTC
- double utcOffset = getUTCOffset();
- result -= utcOffset;
- result -= getDSTOffset(result, utcOffset);
- }
-
- return result;
-}
-
-void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm)
-{
- // input is UTC
- double dstOff = 0.0;
- const double utcOff = getUTCOffset();
-
- if (!outputIsUTC) { // convert to local time
- dstOff = getDSTOffset(ms, utcOff);
- ms += dstOff + utcOff;
- }
-
- const int year = msToYear(ms);
- tm.second = msToSeconds(ms);
- tm.minute = msToMinutes(ms);
- tm.hour = msToHours(ms);
- tm.weekDay = msToWeekDay(ms);
- tm.yearDay = dayInYear(ms, year);
- tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
- tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year));
- tm.year = year - 1900;
- tm.isDST = dstOff != 0.0;
-
- tm.utcOffset = static_cast<long>((dstOff + utcOff) / msPerSecond);
- tm.timeZone = NULL;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- */
-
-#ifndef DateMath_h
-#define DateMath_h
-
-#include <time.h>
-#include <string.h>
-#include <wtf/Noncopyable.h>
-
-namespace KJS {
-
-struct GregorianDateTime;
-
-void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
-double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
-double getUTCOffset();
-int equivalentYearForDST(int year);
-double getCurrentUTCTime();
-
-const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
-const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-const double hoursPerDay = 24.0;
-const double minutesPerHour = 60.0;
-const double secondsPerHour = 60.0 * 60.0;
-const double secondsPerMinute = 60.0;
-const double msPerSecond = 1000.0;
-const double msPerMinute = 60.0 * 1000.0;
-const double msPerHour = 60.0 * 60.0 * 1000.0;
-const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
-
-// Intentionally overridding the default tm of the system
-// Tee members of tm differ on various operating systems.
-struct GregorianDateTime : Noncopyable {
- GregorianDateTime()
- : second(0)
- , minute(0)
- , hour(0)
- , weekDay(0)
- , monthDay(0)
- , yearDay(0)
- , month(0)
- , year(0)
- , isDST(0)
- , utcOffset(0)
- , timeZone(0)
- {
- }
-
- ~GregorianDateTime()
- {
- delete [] timeZone;
- }
-
- GregorianDateTime(const tm& inTm)
- : second(inTm.tm_sec)
- , minute(inTm.tm_min)
- , hour(inTm.tm_hour)
- , weekDay(inTm.tm_wday)
- , monthDay(inTm.tm_mday)
- , yearDay(inTm.tm_yday)
- , month(inTm.tm_mon)
- , year(inTm.tm_year)
- , isDST(inTm.tm_isdst)
- {
-#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS)
- utcOffset = static_cast<int>(inTm.tm_gmtoff);
-
- int inZoneSize = strlen(inTm.tm_zone) + 1;
- timeZone = new char[inZoneSize];
- strncpy(timeZone, inTm.tm_zone, inZoneSize);
-#else
- utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0));
- timeZone = 0;
-#endif
- }
-
- operator tm() const
- {
- tm ret;
- memset(&ret, 0, sizeof(ret));
-
- ret.tm_sec = second;
- ret.tm_min = minute;
- ret.tm_hour = hour;
- ret.tm_wday = weekDay;
- ret.tm_mday = monthDay;
- ret.tm_yday = yearDay;
- ret.tm_mon = month;
- ret.tm_year = year;
- ret.tm_isdst = isDST;
-
-#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS)
- ret.tm_gmtoff = static_cast<long>(utcOffset);
- ret.tm_zone = timeZone;
-#endif
-
- return ret;
- }
-
- int second;
- int minute;
- int hour;
- int weekDay;
- int monthDay;
- int yearDay;
- int month;
- int year;
- int isDST;
- int utcOffset;
- char* timeZone;
-};
-
-} //namespace KJS
-
-#endif // DateMath_h
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "ExecState.h"
-
-#include "Activation.h"
-#include "JSGlobalObject.h"
-#include "function.h"
-#include "internal.h"
-#include "scope_chain_mark.h"
-
-namespace KJS {
-
-static inline List* globalEmptyList()
-{
- static List staticEmptyList;
- return &staticEmptyList;
-}
-
-// ECMA 10.2
-
-// The constructor for the globalExec pseudo-ExecState
-inline ExecState::ExecState(JSGlobalObject* globalObject)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_propertyNames(CommonIdentifiers::shared())
- , m_emptyList(globalEmptyList())
- , m_callingExec(0)
- , m_scopeNode(0)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(&globalObject->localStorage())
- , m_variableObject(globalObject)
- , m_thisValue(globalObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(GlobalCode)
-{
- m_scopeChain.push(globalObject);
-}
-
-inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_propertyNames(CommonIdentifiers::shared())
- , m_emptyList(globalEmptyList())
- , m_callingExec(0)
- , m_scopeNode(programNode)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(&globalObject->localStorage())
- , m_variableObject(globalObject)
- , m_thisValue(globalObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(GlobalCode)
-{
- // FIXME: This function ignores the "thisObject" parameter, which means that the API for evaluating
- // a script with a this object that's not the same as the global object is broken, and probably
- // has been for some time.
- ASSERT(m_scopeNode);
- m_scopeChain.push(globalObject);
-}
-
-inline ExecState::ExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState* callingExec)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_propertyNames(callingExec->m_propertyNames)
- , m_emptyList(callingExec->m_emptyList)
- , m_callingExec(callingExec)
- , m_scopeNode(evalNode)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(callingExec->m_localStorage)
- , m_scopeChain(callingExec->m_scopeChain)
- , m_variableObject(callingExec->m_variableObject)
- , m_thisValue(callingExec->m_thisValue)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(EvalCode)
-{
- ASSERT(m_scopeNode);
-}
-
-inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
- FunctionBodyNode* functionBodyNode, ExecState* callingExec,
- FunctionImp* func, const List& args)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_propertyNames(callingExec->m_propertyNames)
- , m_emptyList(callingExec->m_emptyList)
- , m_callingExec(callingExec)
- , m_scopeNode(functionBodyNode)
- , m_function(func)
- , m_arguments(&args)
- , m_scopeChain(func->scope())
- , m_thisValue(thisObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(FunctionCode)
-{
- ASSERT(m_scopeNode);
-
- ActivationImp* activation = globalObject->pushActivation(this);
- m_activation = activation;
- m_localStorage = &activation->localStorage();
- m_variableObject = activation;
- m_scopeChain.push(activation);
-}
-
-inline ExecState::~ExecState()
-{
-}
-
-JSGlobalObject* ExecState::lexicalGlobalObject() const
-{
- JSObject* object = m_scopeChain.bottom();
- if (object && object->isGlobalObject())
- return static_cast<JSGlobalObject*>(object);
- return m_globalObject;
-}
-
-void ExecState::markActiveExecStates()
-{
- ExecStateStack::const_iterator end = activeExecStates().end();
- for (ExecStateStack::const_iterator it = activeExecStates().begin(); it != end; ++it)
- (*it)->m_scopeChain.mark();
-}
-
-static inline ExecStateStack& inlineActiveExecStates()
-{
- static ExecStateStack staticActiveExecStates;
- return staticActiveExecStates;
-}
-
-ExecStateStack& ExecState::activeExecStates()
-{
- return inlineActiveExecStates();
-}
-
-GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
- : ExecState(globalObject)
-{
-}
-
-GlobalExecState::~GlobalExecState()
-{
-}
-
-InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
- : ExecState(globalObject, thisObject, programNode)
-{
- inlineActiveExecStates().append(this);
-}
-
-InterpreterExecState::~InterpreterExecState()
-{
- ASSERT(inlineActiveExecStates().last() == this);
- inlineActiveExecStates().removeLast();
-}
-
-EvalExecState::EvalExecState(JSGlobalObject* globalObject, EvalNode* evalNode, ExecState* callingExec)
- : ExecState(globalObject, evalNode, callingExec)
-{
- inlineActiveExecStates().append(this);
-}
-
-EvalExecState::~EvalExecState()
-{
- ASSERT(inlineActiveExecStates().last() == this);
- inlineActiveExecStates().removeLast();
-}
-
-FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject,
- FunctionBodyNode* functionBodyNode, ExecState* callingExec,
- FunctionImp* func, const List& args)
- : ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
-{
- inlineActiveExecStates().append(this);
-}
-
-FunctionExecState::~FunctionExecState()
-{
- ASSERT(inlineActiveExecStates().last() == this);
- inlineActiveExecStates().removeLast();
-
- if (m_activation->needsPop())
- m_globalObject->popActivation();
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef ExecState_h
-#define ExecState_h
-
-#include "LabelStack.h"
-#include "LocalStorage.h"
-#include "completion.h"
-#include "list.h"
-#include "scope_chain.h"
-
-namespace KJS {
-
- class ActivationImp;
- class CommonIdentifiers;
- class EvalNode;
- class FunctionBodyNode;
- class FunctionImp;
- class GlobalFuncImp;
- class Interpreter;
- class JSGlobalObject;
- class JSVariableObject;
- class ProgramNode;
- class ScopeNode;
-
- enum CodeType { GlobalCode, EvalCode, FunctionCode };
-
- typedef Vector<ExecState*, 16> ExecStateStack;
-
- // Represents the current state of script execution.
- // Passed as the first argument to most functions.
- class ExecState : Noncopyable {
- public:
- // Global object that was in scope when the current script started executing.
- JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; }
-
- // Global object that was in scope when the current body of code was defined.
- JSGlobalObject* lexicalGlobalObject() const;
-
- void setException(JSValue* e) { m_exception = e; }
- void clearException() { m_exception = 0; }
- JSValue* exception() const { return m_exception; }
- JSValue** exceptionSlot() { return &m_exception; }
- bool hadException() const { return !!m_exception; }
-
- const ScopeChain& scopeChain() const { return m_scopeChain; }
- void pushScope(JSObject* s) { m_scopeChain.push(s); }
- void popScope() { m_scopeChain.pop(); }
- void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); }
-
- JSVariableObject* variableObject() const { return m_variableObject; }
- void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
-
- JSObject* thisValue() const { return m_thisValue; }
-
- ExecState* callingExecState() { return m_callingExec; }
-
- ActivationImp* activationObject() { return m_activation; }
- void setActivationObject(ActivationImp* a) { m_activation = a; }
- CodeType codeType() { return m_codeType; }
- ScopeNode* scopeNode() { return m_scopeNode; }
- FunctionImp* function() const { return m_function; }
- const List* arguments() const { return m_arguments; }
-
- LabelStack& seenLabels() { return m_labelStack; }
-
- void pushIteration() { m_iterationDepth++; }
- void popIteration() { m_iterationDepth--; }
- bool inIteration() const { return (m_iterationDepth > 0); }
-
- void pushSwitch() { m_switchDepth++; }
- void popSwitch() { m_switchDepth--; }
- bool inSwitch() const { return (m_switchDepth > 0); }
-
- // These pointers are used to avoid accessing global variables for these,
- // to avoid taking PIC branches in Mach-O binaries.
- const CommonIdentifiers& propertyNames() const { return *m_propertyNames; }
- const List& emptyList() const { return *m_emptyList; }
-
- LocalStorage& localStorage() { return *m_localStorage; }
- void setLocalStorage(LocalStorage* s) { m_localStorage = s; }
-
- // These are only valid right after calling execute().
- ComplType completionType() const { return m_completionType; }
- const Identifier& breakOrContinueTarget() const
- {
- ASSERT(m_completionType == Break || m_completionType == Continue);
- return *m_breakOrContinueTarget;
- }
-
- // Only for use in the implementation of execute().
- void setCompletionType(ComplType type)
- {
- ASSERT(type != Break);
- ASSERT(type != Continue);
- m_completionType = type;
- }
- JSValue* setNormalCompletion()
- {
- ASSERT(!hadException());
- m_completionType = Normal;
- return 0;
- }
- JSValue* setNormalCompletion(JSValue* value)
- {
- ASSERT(!hadException());
- m_completionType = Normal;
- return value;
- }
- JSValue* setBreakCompletion(const Identifier* target)
- {
- ASSERT(!hadException());
- m_completionType = Break;
- m_breakOrContinueTarget = target;
- return 0;
- }
- JSValue* setContinueCompletion(const Identifier* target)
- {
- ASSERT(!hadException());
- m_completionType = Continue;
- m_breakOrContinueTarget = target;
- return 0;
- }
- JSValue* setReturnValueCompletion(JSValue* returnValue)
- {
- ASSERT(!hadException());
- ASSERT(returnValue);
- m_completionType = ReturnValue;
- return returnValue;
- }
- JSValue* setThrowCompletion(JSValue* exception)
- {
- ASSERT(!hadException());
- ASSERT(exception);
- m_completionType = Throw;
- return exception;
- }
- JSValue* setInterruptedCompletion()
- {
- ASSERT(!hadException());
- m_completionType = Interrupted;
- return 0;
- }
- JSValue* setInterruptedCompletion(JSValue* returnValue)
- {
- ASSERT(!hadException());
- ASSERT(returnValue);
- m_completionType = Interrupted;
- return returnValue;
- }
-
- static void markActiveExecStates();
- static ExecStateStack& activeExecStates();
-
- protected:
- ExecState(JSGlobalObject*);
- ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
- ExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState);
- ExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*,
- ExecState* callingExecState, FunctionImp*, const List& args);
- ~ExecState();
-
- // ExecStates are always stack-allocated, and the garbage collector
- // marks the stack, so we don't need to protect the objects below from GC.
-
- JSGlobalObject* m_globalObject;
- JSValue* m_exception;
- CommonIdentifiers* m_propertyNames;
- const List* m_emptyList;
-
- ExecState* m_callingExec;
-
- ScopeNode* m_scopeNode;
-
- FunctionImp* m_function;
- const List* m_arguments;
- ActivationImp* m_activation;
- LocalStorage* m_localStorage;
-
- ScopeChain m_scopeChain;
- JSVariableObject* m_variableObject;
- JSObject* m_thisValue;
-
- LabelStack m_labelStack;
- int m_iterationDepth;
- int m_switchDepth;
- CodeType m_codeType;
-
- ComplType m_completionType;
- const Identifier* m_breakOrContinueTarget;
- };
-
- class GlobalExecState : public ExecState {
- public:
- GlobalExecState(JSGlobalObject*);
- ~GlobalExecState();
- };
-
- class InterpreterExecState : public ExecState {
- public:
- InterpreterExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
- ~InterpreterExecState();
- };
-
- class EvalExecState : public ExecState {
- public:
- EvalExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState);
- ~EvalExecState();
- };
-
- class FunctionExecState : public ExecState {
- public:
- FunctionExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*,
- ExecState* callingExecState, FunctionImp*, const List& args);
- ~FunctionExecState();
- };
-
-} // namespace KJS
-
-#endif // ExecState_h
+++ /dev/null
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSGlobalObject.h"
-
-#include "Activation.h"
-#include "array_object.h"
-#include "bool_object.h"
-#include "date_object.h"
-#include "debugger.h"
-#include "error_object.h"
-#include "function_object.h"
-#include "math_object.h"
-#include "number_object.h"
-#include "object_object.h"
-#include "regexp_object.h"
-#include "SavedBuiltins.h"
-#include "string_object.h"
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(WIN_OS)
-#include <windows.h>
-#endif
-
-#if PLATFORM(QT)
-#include <QDateTime>
-#endif
-
-namespace KJS {
-
-// Default number of ticks before a timeout check should be done.
-static const int initialTickCountThreshold = 255;
-
-// Preferred number of milliseconds between each timeout check
-static const int preferredScriptCheckTimeInterval = 1000;
-
-static inline void markIfNeeded(JSValue* v)
-{
- if (v && !v->marked())
- v->mark();
-}
-
-// Returns the current time in milliseconds
-// It doesn't matter what "current time" is here, just as long as
-// it's possible to measure the time difference correctly.
-static inline unsigned getCurrentTime()
-{
-#if HAVE(SYS_TIME_H)
- struct timeval tv;
- gettimeofday(&tv, 0);
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#elif PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- return t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
- return timeGetTime();
-#else
-#error Platform does not have getCurrentTime function
-#endif
-}
-
-JSGlobalObject* JSGlobalObject::s_head = 0;
-
-void JSGlobalObject::deleteActivationStack()
-{
- ActivationStackNode* prevNode = 0;
- for (ActivationStackNode* currentNode = d()->activations; currentNode; currentNode = prevNode) {
- prevNode = currentNode->prev;
- delete currentNode;
- }
-}
-
-JSGlobalObject::~JSGlobalObject()
-{
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (d()->debugger)
- d()->debugger->detach(this);
-
- d()->next->d()->prev = d()->prev;
- d()->prev->d()->next = d()->next;
- s_head = d()->next;
- if (s_head == this)
- s_head = 0;
-
- deleteActivationStack();
-
- delete d();
-}
-
-void JSGlobalObject::init()
-{
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (s_head) {
- d()->prev = s_head;
- d()->next = s_head->d()->next;
- s_head->d()->next->d()->prev = this;
- s_head->d()->next = this;
- } else
- s_head = d()->next = d()->prev = this;
-
- d()->compatMode = NativeMode;
-
- resetTimeoutCheck();
- d()->timeoutTime = 0;
- d()->timeoutCheckCount = 0;
-
- d()->recursion = 0;
- d()->debugger = 0;
-
- ActivationStackNode* newStackNode = new ActivationStackNode;
- newStackNode->prev = 0;
- d()->activations = newStackNode;
- d()->activationCount = 0;
-
- reset(prototype());
-}
-
-bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (symbolTableGet(propertyName, slot))
- return true;
- return JSVariableObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
-{
- if (symbolTablePut(propertyName, value, !(attr & ~DontDelete)))
- return;
- return JSVariableObject::put(exec, propertyName, value, attr);
-}
-
-static inline JSObject* lastInPrototypeChain(JSObject* object)
-{
- JSObject* o = object;
- while (o->prototype()->isObject())
- o = static_cast<JSObject*>(o->prototype());
- return o;
-}
-
-void JSGlobalObject::reset(JSValue* prototype)
-{
- // Clear before inititalizing, to avoid calling mark() on stale pointers --
- // which would be wasteful -- or uninitialized pointers -- which would be
- // dangerous. (The allocations below may cause a GC.)
-
- _prop.clear();
- localStorage().clear();
- symbolTable().clear();
-
- // Prototypes
- d()->functionPrototype = 0;
- d()->objectPrototype = 0;
-
- d()->arrayPrototype = 0;
- d()->stringPrototype = 0;
- d()->booleanPrototype = 0;
- d()->numberPrototype = 0;
- d()->datePrototype = 0;
- d()->regExpPrototype = 0;
- d()->errorPrototype = 0;
-
- d()->evalErrorPrototype = 0;
- d()->rangeErrorPrototype = 0;
- d()->referenceErrorPrototype = 0;
- d()->syntaxErrorPrototype = 0;
- d()->typeErrorPrototype = 0;
- d()->URIErrorPrototype = 0;
-
- // Constructors
- d()->objectConstructor = 0;
- d()->functionConstructor = 0;
- d()->arrayConstructor = 0;
- d()->stringConstructor = 0;
- d()->booleanConstructor = 0;
- d()->numberConstructor = 0;
- d()->dateConstructor = 0;
- d()->regExpConstructor = 0;
- d()->errorConstructor = 0;
-
- d()->evalErrorConstructor = 0;
- d()->rangeErrorConstructor = 0;
- d()->referenceErrorConstructor = 0;
- d()->syntaxErrorConstructor = 0;
- d()->typeErrorConstructor = 0;
- d()->URIErrorConstructor = 0;
-
- ExecState* exec = &d()->globalExec;
-
- // Prototypes
- d()->functionPrototype = new FunctionPrototype(exec);
- d()->objectPrototype = new ObjectPrototype(exec, d()->functionPrototype);
- d()->functionPrototype->setPrototype(d()->objectPrototype);
-
- d()->arrayPrototype = new ArrayPrototype(exec, d()->objectPrototype);
- d()->stringPrototype = new StringPrototype(exec, d()->objectPrototype);
- d()->booleanPrototype = new BooleanPrototype(exec, d()->objectPrototype, d()->functionPrototype);
- d()->numberPrototype = new NumberPrototype(exec, d()->objectPrototype, d()->functionPrototype);
- d()->datePrototype = new DatePrototype(exec, d()->objectPrototype);
- d()->regExpPrototype = new RegExpPrototype(exec, d()->objectPrototype, d()->functionPrototype);
- d()->errorPrototype = new ErrorPrototype(exec, d()->objectPrototype, d()->functionPrototype);
-
- d()->evalErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "EvalError", "EvalError");
- d()->rangeErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "RangeError", "RangeError");
- d()->referenceErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "ReferenceError", "ReferenceError");
- d()->syntaxErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "SyntaxError", "SyntaxError");
- d()->typeErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "TypeError", "TypeError");
- d()->URIErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "URIError", "URIError");
-
- // Constructors
- d()->objectConstructor = new ObjectObjectImp(exec, d()->objectPrototype, d()->functionPrototype);
- d()->functionConstructor = new FunctionObjectImp(exec, d()->functionPrototype);
- d()->arrayConstructor = new ArrayObjectImp(exec, d()->functionPrototype, d()->arrayPrototype);
- d()->stringConstructor = new StringObjectImp(exec, d()->functionPrototype, d()->stringPrototype);
- d()->booleanConstructor = new BooleanObjectImp(exec, d()->functionPrototype, d()->booleanPrototype);
- d()->numberConstructor = new NumberObjectImp(exec, d()->functionPrototype, d()->numberPrototype);
- d()->dateConstructor = new DateObjectImp(exec, d()->functionPrototype, d()->datePrototype);
- d()->regExpConstructor = new RegExpObjectImp(exec, d()->functionPrototype, d()->regExpPrototype);
- d()->errorConstructor = new ErrorObjectImp(exec, d()->functionPrototype, d()->errorPrototype);
-
- d()->evalErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->evalErrorPrototype);
- d()->rangeErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->rangeErrorPrototype);
- d()->referenceErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->referenceErrorPrototype);
- d()->syntaxErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->syntaxErrorPrototype);
- d()->typeErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->typeErrorPrototype);
- d()->URIErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->URIErrorPrototype);
-
- d()->functionPrototype->putDirect(exec->propertyNames().constructor, d()->functionConstructor, DontEnum);
-
- d()->objectPrototype->putDirect(exec->propertyNames().constructor, d()->objectConstructor, DontEnum | DontDelete | ReadOnly);
- d()->functionPrototype->putDirect(exec->propertyNames().constructor, d()->functionConstructor, DontEnum | DontDelete | ReadOnly);
- d()->arrayPrototype->putDirect(exec->propertyNames().constructor, d()->arrayConstructor, DontEnum | DontDelete | ReadOnly);
- d()->booleanPrototype->putDirect(exec->propertyNames().constructor, d()->booleanConstructor, DontEnum | DontDelete | ReadOnly);
- d()->stringPrototype->putDirect(exec->propertyNames().constructor, d()->stringConstructor, DontEnum | DontDelete | ReadOnly);
- d()->numberPrototype->putDirect(exec->propertyNames().constructor, d()->numberConstructor, DontEnum | DontDelete | ReadOnly);
- d()->datePrototype->putDirect(exec->propertyNames().constructor, d()->dateConstructor, DontEnum | DontDelete | ReadOnly);
- d()->regExpPrototype->putDirect(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum | DontDelete | ReadOnly);
- d()->errorPrototype->putDirect(exec->propertyNames().constructor, d()->errorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->referenceErrorPrototype->putDirect(exec->propertyNames().constructor, d()->referenceErrorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->syntaxErrorPrototype->putDirect(exec->propertyNames().constructor, d()->syntaxErrorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->typeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->typeErrorConstructor, DontEnum | DontDelete | ReadOnly);
- d()->URIErrorPrototype->putDirect(exec->propertyNames().constructor, d()->URIErrorConstructor, DontEnum | DontDelete | ReadOnly);
-
- // Set global constructors
-
- // FIXME: kjs_window.cpp checks Internal/DontEnum as a performance hack, to
- // see that these values can be put directly without a check for override
- // properties.
-
- // FIXME: These properties should be handled by a static hash table.
-
- putDirect("Object", d()->objectConstructor, DontEnum);
- putDirect("Function", d()->functionConstructor, DontEnum);
- putDirect("Array", d()->arrayConstructor, DontEnum);
- putDirect("Boolean", d()->booleanConstructor, DontEnum);
- putDirect("String", d()->stringConstructor, DontEnum);
- putDirect("Number", d()->numberConstructor, DontEnum);
- putDirect("Date", d()->dateConstructor, DontEnum);
- putDirect("RegExp", d()->regExpConstructor, DontEnum);
- putDirect("Error", d()->errorConstructor, DontEnum);
- putDirect("EvalError", d()->evalErrorConstructor, Internal);
- putDirect("RangeError", d()->rangeErrorConstructor, Internal);
- putDirect("ReferenceError", d()->referenceErrorConstructor, Internal);
- putDirect("SyntaxError", d()->syntaxErrorConstructor, Internal);
- putDirect("TypeError", d()->typeErrorConstructor, Internal);
- putDirect("URIError", d()->URIErrorConstructor, Internal);
-
- // Set global values.
-
- putDirect("Math", new MathObjectImp(exec, d()->objectPrototype), DontEnum);
-
- putDirect("NaN", jsNaN(), DontEnum | DontDelete);
- putDirect("Infinity", jsNumber(Inf), DontEnum | DontDelete);
- putDirect("undefined", jsUndefined(), DontEnum | DontDelete);
-
- // Set global functions.
-
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "eval", globalFuncEval), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 2, "parseInt", globalFuncParseInt), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "parseFloat", globalFuncParseFloat), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isNaN", globalFuncIsNaN), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isFinite", globalFuncIsFinite), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "escape", globalFuncEscape), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "unescape", globalFuncUnescape), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURI", globalFuncDecodeURI), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURIComponent", globalFuncDecodeURIComponent), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURI", globalFuncEncodeURI), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURIComponent", globalFuncEncodeURIComponent), DontEnum);
-#ifndef NDEBUG
- putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "kjsprint", globalFuncKJSPrint), DontEnum);
-#endif
-
- // Set prototype, and also insert the object prototype at the end of the chain.
-
- setPrototype(prototype);
- lastInPrototypeChain(this)->setPrototype(d()->objectPrototype);
-}
-
-void JSGlobalObject::startTimeoutCheck()
-{
- if (!d()->timeoutCheckCount)
- resetTimeoutCheck();
-
- ++d()->timeoutCheckCount;
-}
-
-void JSGlobalObject::stopTimeoutCheck()
-{
- --d()->timeoutCheckCount;
-}
-
-void JSGlobalObject::resetTimeoutCheck()
-{
- d()->tickCount = 0;
- d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold;
- d()->timeAtLastCheckTimeout = 0;
- d()->timeExecuting = 0;
-}
-
-bool JSGlobalObject::checkTimeout()
-{
- d()->tickCount = 0;
-
- unsigned currentTime = getCurrentTime();
-
- if (!d()->timeAtLastCheckTimeout) {
- // Suspicious amount of looping in a script -- start timing it
- d()->timeAtLastCheckTimeout = currentTime;
- return false;
- }
-
- unsigned timeDiff = currentTime - d()->timeAtLastCheckTimeout;
-
- if (timeDiff == 0)
- timeDiff = 1;
-
- d()->timeExecuting += timeDiff;
- d()->timeAtLastCheckTimeout = currentTime;
-
- // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
- // preferredScriptCheckTimeInterval
- d()->ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * d()->ticksUntilNextTimeoutCheck;
-
- // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
- // preferred script check time interval.
- if (d()->ticksUntilNextTimeoutCheck == 0)
- d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold;
-
- if (shouldInterruptScriptBeforeTimeout())
- return true;
-
- if (d()->timeoutTime && d()->timeExecuting > d()->timeoutTime) {
- if (shouldInterruptScript())
- return true;
-
- resetTimeoutCheck();
- }
-
- return false;
-}
-
-void JSGlobalObject::saveBuiltins(SavedBuiltins& builtins) const
-{
- if (!builtins._internal)
- builtins._internal = new SavedBuiltinsInternal;
-
- builtins._internal->objectConstructor = d()->objectConstructor;
- builtins._internal->functionConstructor = d()->functionConstructor;
- builtins._internal->arrayConstructor = d()->arrayConstructor;
- builtins._internal->booleanConstructor = d()->booleanConstructor;
- builtins._internal->stringConstructor = d()->stringConstructor;
- builtins._internal->numberConstructor = d()->numberConstructor;
- builtins._internal->dateConstructor = d()->dateConstructor;
- builtins._internal->regExpConstructor = d()->regExpConstructor;
- builtins._internal->errorConstructor = d()->errorConstructor;
- builtins._internal->evalErrorConstructor = d()->evalErrorConstructor;
- builtins._internal->rangeErrorConstructor = d()->rangeErrorConstructor;
- builtins._internal->referenceErrorConstructor = d()->referenceErrorConstructor;
- builtins._internal->syntaxErrorConstructor = d()->syntaxErrorConstructor;
- builtins._internal->typeErrorConstructor = d()->typeErrorConstructor;
- builtins._internal->URIErrorConstructor = d()->URIErrorConstructor;
-
- builtins._internal->objectPrototype = d()->objectPrototype;
- builtins._internal->functionPrototype = d()->functionPrototype;
- builtins._internal->arrayPrototype = d()->arrayPrototype;
- builtins._internal->booleanPrototype = d()->booleanPrototype;
- builtins._internal->stringPrototype = d()->stringPrototype;
- builtins._internal->numberPrototype = d()->numberPrototype;
- builtins._internal->datePrototype = d()->datePrototype;
- builtins._internal->regExpPrototype = d()->regExpPrototype;
- builtins._internal->errorPrototype = d()->errorPrototype;
- builtins._internal->evalErrorPrototype = d()->evalErrorPrototype;
- builtins._internal->rangeErrorPrototype = d()->rangeErrorPrototype;
- builtins._internal->referenceErrorPrototype = d()->referenceErrorPrototype;
- builtins._internal->syntaxErrorPrototype = d()->syntaxErrorPrototype;
- builtins._internal->typeErrorPrototype = d()->typeErrorPrototype;
- builtins._internal->URIErrorPrototype = d()->URIErrorPrototype;
-}
-
-void JSGlobalObject::restoreBuiltins(const SavedBuiltins& builtins)
-{
- if (!builtins._internal)
- return;
-
- d()->objectConstructor = builtins._internal->objectConstructor;
- d()->functionConstructor = builtins._internal->functionConstructor;
- d()->arrayConstructor = builtins._internal->arrayConstructor;
- d()->booleanConstructor = builtins._internal->booleanConstructor;
- d()->stringConstructor = builtins._internal->stringConstructor;
- d()->numberConstructor = builtins._internal->numberConstructor;
- d()->dateConstructor = builtins._internal->dateConstructor;
- d()->regExpConstructor = builtins._internal->regExpConstructor;
- d()->errorConstructor = builtins._internal->errorConstructor;
- d()->evalErrorConstructor = builtins._internal->evalErrorConstructor;
- d()->rangeErrorConstructor = builtins._internal->rangeErrorConstructor;
- d()->referenceErrorConstructor = builtins._internal->referenceErrorConstructor;
- d()->syntaxErrorConstructor = builtins._internal->syntaxErrorConstructor;
- d()->typeErrorConstructor = builtins._internal->typeErrorConstructor;
- d()->URIErrorConstructor = builtins._internal->URIErrorConstructor;
-
- d()->objectPrototype = builtins._internal->objectPrototype;
- d()->functionPrototype = builtins._internal->functionPrototype;
- d()->arrayPrototype = builtins._internal->arrayPrototype;
- d()->booleanPrototype = builtins._internal->booleanPrototype;
- d()->stringPrototype = builtins._internal->stringPrototype;
- d()->numberPrototype = builtins._internal->numberPrototype;
- d()->datePrototype = builtins._internal->datePrototype;
- d()->regExpPrototype = builtins._internal->regExpPrototype;
- d()->errorPrototype = builtins._internal->errorPrototype;
- d()->evalErrorPrototype = builtins._internal->evalErrorPrototype;
- d()->rangeErrorPrototype = builtins._internal->rangeErrorPrototype;
- d()->referenceErrorPrototype = builtins._internal->referenceErrorPrototype;
- d()->syntaxErrorPrototype = builtins._internal->syntaxErrorPrototype;
- d()->typeErrorPrototype = builtins._internal->typeErrorPrototype;
- d()->URIErrorPrototype = builtins._internal->URIErrorPrototype;
-}
-
-void JSGlobalObject::mark()
-{
- JSVariableObject::mark();
-
- markIfNeeded(d()->globalExec.exception());
-
- markIfNeeded(d()->objectConstructor);
- markIfNeeded(d()->functionConstructor);
- markIfNeeded(d()->arrayConstructor);
- markIfNeeded(d()->booleanConstructor);
- markIfNeeded(d()->stringConstructor);
- markIfNeeded(d()->numberConstructor);
- markIfNeeded(d()->dateConstructor);
- markIfNeeded(d()->regExpConstructor);
- markIfNeeded(d()->errorConstructor);
- markIfNeeded(d()->evalErrorConstructor);
- markIfNeeded(d()->rangeErrorConstructor);
- markIfNeeded(d()->referenceErrorConstructor);
- markIfNeeded(d()->syntaxErrorConstructor);
- markIfNeeded(d()->typeErrorConstructor);
- markIfNeeded(d()->URIErrorConstructor);
-
- markIfNeeded(d()->objectPrototype);
- markIfNeeded(d()->functionPrototype);
- markIfNeeded(d()->arrayPrototype);
- markIfNeeded(d()->booleanPrototype);
- markIfNeeded(d()->stringPrototype);
- markIfNeeded(d()->numberPrototype);
- markIfNeeded(d()->datePrototype);
- markIfNeeded(d()->regExpPrototype);
- markIfNeeded(d()->errorPrototype);
- markIfNeeded(d()->evalErrorPrototype);
- markIfNeeded(d()->rangeErrorPrototype);
- markIfNeeded(d()->referenceErrorPrototype);
- markIfNeeded(d()->syntaxErrorPrototype);
- markIfNeeded(d()->typeErrorPrototype);
- markIfNeeded(d()->URIErrorPrototype);
-}
-
-ExecState* JSGlobalObject::globalExec()
-{
- return &d()->globalExec;
-}
-
-ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
-{
- if (d()->activationCount == activationStackNodeSize) {
- ActivationStackNode* newNode = new ActivationStackNode;
- newNode->prev = d()->activations;
- d()->activations = newNode;
- d()->activationCount = 0;
- }
-
- StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
- stackEntry->activationStorage.init(exec);
- return &stackEntry->activationStorage;
-}
-
-inline void JSGlobalObject::checkActivationCount()
-{
- if (!d()->activationCount) {
- ActivationStackNode* prev = d()->activations->prev;
- ASSERT(prev);
- delete d()->activations;
- d()->activations = prev;
- d()->activationCount = activationStackNodeSize;
- }
-}
-
-void JSGlobalObject::popActivation()
-{
- checkActivationCount();
- d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0);
-}
-
-void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic)
-{
- ActivationImp* oldActivation = exec->activationObject();
- if (!oldActivation || !oldActivation->isOnStack())
- return;
-
- ASSERT(exec->codeType() == FunctionCode);
- ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic);
-
- if (!leaveRelic) {
- checkActivationCount();
- d()->activationCount--;
- }
-
- oldActivation->d()->localStorage.shrink(0);
-
- exec->setActivationObject(newActivation);
- exec->setVariableObject(newActivation);
- exec->setLocalStorage(&newActivation->localStorage());
- exec->replaceScopeChainTop(newActivation);
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_GlobalObject_h
-#define KJS_GlobalObject_h
-
-#include "JSVariableObject.h"
-
-namespace KJS {
-
- class ActivationImp;
- class ArrayObjectImp;
- class ArrayPrototype;
- class BooleanObjectImp;
- class BooleanPrototype;
- class DateObjectImp;
- class DatePrototype;
- class Debugger;
- class ErrorObjectImp;
- class ErrorPrototype;
- class EvalError;
- class EvalErrorPrototype;
- class FunctionObjectImp;
- class FunctionPrototype;
- class JSGlobalObject;
- class NativeErrorImp;
- class NativeErrorPrototype;
- class NumberObjectImp;
- class NumberPrototype;
- class ObjectObjectImp;
- class ObjectPrototype;
- class RangeError;
- class RangeErrorPrototype;
- class ReferenceError;
- class ReferenceError;
- class ReferenceErrorPrototype;
- class RegExpObjectImp;
- class RegExpPrototype;
- class RuntimeMethod;
- class SavedBuiltins;
- class ScopeChain;
- class StringObjectImp;
- class StringPrototype;
- class SyntaxErrorPrototype;
- class TypeError;
- class TypeErrorPrototype;
- class UriError;
- class UriErrorPrototype;
- struct ActivationStackNode;
-
- enum CompatMode { NativeMode, IECompat, NetscapeCompat };
-
- class JSGlobalObject : public JSVariableObject {
- protected:
- using JSVariableObject::JSVariableObjectData;
-
- struct JSGlobalObjectData : public JSVariableObjectData {
- JSGlobalObjectData(JSGlobalObject* globalObject)
- : JSVariableObjectData(&inlineSymbolTable)
- , globalExec(globalObject)
- {
- }
-
- JSGlobalObject* next;
- JSGlobalObject* prev;
-
- Debugger* debugger;
- CompatMode compatMode;
-
- GlobalExecState globalExec;
- int recursion;
-
- unsigned timeoutTime;
- unsigned timeAtLastCheckTimeout;
- unsigned timeExecuting;
- unsigned timeoutCheckCount;
- unsigned tickCount;
- unsigned ticksUntilNextTimeoutCheck;
-
- ObjectObjectImp* objectConstructor;
- FunctionObjectImp* functionConstructor;
- ArrayObjectImp* arrayConstructor;
- BooleanObjectImp* booleanConstructor;
- StringObjectImp* stringConstructor;
- NumberObjectImp* numberConstructor;
- DateObjectImp* dateConstructor;
- RegExpObjectImp* regExpConstructor;
- ErrorObjectImp* errorConstructor;
- NativeErrorImp* evalErrorConstructor;
- NativeErrorImp* rangeErrorConstructor;
- NativeErrorImp* referenceErrorConstructor;
- NativeErrorImp* syntaxErrorConstructor;
- NativeErrorImp* typeErrorConstructor;
- NativeErrorImp* URIErrorConstructor;
-
- ObjectPrototype* objectPrototype;
- FunctionPrototype* functionPrototype;
- ArrayPrototype* arrayPrototype;
- BooleanPrototype* booleanPrototype;
- StringPrototype* stringPrototype;
- NumberPrototype* numberPrototype;
- DatePrototype* datePrototype;
- RegExpPrototype* regExpPrototype;
- ErrorPrototype* errorPrototype;
- NativeErrorPrototype* evalErrorPrototype;
- NativeErrorPrototype* rangeErrorPrototype;
- NativeErrorPrototype* referenceErrorPrototype;
- NativeErrorPrototype* syntaxErrorPrototype;
- NativeErrorPrototype* typeErrorPrototype;
- NativeErrorPrototype* URIErrorPrototype;
-
- SymbolTable inlineSymbolTable;
-
- ActivationStackNode* activations;
- size_t activationCount;
- };
-
- public:
- JSGlobalObject()
- : JSVariableObject(new JSGlobalObjectData(this))
- {
- init();
- }
-
- protected:
- JSGlobalObject(JSValue* proto)
- : JSVariableObject(proto, new JSGlobalObjectData(this))
- {
- init();
- }
-
- public:
- virtual ~JSGlobalObject();
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValue*, int attr = None);
-
- // Linked list of all global objects.
- static JSGlobalObject* head() { return s_head; }
- JSGlobalObject* next() { return d()->next; }
-
- // Resets the global object to contain only built-in properties, sets
- // the global object's prototype to "prototype," then adds the
- // default object prototype to the tail of the global object's
- // prototype chain.
- void reset(JSValue* prototype);
-
- // The following accessors return pristine values, even if a script
- // replaces the global object's associated property.
-
- ObjectObjectImp* objectConstructor() const { return d()->objectConstructor; }
- FunctionObjectImp* functionConstructor() const { return d()->functionConstructor; }
- ArrayObjectImp* arrayConstructor() const { return d()->arrayConstructor; }
- BooleanObjectImp* booleanConstructor() const { return d()->booleanConstructor; }
- StringObjectImp* stringConstructor() const{ return d()->stringConstructor; }
- NumberObjectImp* numberConstructor() const{ return d()->numberConstructor; }
- DateObjectImp* dateConstructor() const{ return d()->dateConstructor; }
- RegExpObjectImp* regExpConstructor() const { return d()->regExpConstructor; }
- ErrorObjectImp* errorConstructor() const { return d()->errorConstructor; }
- NativeErrorImp* evalErrorConstructor() const { return d()->evalErrorConstructor; }
- NativeErrorImp* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
- NativeErrorImp* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
- NativeErrorImp* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
- NativeErrorImp* typeErrorConstructor() const { return d()->typeErrorConstructor; }
- NativeErrorImp* URIErrorConstructor() const { return d()->URIErrorConstructor; }
-
- ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
- FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
- ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
- BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
- StringPrototype* stringPrototype() const { return d()->stringPrototype; }
- NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
- DatePrototype* datePrototype() const { return d()->datePrototype; }
- RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
- ErrorPrototype* errorPrototype() const { return d()->errorPrototype; }
- NativeErrorPrototype* evalErrorPrototype() const { return d()->evalErrorPrototype; }
- NativeErrorPrototype* rangeErrorPrototype() const { return d()->rangeErrorPrototype; }
- NativeErrorPrototype* referenceErrorPrototype() const { return d()->referenceErrorPrototype; }
- NativeErrorPrototype* syntaxErrorPrototype() const { return d()->syntaxErrorPrototype; }
- NativeErrorPrototype* typeErrorPrototype() const { return d()->typeErrorPrototype; }
- NativeErrorPrototype* URIErrorPrototype() const { return d()->URIErrorPrototype; }
-
- void saveBuiltins(SavedBuiltins&) const;
- void restoreBuiltins(const SavedBuiltins&);
-
- void setTimeoutTime(unsigned timeoutTime) { d()->timeoutTime = timeoutTime; }
- void startTimeoutCheck();
- void stopTimeoutCheck();
- bool timedOut();
-
- Debugger* debugger() const { return d()->debugger; }
- void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
-
- // FIXME: Let's just pick one compatible behavior and go with it.
- void setCompatMode(CompatMode mode) { d()->compatMode = mode; }
- CompatMode compatMode() const { return d()->compatMode; }
-
- int recursion() { return d()->recursion; }
- void incRecursion() { ++d()->recursion; }
- void decRecursion() { --d()->recursion; }
-
- virtual void mark();
-
- virtual bool isGlobalObject() const { return true; }
-
- virtual ExecState* globalExec();
-
- virtual bool shouldInterruptScriptBeforeTimeout() const { return false; }
- virtual bool shouldInterruptScript() const { return true; }
-
- virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
-
- ActivationImp* pushActivation(ExecState*);
- void popActivation();
- void tearOffActivation(ExecState*, bool markAsRelic = false);
-
- private:
- void init();
-
- JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
-
- bool checkTimeout();
- void resetTimeoutCheck();
-
- void deleteActivationStack();
- void checkActivationCount();
-
- static JSGlobalObject* s_head;
- };
-
- inline bool JSGlobalObject::timedOut()
- {
- d()->tickCount++;
-
- if (d()->tickCount != d()->ticksUntilNextTimeoutCheck)
- return false;
-
- return checkTimeout();
- }
-
-} // namespace KJS
-
-#endif // KJS_GlobalObject_h
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003-2006 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "JSImmediate.h"
-
-#include "JSGlobalObject.h"
-#include "bool_object.h"
-#include "number_object.h"
-#include "object.h"
-
-namespace KJS {
-
-JSObject *JSImmediate::toObject(const JSValue *v, ExecState *exec)
-{
- ASSERT(isImmediate(v));
- if (v == jsNull())
- return throwError(exec, TypeError, "Null value");
- else if (v == jsUndefined())
- return throwError(exec, TypeError, "Undefined value");
- else if (isBoolean(v)) {
- List args;
- args.append(const_cast<JSValue *>(v));
- return exec->lexicalGlobalObject()->booleanConstructor()->construct(exec, args);
- } else {
- ASSERT(isNumber(v));
- List args;
- args.append(const_cast<JSValue *>(v));
- return exec->lexicalGlobalObject()->numberConstructor()->construct(exec, args);
- }
-}
-
-UString JSImmediate::toString(const JSValue *v)
-{
- ASSERT(isImmediate(v));
-
- if (v == jsNull())
- return "null";
- else if (v == jsUndefined())
- return "undefined";
- else if (v == jsBoolean(true))
- return "true";
- else if (v == jsBoolean(false))
- return "false";
- else {
- ASSERT(isNumber(v));
- double d = toDouble(v);
- if (d == 0.0) // +0.0 or -0.0
- return "0";
- return UString::from(d);
- }
-}
-
-JSType JSImmediate::type(const JSValue *v)
-{
- ASSERT(isImmediate(v));
-
- uintptr_t tag = getTag(v);
- if (tag == UndefinedType)
- return v == jsUndefined() ? UndefinedType : NullType;
- return static_cast<JSType>(tag);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_JS_IMMEDIATE_H
-#define KJS_JS_IMMEDIATE_H
-
-#include "JSType.h"
-#include <wtf/Assertions.h>
-#include <wtf/AlwaysInline.h>
-#include <wtf/MathExtras.h>
-#include <limits>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-namespace KJS {
-
-class ExecState;
-class JSObject;
-class JSValue;
-class UString;
-
-/*
- * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
- * signed int masquerading as a pointer). The low two bits in a JSValue* are available
- * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
- *
- * For example, on a 32 bit system:
- *
- * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
- * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
- *
- * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
- * [ high 30 bits: signed int ] [ low 2 bits -- type tag ]
- *
- * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false
- * and undefined/null.
- *
- * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits
- * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has
- * to sort them out.
- */
-
-class JSImmediate {
-public:
- static ALWAYS_INLINE bool isImmediate(const JSValue* v)
- {
- return getTag(v) != 0;
- }
-
- static ALWAYS_INLINE bool isNumber(const JSValue* v)
- {
- return (getTag(v) == NumberType);
- }
-
- static ALWAYS_INLINE bool isBoolean(const JSValue* v)
- {
- return (getTag(v) == BooleanType);
- }
-
- // Since we have room for only 3 unique tags, null and undefined have to share.
- static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
- {
- return (getTag(v) == UndefinedType);
- }
-
- static JSValue* from(char);
- static JSValue* from(signed char);
- static JSValue* from(unsigned char);
- static JSValue* from(short);
- static JSValue* from(unsigned short);
- static JSValue* from(int);
- static JSValue* from(unsigned);
- static JSValue* from(long);
- static JSValue* from(unsigned long);
- static JSValue* from(long long);
- static JSValue* from(unsigned long long);
- static JSValue* from(double);
-
- static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
- {
- return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
- }
-
- static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
- {
- ASSERT(areBothImmediateNumbers(v1, v2));
- return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
- }
-
- static double toDouble(const JSValue*);
- static bool toBoolean(const JSValue*);
- static JSObject* toObject(const JSValue*, ExecState*);
- static UString toString(const JSValue*);
- static JSType type(const JSValue*);
-
- static bool getUInt32(const JSValue*, uint32_t&);
- static bool getTruncatedInt32(const JSValue*, int32_t&);
- static bool getTruncatedUInt32(const JSValue*, uint32_t&);
-
- static int32_t getTruncatedInt32(const JSValue*);
-
- static JSValue* trueImmediate();
- static JSValue* falseImmediate();
- static JSValue* undefinedImmediate();
- static JSValue* nullImmediate();
-
-private:
- static const uintptr_t TagMask = 3; // type tags are 2 bits long
-
- // Immediate values are restricted to a 30 bit signed value.
- static const int minImmediateInt = -(1 << 29);
- static const int maxImmediateInt = (1 << 29) - 1;
- static const unsigned maxImmediateUInt = maxImmediateInt;
-
- static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
- {
- return reinterpret_cast<JSValue*>(bits | tag);
- }
-
- static ALWAYS_INLINE uintptr_t unTag(const JSValue* v)
- {
- return reinterpret_cast<uintptr_t>(v) & ~TagMask;
- }
-
- static ALWAYS_INLINE uintptr_t getTag(const JSValue* v)
- {
- return reinterpret_cast<uintptr_t>(v) & TagMask;
- }
-};
-
-ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
-ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
-ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
-ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
-
-ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
-{
- ASSERT(isImmediate(v));
- uintptr_t bits = unTag(v);
- return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(char i)
-{
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
-{
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
-{
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(short i)
-{
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
-{
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(int i)
-{
- if ((i < minImmediateInt) | (i > maxImmediateInt))
- return 0;
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
-{
- if (i > maxImmediateUInt)
- return 0;
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(long i)
-{
- if ((i < minImmediateInt) | (i > maxImmediateInt))
- return 0;
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
-{
- if (i > maxImmediateUInt)
- return 0;
- return tag(i << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
-{
- if ((i < minImmediateInt) | (i > maxImmediateInt))
- return 0;
- return tag(static_cast<uintptr_t>(i) << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
-{
- if (i > maxImmediateUInt)
- return 0;
- return tag(static_cast<uintptr_t>(i) << 2, NumberType);
-}
-
-ALWAYS_INLINE JSValue* JSImmediate::from(double d)
-{
- const int intVal = static_cast<int>(d);
-
- if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
- return 0;
-
- // Check for data loss from conversion to int.
- if ((intVal != d) || (!intVal && signbit(d)))
- return 0;
-
- return tag(intVal << 2, NumberType);
-}
-
-ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v)
-{
- ASSERT(isNumber(v));
- return static_cast<int32_t>(unTag(v)) >> 2;
-}
-
-ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
-{
- ASSERT(isImmediate(v));
- const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
- if (JSImmediate::getTag(v) == UndefinedType && i)
- return std::numeric_limits<double>::quiet_NaN();
- return i;
-}
-
-ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
-{
- const int32_t si = static_cast<int32_t>(unTag(v)) >> 2;
- i = si;
- return isNumber(v) & (si >= 0);
-}
-
-ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
-{
- i = static_cast<int32_t>(unTag(v)) >> 2;
- return isNumber(v);
-}
-
-ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
-{
- return getUInt32(v, i);
-}
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA
- *
- */
-
-#include "config.h"
-#include "JSLock.h"
-
-#include "collector.h"
-#if USE(MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
-namespace KJS {
-
-#if USE(MULTIPLE_THREADS)
-
-// Acquire this mutex before accessing lock-related data.
-static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
-
-// Thread-specific key that tells whether a thread holds the JSMutex.
-pthread_key_t didLockJSMutex;
-
-// Lock nesting count.
-static int JSLockCount;
-
-static void createDidLockJSMutex()
-{
- pthread_key_create(&didLockJSMutex, 0);
-}
-pthread_once_t createDidLockJSMutexOnce = PTHREAD_ONCE_INIT;
-
-void JSLock::lock()
-{
- pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
-
- if (!pthread_getspecific(didLockJSMutex)) {
- int result;
- result = pthread_mutex_lock(&JSMutex);
- ASSERT(!result);
- pthread_setspecific(didLockJSMutex, &didLockJSMutex);
- }
- ++JSLockCount;
-}
-
-void JSLock::unlock()
-{
- ASSERT(JSLockCount);
- ASSERT(!!pthread_getspecific(didLockJSMutex));
-
- --JSLockCount;
- if (!JSLockCount) {
- pthread_setspecific(didLockJSMutex, 0);
- int result;
- result = pthread_mutex_unlock(&JSMutex);
- ASSERT(!result);
- }
-}
-
-bool JSLock::currentThreadIsHoldingLock()
-{
- pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
- return !!pthread_getspecific(didLockJSMutex);
-}
-
-void JSLock::registerThread()
-{
- Collector::registerThread();
-}
-
-JSLock::DropAllLocks::DropAllLocks()
- : m_lockCount(0)
-{
- pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
-
- m_lockCount = !!pthread_getspecific(didLockJSMutex) ? JSLock::lockCount() : 0;
- for (int i = 0; i < m_lockCount; i++)
- JSLock::unlock();
-}
-
-JSLock::DropAllLocks::~DropAllLocks()
-{
- for (int i = 0; i < m_lockCount; i++)
- JSLock::lock();
- m_lockCount = 0;
-}
-
-#else
-
-// If threading support is off, set the lock count to a constant value of 1 so assertions
-// that the lock is held don't fail
-const int JSLockCount = 1;
-
-bool JSLock::currentThreadIsHoldingLock()
-{
- return true;
-}
-
-void JSLock::lock()
-{
-}
-
-void JSLock::unlock()
-{
-}
-
-void JSLock::registerThread()
-{
-}
-
-JSLock::DropAllLocks::DropAllLocks()
-{
-}
-
-JSLock::DropAllLocks::~DropAllLocks()
-{
-}
-
-#endif // USE(MULTIPLE_THREADS)
-
-int JSLock::lockCount()
-{
- return JSLockCount;
-}
-
-}
-
-
-#include "JSLockC.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static JSLock::DropAllLocks* sLockDropper = NULL;
-
-void JSLockDropAllLocks(void)
-{
- ASSERT(sLockDropper == NULL);
- sLockDropper = new JSLock::DropAllLocks();
-}
-
-void JSLockRecoverAllLocks(void)
-{
- ASSERT(sLockDropper != NULL);
- delete sLockDropper;
- sLockDropper = NULL;
-}
-
-static pthread_t javaScriptCollectionThread = 0;
-
-void JSSetJavaScriptCollectionThread (pthread_t thread)
-{
- javaScriptCollectionThread = thread;
-}
-
-pthread_t JSJavaScriptCollectionThread (void)
-{
- return javaScriptCollectionThread;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_JSLock_h
-#define KJS_JSLock_h
-
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
-
-namespace KJS {
-
- // To make it safe to use JavaScript on multiple threads, it is
- // important to lock before doing anything that allocates a
- // JavaScript data structure or that interacts with shared state
- // such as the protect count hash table. The simplest way to lock
- // is to create a local JSLock object in the scope where the lock
- // must be held. The lock is recursive so nesting is ok. The JSLock
- // object also acts as a convenience short-hand for running important
- // initialization routines.
-
- // To avoid deadlock, sometimes it is necessary to temporarily
- // release the lock. Since it is recursive you actually have to
- // release all locks held by your thread. This is safe to do if
- // you are executing code that doesn't require the lock, and you
- // reacquire the right number of locks at the end. You can do this
- // by constructing a locally scoped JSLock::DropAllLocks object. The
- // DropAllLocks object takes care to release the JSLock only if your
- // thread acquired it to begin with.
-
- class JSLock : Noncopyable {
- public:
- JSLock()
- {
- lock();
- registerThread();
- }
-
- ~JSLock()
- {
- unlock();
- }
-
- static void lock();
- static void unlock();
- static int lockCount();
- static bool currentThreadIsHoldingLock();
-
- static void registerThread();
-
- class DropAllLocks : Noncopyable {
- public:
- DropAllLocks();
- ~DropAllLocks();
-
- private:
- int m_lockCount;
- };
- };
-
-} // namespace
-
-#endif // KJS_JSLock_h
+++ /dev/null
-/*
- * Copyright (C) 2006, 2007, Apple Inc. All rights reserved.
- */
-
-#include <pthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void JSLockDropAllLocks(void);
-void JSLockRecoverAllLocks(void);
-void JSSetJavaScriptCollectionThread (pthread_t thread);
-pthread_t JSJavaScriptCollectionThread (void);
-
-#ifdef __cplusplus
-}
-#endif
-
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2006 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_JSTYPE_H
-#define KJS_JSTYPE_H
-
-namespace KJS {
-
-/**
- * Primitive types
- */
-enum JSType {
- UnspecifiedType = 0,
- UndefinedType = 1,
- BooleanType = 2,
- NumberType = 3,
- NullType = 4,
- StringType = 5,
- ObjectType = 6,
- GetterSetterType = 7
-};
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSVariableObject.h"
-
-#include "PropertyNameArray.h"
-#include "property_map.h"
-
-namespace KJS {
-
-UString::Rep* IdentifierRepHashTraits::nullRepPtr = &UString::Rep::null; // Didn't want to make a whole source file for just this.
-
-void JSVariableObject::saveLocalStorage(SavedProperties& p) const
-{
- ASSERT(d->symbolTable);
- ASSERT(static_cast<size_t>(d->symbolTable->size()) == d->localStorage.size());
-
- unsigned count = d->symbolTable->size();
-
- p.properties.clear();
- p.count = count;
-
- if (!count)
- return;
-
- p.properties.set(new SavedProperty[count]);
-
- SymbolTable::const_iterator end = d->symbolTable->end();
- for (SymbolTable::const_iterator it = d->symbolTable->begin(); it != end; ++it) {
- size_t i = it->second;
- const LocalStorageEntry& entry = d->localStorage[i];
- p.properties[i].init(it->first.get(), entry.value, entry.attributes);
- }
-}
-
-void JSVariableObject::restoreLocalStorage(const SavedProperties& p)
-{
- unsigned count = p.count;
- d->symbolTable->clear();
- d->localStorage.resize(count);
- SavedProperty* property = p.properties.get();
- for (size_t i = 0; i < count; ++i, ++property) {
- ASSERT(!d->symbolTable->contains(property->name()));
- LocalStorageEntry& entry = d->localStorage[i];
- d->symbolTable->set(property->name(), i);
- entry.value = property->value();
- entry.attributes = property->attributes();
- }
-}
-
-bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- if (symbolTable().contains(propertyName.ustring().rep()))
- return false;
-
- return JSObject::deleteProperty(exec, propertyName);
-}
-
-void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
-{
- SymbolTable::const_iterator::Keys end = symbolTable().end().keys();
- for (SymbolTable::const_iterator::Keys it = symbolTable().begin().keys(); it != end; ++it)
- propertyNames.add(Identifier(it->get()));
-
- JSObject::getPropertyNames(exec, propertyNames);
-}
-
-void JSVariableObject::mark()
-{
- JSObject::mark();
-
- size_t size = d->localStorage.size();
- for (size_t i = 0; i < size; ++i) {
- JSValue* value = d->localStorage[i].value;
- if (!value->marked())
- value->mark();
- }
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSVariableObject_h
-#define JSVariableObject_h
-
-#include "LocalStorage.h"
-#include "SymbolTable.h"
-#include "object.h"
-
-namespace KJS {
-
- class JSVariableObject : public JSObject {
- public:
- SymbolTable& symbolTable() { return *d->symbolTable; }
- LocalStorage& localStorage() { return d->localStorage; }
-
- void saveLocalStorage(SavedProperties&) const;
- void restoreLocalStorage(const SavedProperties&);
-
- virtual bool deleteProperty(ExecState*, const Identifier&);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual void mark();
-
- protected:
- // Subclasses of JSVariableObject can subclass this struct to add data
- // without increasing their own size (since there's a hard limit on the
- // size of a JSCell).
- struct JSVariableObjectData {
- JSVariableObjectData() { }
- JSVariableObjectData(SymbolTable* s)
- : symbolTable(s) // Subclass owns this pointer.
- {
- }
-
- LocalStorage localStorage; // Storage for variables in the symbol table.
- SymbolTable* symbolTable; // Maps name -> index in localStorage.
- };
-
- JSVariableObject() { }
-
- JSVariableObject(JSVariableObjectData* data)
- : d(data) // Subclass owns this pointer.
- {
- }
-
- JSVariableObject(JSValue* proto, JSVariableObjectData* data)
- : JSObject(proto)
- , d(data) // Subclass owns this pointer.
- {
- }
-
- bool symbolTableGet(const Identifier&, PropertySlot&);
- bool symbolTablePut(const Identifier&, JSValue*, bool checkReadOnly);
-
- JSVariableObjectData* d;
- };
-
- inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
- {
- size_t index = symbolTable().get(propertyName.ustring().rep());
- if (index != missingSymbolMarker()) {
-#ifndef NDEBUG
- // During initialization, the variable object needs to advertise that it has certain
- // properties, even if they're not ready for access yet. This check verifies that
- // no one tries to access such a property.
-
- // In a release build, we optimize this check away and just return an invalid pointer.
- // There's no harm in an invalid pointer, since no one dereferences it.
- if (index >= d->localStorage.size()) {
- slot.setUngettable(this);
- return true;
- }
-#endif
- slot.setValueSlot(this, &d->localStorage[index].value);
- return true;
- }
- return false;
- }
-
- inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value, bool checkReadOnly)
- {
- size_t index = symbolTable().get(propertyName.ustring().rep());
- if (index == missingSymbolMarker())
- return false;
- LocalStorageEntry& entry = d->localStorage[index];
- if (checkReadOnly && (entry.attributes & ReadOnly))
- return true;
- entry.value = value;
- return true;
- }
-
-} // namespace KJS
-
-#endif // JSVariableObject_h
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 2006 Maks Orlovich
- * Copyright (C) 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "JSWrapperObject.h"
-
-namespace KJS {
-
-void JSWrapperObject::mark()
-{
- JSObject::mark();
- if (m_internalValue && !m_internalValue->marked())
- m_internalValue->mark();
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Maks Orlovich
- * Copyright (C) 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_JSWrapperObject_h
-#define KJS_JSWrapperObject_h
-
-#include "object.h"
-
-namespace KJS {
-
- /**
- This class is used as a base for classes such as String,
- Number, Boolean and Date which which are wrappers for primitive
- types. These classes stores the internal value, which is the
- actual value represented by the wrapper objects.
- */
- class JSWrapperObject : public JSObject {
- public:
- JSWrapperObject(JSValue* proto);
-
- /**
- * Returns the internal value of the object. This is used for objects such
- * as String and Boolean which are wrappers for native types. The interal
- * value is the actual value represented by the wrapper objects.
- *
- * @see ECMA 8.6.2
- * @return The internal value of the object
- */
- JSValue* internalValue() const;
-
- /**
- * Sets the internal value of the object
- *
- * @see internalValue()
- *
- * @param v The new internal value
- */
- void setInternalValue(JSValue* v);
-
- virtual void mark();
-
- private:
- JSValue* m_internalValue;
- };
-
- inline JSWrapperObject::JSWrapperObject(JSValue* proto)
- : JSObject(proto)
- , m_internalValue(0)
- {
- }
-
- inline JSValue* JSWrapperObject::internalValue() const
- {
- return m_internalValue;
- }
-
- inline void JSWrapperObject::setInternalValue(JSValue* v)
- {
- ASSERT(v);
- m_internalValue = v;
- }
-
-} // namespace KJS
-
-#endif // KJS_JSWrapperObject_h
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_LABEL_STACK_H
-#define KJS_LABEL_STACK_H
-
-#include "identifier.h"
-#include <wtf/Noncopyable.h>
-
-namespace KJS {
- /**
- * @short The "label set" in Ecma-262 spec
- */
- class LabelStack : Noncopyable {
- public:
- LabelStack()
- : tos(0)
- {
- }
- ~LabelStack();
-
- /**
- * If id is not empty and is not in the stack already, puts it on top of
- * the stack and returns true, otherwise returns false
- */
- bool push(const Identifier &id);
- /**
- * Is the id in the stack?
- */
- bool contains(const Identifier &id) const;
- /**
- * Removes from the stack the last pushed id (what else?)
- */
- void pop();
-
- private:
- struct StackElem {
- Identifier id;
- StackElem *prev;
- };
-
- StackElem *tos;
- };
-
-inline LabelStack::~LabelStack()
-{
- StackElem *prev;
- for (StackElem *e = tos; e; e = prev) {
- prev = e->prev;
- delete e;
- }
-}
-
-inline void LabelStack::pop()
-{
- if (StackElem *e = tos) {
- tos = e->prev;
- delete e;
- }
-}
-
-}
-
-#endif // KJS_LABEL_STACK_H
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_LOCAL_STORAGE_H
-#define KJS_LOCAL_STORAGE_H
-
-#include <wtf/Forward.h>
-#include <wtf/VectorTraits.h>
-
-namespace KJS {
- class JSValue;
-
- struct LocalStorageEntry {
- LocalStorageEntry()
- {
- }
-
- LocalStorageEntry(JSValue* v, unsigned a)
- : value(v)
- , attributes(a)
- {
- }
-
- JSValue* value;
- unsigned attributes;
- };
-
- typedef Vector<LocalStorageEntry, 32> LocalStorage;
-}
-
-namespace WTF {
- template<> struct VectorTraits<KJS::LocalStorageEntry> : VectorTraitsBase<true, KJS::LocalStorageEntry> { };
-}
-
-#endif // KJS_LOCAL_STORAGE_H
+++ /dev/null
-/*
- * Copyright (C) 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef NodeInfo_h
-#define NodeInfo_h
-
-#include "nodes.h"
-#include "Parser.h"
-
-namespace KJS {
-
-template <typename T> struct NodeInfo {
- T m_node;
- ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
- ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
-};
-
-typedef NodeInfo<StatementNode*> StatementNodeInfo;
-typedef NodeInfo<CaseBlockNode*> CaseBlockNodeInfo;
-typedef NodeInfo<CaseClauseNode*> CaseClauseNodeInfo;
-typedef NodeInfo<SourceElements*> SourceElementsInfo;
-typedef NodeInfo<ClauseList> ClauseListInfo;
-typedef NodeInfo<ExpressionNode*> VarDeclListInfo;
-typedef NodeInfo<ConstDeclList> ConstDeclListInfo;
-
-} // namespace KJS
-
-#endif // NodeInfo_h
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2006, 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "Parser.h"
-
-#include "lexer.h"
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-extern int kjsyyparse();
-
-namespace KJS {
-
-void Parser::parse(int* errLine, UString* errMsg)
-{
- ASSERT(!m_sourceElements);
-
- if (errLine)
- *errLine = -1;
- if (errMsg)
- *errMsg = 0;
-
- Lexer& lexer = KJS::lexer();
- lexer.setCode(*m_source);
-
- int parseError = kjsyyparse();
- bool lexError = lexer.sawError();
- lexer.clear();
-
- ParserRefCounted::deleteNewObjects();
-
- if (parseError || lexError) {
- if (errLine)
- *errLine = lexer.lineNo();
- if (errMsg)
- *errMsg = "Parse error";
- m_sourceElements.clear();
- }
-}
-
-void Parser::reparse(FunctionBodyNode* functionBodyNode)
-{
- m_source = &functionBodyNode->source();
- parse(0, 0);
- ASSERT(m_sourceElements);
-
- functionBodyNode->setData(m_sourceElements.get(),
- m_varDeclarations ? &m_varDeclarations->data : 0,
- m_funcDeclarations ? &m_funcDeclarations->data : 0);
- functionBodyNode->setLoc(m_source->firstLine(), m_lastLine);
-
- m_source = 0;
- m_sourceElements = 0;
- m_varDeclarations = 0;
- m_funcDeclarations = 0;
-}
-
-void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
- ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, int lastLine)
-{
- m_sourceElements = sourceElements ? sourceElements : new SourceElements;
- m_varDeclarations = varStack;
- m_funcDeclarations = funcStack;
- m_lastLine = lastLine;
-}
-
-Parser& parser()
-{
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- static Parser& staticParser = *new Parser;
- return staticParser;
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2006, 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Parser_h
-#define Parser_h
-
-#include "SourceProvider.h"
-#include "nodes.h"
-#include <wtf/Forward.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace KJS {
-
- class FunctionBodyNode;
- class ProgramNode;
- class UString;
-
- struct UChar;
-
- template <typename T> struct ParserRefCountedData : ParserRefCounted {
- T data;
- };
-
- class Parser : Noncopyable {
- public:
- template <class ParsedNode> PassRefPtr<ParsedNode> parse(PassRefPtr<SourceProvider>, int* errLine = 0, UString* errMsg = 0);
- template <class ParsedNode> PassRefPtr<ParsedNode> parse(const SourceCode&, int* errLine = 0, UString* errMsg = 0);
-
- void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*,
- ParserRefCountedData<DeclarationStacks::FunctionStack>*, int lastLine);
-
- void reparse(FunctionBodyNode*);
-
- private:
- friend Parser& parser();
-
- void parse(int* errLine, UString* errMsg);
-
- const SourceCode* m_source;
- RefPtr<SourceElements> m_sourceElements;
- RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
- RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
- int m_lastLine;
- };
-
- Parser& parser(); // Returns the singleton JavaScript parser.
-
- template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(const SourceCode& source, int* errLine, UString* errMsg)
- {
- m_source = &source;
- parse(errLine, errMsg);
- RefPtr<ParsedNode> result;
- if (m_sourceElements) {
- result = ParsedNode::create(*m_source,
- m_sourceElements.get(),
- m_varDeclarations ? &m_varDeclarations->data : 0,
- m_funcDeclarations ? &m_funcDeclarations->data : 0);
- result->setLoc(m_source->firstLine(), m_lastLine);
- }
-
- m_source = 0;
- m_sourceElements = 0;
- m_varDeclarations = 0;
- m_funcDeclarations = 0;
- return result.release();
- }
-
-} // namespace KJS
-
-#endif // Parser_h
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "PropertyNameArray.h"
-
-namespace KJS {
-
-void PropertyNameArray::add(const Identifier& ident)
-{
- if (!m_set.add(ident.ustring().rep()).second)
- return;
-
- m_vector.append(ident);
-}
-
-void PropertyNameArray::swap(PropertyNameArray& other)
-{
- m_vector.swap(other.m_vector);
- m_set.swap(other.m_set);
-}
-
-
-} // namespace KJS
-
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2006 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_PROPERTY_NAME_ARRAY_H
-#define KJS_PROPERTY_NAME_ARRAY_H
-
-#include "identifier.h"
-
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-
- class PropertyNameArray {
- public:
- typedef Identifier ValueType;
- typedef Vector<Identifier>::const_iterator const_iterator;
-
- void add(const Identifier&);
- const_iterator begin() const { return m_vector.begin(); }
- const_iterator end() const { return m_vector.end(); }
- size_t size() const { return m_vector.size(); }
-
- Identifier& operator[](unsigned i) { return m_vector[i]; }
- const Identifier& operator[](unsigned i) const { return m_vector[i]; }
-
- void swap(PropertyNameArray&);
- private:
- typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
- IdentifierSet m_set;
- Vector<Identifier> m_vector;
- };
-
-
-} // namespace KJS
-
-
-#endif // KJS_PROPERTY_NAME_ARRAY_H
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SavedBuiltins_H
-#define SavedBuiltins_H
-
-#include "protect.h"
-#include "object_object.h"
-#include "string_object.h"
-#include "error_object.h"
-#include "regexp_object.h"
-#include "array_object.h"
-#include "bool_object.h"
-#include "date_object.h"
-#include "number_object.h"
-#include "math_object.h"
-
-namespace KJS {
-
-struct SavedBuiltinsInternal {
- ProtectedPtr<ObjectObjectImp> objectConstructor;
- ProtectedPtr<FunctionObjectImp> functionConstructor;
- ProtectedPtr<ArrayObjectImp> arrayConstructor;
- ProtectedPtr<BooleanObjectImp> booleanConstructor;
- ProtectedPtr<StringObjectImp> stringConstructor;
- ProtectedPtr<NumberObjectImp> numberConstructor;
- ProtectedPtr<DateObjectImp> dateConstructor;
- ProtectedPtr<RegExpObjectImp> regExpConstructor;
- ProtectedPtr<ErrorObjectImp> errorConstructor;
- ProtectedPtr<NativeErrorImp> evalErrorConstructor;
- ProtectedPtr<NativeErrorImp> rangeErrorConstructor;
- ProtectedPtr<NativeErrorImp> referenceErrorConstructor;
- ProtectedPtr<NativeErrorImp> syntaxErrorConstructor;
- ProtectedPtr<NativeErrorImp> typeErrorConstructor;
- ProtectedPtr<NativeErrorImp> URIErrorConstructor;
-
- ProtectedPtr<ObjectPrototype> objectPrototype;
- ProtectedPtr<FunctionPrototype> functionPrototype;
- ProtectedPtr<ArrayPrototype> arrayPrototype;
- ProtectedPtr<BooleanPrototype> booleanPrototype;
- ProtectedPtr<StringPrototype> stringPrototype;
- ProtectedPtr<NumberPrototype> numberPrototype;
- ProtectedPtr<DatePrototype> datePrototype;
- ProtectedPtr<RegExpPrototype> regExpPrototype;
- ProtectedPtr<ErrorPrototype> errorPrototype;
- ProtectedPtr<NativeErrorPrototype> evalErrorPrototype;
- ProtectedPtr<NativeErrorPrototype> rangeErrorPrototype;
- ProtectedPtr<NativeErrorPrototype> referenceErrorPrototype;
- ProtectedPtr<NativeErrorPrototype> syntaxErrorPrototype;
- ProtectedPtr<NativeErrorPrototype> typeErrorPrototype;
- ProtectedPtr<NativeErrorPrototype> URIErrorPrototype;
-};
-
-class SavedBuiltins {
- friend class JSGlobalObject;
-public:
- SavedBuiltins()
- : _internal(0)
- {
- }
-
- ~SavedBuiltins()
- {
- delete _internal;
- }
-
-private:
- SavedBuiltinsInternal* _internal;
-};
-
-} // namespace
-
-#endif // SavedBuiltins_H
+++ /dev/null
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SourceCode_h
-#define SourceCode_h
-
-#include "SourceProvider.h"
-#include <wtf/RefPtr.h>
-
-namespace KJS {
-
- class SourceCode {
- public:
- SourceCode()
- : m_startChar(0)
- , m_endChar(0)
- , m_firstLine(0)
- {
- }
-
- SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 0)
- : m_provider(provider)
- , m_startChar(0)
- , m_endChar(m_provider->length())
- , m_firstLine(firstLine + 1)
- {
- }
-
- SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine)
- : m_provider(provider)
- , m_startChar(start)
- , m_endChar(end)
- , m_firstLine(firstLine + 1)
- {
- }
-
- UString toString() const
- {
- if (!m_provider)
- return UString();
- return m_provider->getRange(m_startChar, m_endChar);
- }
-
- SourceProvider* provider() const { return m_provider.get(); }
- int firstLine() const { return m_firstLine; }
- int startOffset() const { return m_startChar; }
- const UChar* data() const { return m_provider->data() + m_startChar; }
- int length() const { return m_endChar - m_startChar; }
-
- private:
- RefPtr<SourceProvider> m_provider;
- int m_startChar;
- int m_endChar;
- int m_firstLine;
- };
-
- inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 0)
- {
- return SourceCode(UStringSourceProvider::create(source, url), firstLine);
- }
-
-} // namespace KJS
-
-#endif // SourceCode_h
+++ /dev/null
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SourceProvider_h
-#define SourceProvider_h
-
-#include "ustring.h"
-#include <wtf/RefCounted.h>
-
-namespace KJS {
-
- class SourceProvider : public RefCounted<SourceProvider> {
- public:
- SourceProvider(const UString& url)
- : m_url(url)
- {
- }
- virtual ~SourceProvider() { }
-
- virtual UString getRange(int start, int end) const = 0;
- virtual const UChar* data() const = 0;
- virtual int length() const = 0;
-
- const UString& url() { return m_url; }
- intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
-
- private:
- UString m_url;
- };
-
- class UStringSourceProvider : public SourceProvider {
- public:
- static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url)
- {
- return new UStringSourceProvider(source, url);
- }
-
- UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
- const UChar* data() const { return m_source.data(); }
- int length() const { return m_source.size(); }
-
- private:
- UStringSourceProvider(const UString& source, const UString& url)
- : SourceProvider(url)
- , m_source(source)
- {
- }
-
- UString m_source;
- };
-
-} // namespace KJS
-
-#endif // SourceProvider_h
+++ /dev/null
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SymbolTable_h
-#define SymbolTable_h
-
-#include "ustring.h"
-#include <wtf/AlwaysInline.h>
-
-namespace KJS {
-
- struct IdentifierRepHash {
- static unsigned hash(const RefPtr<UString::Rep>& key) { return key->computedHash(); }
- static bool equal(const RefPtr<UString::Rep>& a, const RefPtr<UString::Rep>& b) { return a == b; }
- static const bool safeToCompareToEmptyOrDeleted = true;
- };
-
- struct IdentifierRepHashTraits : HashTraits<RefPtr<UString::Rep> > {
- static const RefPtr<UString::Rep>& deletedValue()
- {
- return *reinterpret_cast<RefPtr<UString::Rep>*>(&nullRepPtr);
- }
-
- private:
- static UString::Rep* nullRepPtr;
- };
-
- static ALWAYS_INLINE size_t missingSymbolMarker() { return std::numeric_limits<size_t>::max(); }
-
- struct SymbolTableIndexHashTraits {
- typedef size_t TraitType;
- typedef SymbolTableIndexHashTraits StorageTraits;
- static size_t emptyValue() { return missingSymbolMarker(); }
- static const bool emptyValueIsZero = false;
- static const bool needsDestruction = false;
- static const bool needsRef = false;
- };
-
- typedef HashMap<RefPtr<UString::Rep>, size_t, IdentifierRepHash, IdentifierRepHashTraits, SymbolTableIndexHashTraits> SymbolTable;
-
-} // namespace KJS
-
-#endif // SymbolTable_h
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2003 Peter Kelly (pmk@post.com)
- * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "array_instance.h"
-
-#include "JSGlobalObject.h"
-#include "PropertyNameArray.h"
-#include <wtf/Assertions.h>
-
-using namespace std;
-
-namespace KJS {
-
-typedef HashMap<unsigned, JSValue*> SparseArrayValueMap;
-
-struct ArrayStorage {
- unsigned m_numValuesInVector;
- SparseArrayValueMap* m_sparseValueMap;
- JSValue* m_vector[1];
-};
-
-// 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer
-static const unsigned maxArrayIndex = 0xFFFFFFFEU;
-
-// Our policy for when to use a vector and when to use a sparse map.
-// For all array indices under sparseArrayCutoff, we always use a vector.
-// When indices greater than sparseArrayCutoff are involved, we use a vector
-// as long as it is 1/8 full. If more sparse than that, we use a map.
-// This value has to be a macro to be used in max() and min() without introducing
-// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
-#define sparseArrayCutoff 10000U
-static const unsigned minDensityMultiplier = 8;
-
-static const unsigned copyingSortCutoff = 50000;
-
-const ClassInfo ArrayInstance::info = {"Array", 0, 0};
-
-static inline size_t storageSize(unsigned vectorLength)
-{
- return sizeof(ArrayStorage) - sizeof(JSValue*) + vectorLength * sizeof(JSValue*);
-}
-
-static inline unsigned increasedVectorLength(unsigned newLength)
-{
- return (newLength * 3 + 1) / 2;
-}
-
-static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
-{
- return length / minDensityMultiplier <= numValues;
-}
-
-ArrayInstance::ArrayInstance(JSObject* prototype, unsigned initialLength)
- : JSObject(prototype)
-{
- unsigned initialCapacity = min(initialLength, sparseArrayCutoff);
-
- m_length = initialLength;
- m_vectorLength = initialCapacity;
- m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
-
- Collector::reportExtraMemoryCost(initialCapacity * sizeof(JSValue*));
-}
-
-ArrayInstance::ArrayInstance(JSObject* prototype, const List& list)
- : JSObject(prototype)
-{
- unsigned length = list.size();
-
- m_length = length;
- m_vectorLength = length;
-
- ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length)));
-
- storage->m_numValuesInVector = length;
- storage->m_sparseValueMap = 0;
-
- size_t i = 0;
- List::const_iterator end = list.end();
- for (List::const_iterator it = list.begin(); it != end; ++it, ++i)
- storage->m_vector[i] = *it;
-
- m_storage = storage;
-
- // When the array is created non-empty, its cells are filled, so it's really no worse than
- // a property map. Therefore don't report extra memory cost.
-}
-
-ArrayInstance::~ArrayInstance()
-{
- delete m_storage->m_sparseValueMap;
- fastFree(m_storage);
-}
-
-JSValue* ArrayInstance::getItem(unsigned i) const
-{
- ASSERT(i <= maxArrayIndex);
-
- ArrayStorage* storage = m_storage;
-
- if (i < m_vectorLength) {
- JSValue* value = storage->m_vector[i];
- return value ? value : jsUndefined();
- }
-
- SparseArrayValueMap* map = storage->m_sparseValueMap;
- if (!map)
- return jsUndefined();
-
- JSValue* value = map->get(i);
- return value ? value : jsUndefined();
-}
-
-JSValue* ArrayInstance::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- return jsNumber(static_cast<ArrayInstance*>(slot.slotBase())->m_length);
-}
-
-ALWAYS_INLINE bool ArrayInstance::inlineGetOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
-{
- ArrayStorage* storage = m_storage;
-
- if (i >= m_length) {
- if (i > maxArrayIndex)
- return getOwnPropertySlot(exec, Identifier::from(i), slot);
- return false;
- }
-
- if (i < m_vectorLength) {
- JSValue*& valueSlot = storage->m_vector[i];
- if (valueSlot) {
- slot.setValueSlot(this, &valueSlot);
- return true;
- }
- } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- if (i >= sparseArrayCutoff) {
- SparseArrayValueMap::iterator it = map->find(i);
- if (it != map->end()) {
- slot.setValueSlot(this, &it->second);
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool ArrayInstance::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- bool isArrayIndex;
- unsigned i = propertyName.toArrayIndex(&isArrayIndex);
- if (isArrayIndex)
- return inlineGetOwnPropertySlot(exec, i, slot);
-
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-bool ArrayInstance::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
-{
- return inlineGetOwnPropertySlot(exec, i, slot);
-}
-
-// ECMA 15.4.5.1
-void ArrayInstance::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attributes)
-{
- bool isArrayIndex;
- unsigned i = propertyName.toArrayIndex(&isArrayIndex);
- if (isArrayIndex) {
- put(exec, i, value, attributes);
- return;
- }
-
- if (propertyName == exec->propertyNames().length) {
- unsigned newLength = value->toUInt32(exec);
- if (value->toNumber(exec) != static_cast<double>(newLength)) {
- throwError(exec, RangeError, "Invalid array length.");
- return;
- }
- setLength(newLength);
- return;
- }
-
- JSObject::put(exec, propertyName, value, attributes);
-}
-
-void ArrayInstance::put(ExecState* exec, unsigned i, JSValue* value, int attributes)
-{
- if (i > maxArrayIndex) {
- put(exec, Identifier::from(i), value, attributes);
- return;
- }
-
- ArrayStorage* storage = m_storage;
-
- unsigned length = m_length;
- if (i >= length) {
- length = i + 1;
- m_length = length;
- }
-
- if (i < m_vectorLength) {
- JSValue*& valueSlot = storage->m_vector[i];
- storage->m_numValuesInVector += !valueSlot;
- valueSlot = value;
- return;
- }
-
- SparseArrayValueMap* map = storage->m_sparseValueMap;
-
- if (i >= sparseArrayCutoff) {
- // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
- // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
- if (!isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
- if (!map) {
- map = new SparseArrayValueMap;
- storage->m_sparseValueMap = map;
- }
- map->set(i, value);
- return;
- }
- }
-
- // We have decided that we'll put the new item into the vector.
- // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.
- if (!map || map->isEmpty()) {
- increaseVectorLength(i + 1);
- storage = m_storage;
- ++storage->m_numValuesInVector;
- storage->m_vector[i] = value;
- return;
- }
-
- // Decide how many values it would be best to move from the map.
- unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
- unsigned newVectorLength = increasedVectorLength(i + 1);
- for (unsigned j = max(m_vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
- newNumValuesInVector += map->contains(j);
- if (i >= sparseArrayCutoff)
- newNumValuesInVector -= map->contains(i);
- if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
- unsigned proposedNewNumValuesInVector = newNumValuesInVector;
- while (true) {
- unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);
- for (unsigned j = max(newVectorLength, sparseArrayCutoff); j < proposedNewVectorLength; ++j)
- proposedNewNumValuesInVector += map->contains(j);
- if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))
- break;
- newVectorLength = proposedNewVectorLength;
- newNumValuesInVector = proposedNewNumValuesInVector;
- }
- }
-
- storage = static_cast<ArrayStorage*>(fastRealloc(storage, storageSize(newVectorLength)));
-
- unsigned vectorLength = m_vectorLength;
- if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
- for (unsigned j = vectorLength; j < newVectorLength; ++j)
- storage->m_vector[j] = 0;
- if (i > sparseArrayCutoff)
- map->remove(i);
- } else {
- for (unsigned j = vectorLength; j < max(vectorLength, sparseArrayCutoff); ++j)
- storage->m_vector[j] = 0;
- for (unsigned j = max(vectorLength, sparseArrayCutoff); j < newVectorLength; ++j)
- storage->m_vector[j] = map->take(j);
- }
-
- storage->m_vector[i] = value;
-
- m_vectorLength = newVectorLength;
- storage->m_numValuesInVector = newNumValuesInVector;
-
- m_storage = storage;
-}
-
-bool ArrayInstance::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- bool isArrayIndex;
- unsigned i = propertyName.toArrayIndex(&isArrayIndex);
- if (isArrayIndex)
- return deleteProperty(exec, i);
-
- if (propertyName == exec->propertyNames().length)
- return false;
-
- return JSObject::deleteProperty(exec, propertyName);
-}
-
-bool ArrayInstance::deleteProperty(ExecState* exec, unsigned i)
-{
- ArrayStorage* storage = m_storage;
-
- if (i < m_vectorLength) {
- JSValue*& valueSlot = storage->m_vector[i];
- bool hadValue = valueSlot;
- valueSlot = 0;
- storage->m_numValuesInVector -= hadValue;
- return hadValue;
- }
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- if (i >= sparseArrayCutoff) {
- SparseArrayValueMap::iterator it = map->find(i);
- if (it != map->end()) {
- map->remove(it);
- return true;
- }
- }
- }
-
- if (i > maxArrayIndex)
- return deleteProperty(exec, Identifier::from(i));
-
- return false;
-}
-
-void ArrayInstance::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
-{
- // FIXME: Filling PropertyNameArray with an identifier for every integer
- // is incredibly inefficient for large arrays. We need a different approach.
-
- ArrayStorage* storage = m_storage;
-
- unsigned usedVectorLength = min(m_length, m_vectorLength);
- for (unsigned i = 0; i < usedVectorLength; ++i) {
- if (storage->m_vector[i])
- propertyNames.add(Identifier::from(i));
- }
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- SparseArrayValueMap::iterator end = map->end();
- for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
- propertyNames.add(Identifier::from(it->first));
- }
-
- JSObject::getPropertyNames(exec, propertyNames);
-}
-
-void ArrayInstance::increaseVectorLength(unsigned newLength)
-{
- // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
- // to the vector. Callers have to account for that, because they can do it more efficiently.
-
- ArrayStorage* storage = m_storage;
-
- unsigned vectorLength = m_vectorLength;
- ASSERT(newLength > vectorLength);
- unsigned newVectorLength = increasedVectorLength(newLength);
-
- storage = static_cast<ArrayStorage*>(fastRealloc(storage, storageSize(newVectorLength)));
- m_vectorLength = newVectorLength;
-
- for (unsigned i = vectorLength; i < newVectorLength; ++i)
- storage->m_vector[i] = 0;
-
- m_storage = storage;
-}
-
-void ArrayInstance::setLength(unsigned newLength)
-{
- ArrayStorage* storage = m_storage;
-
- unsigned length = m_length;
-
- if (newLength < length) {
- unsigned usedVectorLength = min(length, m_vectorLength);
- for (unsigned i = newLength; i < usedVectorLength; ++i) {
- JSValue*& valueSlot = storage->m_vector[i];
- bool hadValue = valueSlot;
- valueSlot = 0;
- storage->m_numValuesInVector -= hadValue;
- }
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- SparseArrayValueMap copy = *map;
- SparseArrayValueMap::iterator end = copy.end();
- for (SparseArrayValueMap::iterator it = copy.begin(); it != end; ++it) {
- if (it->first >= newLength)
- map->remove(it->first);
- }
- if (map->isEmpty()) {
- delete map;
- storage->m_sparseValueMap = 0;
- }
- }
- }
-
- m_length = newLength;
-}
-
-void ArrayInstance::mark()
-{
- JSObject::mark();
-
- ArrayStorage* storage = m_storage;
-
- unsigned usedVectorLength = min(m_length, m_vectorLength);
- for (unsigned i = 0; i < usedVectorLength; ++i) {
- JSValue* value = storage->m_vector[i];
- if (value && !value->marked())
- value->mark();
- }
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- SparseArrayValueMap::iterator end = map->end();
- for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
- JSValue* value = it->second;
- if (!value->marked())
- value->mark();
- }
- }
-}
-
-static int compareByStringPairForQSort(const void* a, const void* b)
-{
- const std::pair<JSValue*, UString>* va = static_cast<const std::pair<JSValue*, UString>*>(a);
- const std::pair<JSValue*, UString>* vb = static_cast<const std::pair<JSValue*, UString>*>(b);
- return compare(va->second, vb->second);
-}
-
-static ExecState* execForCompareByStringForQSort = 0;
-static int compareByStringForQSort(const void* a, const void* b)
-{
- ExecState* exec = execForCompareByStringForQSort;
-
- JSValue* va = *static_cast<JSValue* const*>(a);
- JSValue* vb = *static_cast<JSValue* const*>(b);
- ASSERT(!va->isUndefined());
- ASSERT(!vb->isUndefined());
-
- return compare(va->toString(exec), vb->toString(exec));
-}
-
-void ArrayInstance::sort(ExecState* exec)
-{
- unsigned lengthNotIncludingUndefined = compactForSorting();
-
- if (lengthNotIncludingUndefined < copyingSortCutoff) {
- // Converting JavaScript values to strings can be expensive, so we do it once up front and sort based on that.
- // This is a considerable improvement over doing it twice per comparison, though it requires a large temporary
- // buffer. For large arrays, we fall back to a qsort on the JavaScriptValues to avoid creating copies.
-
- Vector<std::pair<JSValue*, UString> > values(lengthNotIncludingUndefined);
- for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
- JSValue* value = m_storage->m_vector[i];
- ASSERT(!value->isUndefined());
- values[i].first = value;
- values[i].second = value->toString(exec);
- }
-
- // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather
- // than O(N log N).
-
-#if HAVE(MERGESORT)
- mergesort(values.begin(), values.size(), sizeof(std::pair<JSValue*, UString>), compareByStringPairForQSort);
-#else
- qsort(values.begin(), values.size(), sizeof(std::pair<JSValue*, UString>), compareByStringPairForQSort);
-#endif
- for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
- m_storage->m_vector[i] = values[i].first;
- return;
- }
-
- ExecState* oldExec = execForCompareByStringForQSort;
- execForCompareByStringForQSort = exec;
- qsort(m_storage->m_vector, lengthNotIncludingUndefined, sizeof(JSValue*), compareByStringForQSort);
- execForCompareByStringForQSort = oldExec;
-}
-
-struct CompareWithCompareFunctionArguments {
- CompareWithCompareFunctionArguments(ExecState *e, JSObject *cf)
- : exec(e)
- , compareFunction(cf)
- , globalObject(e->dynamicGlobalObject())
- {
- }
-
- ExecState *exec;
- JSObject *compareFunction;
- List arguments;
- JSGlobalObject* globalObject;
-};
-
-static CompareWithCompareFunctionArguments* compareWithCompareFunctionArguments = 0;
-
-static int compareWithCompareFunctionForQSort(const void* a, const void* b)
-{
- CompareWithCompareFunctionArguments *args = compareWithCompareFunctionArguments;
-
- JSValue* va = *static_cast<JSValue* const*>(a);
- JSValue* vb = *static_cast<JSValue* const*>(b);
- ASSERT(!va->isUndefined());
- ASSERT(!vb->isUndefined());
-
- args->arguments.clear();
- args->arguments.append(va);
- args->arguments.append(vb);
- double compareResult = args->compareFunction->call
- (args->exec, args->globalObject, args->arguments)->toNumber(args->exec);
- return compareResult < 0 ? -1 : compareResult > 0 ? 1 : 0;
-}
-
-void ArrayInstance::sort(ExecState* exec, JSObject* compareFunction)
-{
- size_t lengthNotIncludingUndefined = compactForSorting();
-
- CompareWithCompareFunctionArguments* oldArgs = compareWithCompareFunctionArguments;
- CompareWithCompareFunctionArguments args(exec, compareFunction);
- compareWithCompareFunctionArguments = &args;
-
-#if HAVE(MERGESORT)
- // Because mergesort usually does fewer compares, it is faster than qsort here.
- // However, because it requires extra copies of the storage buffer, don't use it for very
- // large arrays.
-
- // FIXME: A tree sort using a perfectly balanced tree (e.g. an AVL tree) could do an even
- // better job of minimizing compares.
-
- if (lengthNotIncludingUndefined < copyingSortCutoff) {
- // During the sort, we could do a garbage collect, and it's important to still
- // have references to every object in the array for ArrayInstance::mark.
- // The mergesort algorithm does not guarantee this, so we sort a copy rather
- // than the original.
- size_t size = storageSize(m_vectorLength);
- ArrayStorage* copy = static_cast<ArrayStorage*>(fastMalloc(size));
- memcpy(copy, m_storage, size);
- mergesort(copy->m_vector, lengthNotIncludingUndefined, sizeof(JSValue*), compareWithCompareFunctionForQSort);
- fastFree(m_storage);
- m_storage = copy;
- compareWithCompareFunctionArguments = oldArgs;
- return;
- }
-#endif
-
- qsort(m_storage->m_vector, lengthNotIncludingUndefined, sizeof(JSValue*), compareWithCompareFunctionForQSort);
- compareWithCompareFunctionArguments = oldArgs;
-}
-
-unsigned ArrayInstance::compactForSorting()
-{
- ArrayStorage* storage = m_storage;
-
- unsigned usedVectorLength = min(m_length, m_vectorLength);
-
- unsigned numDefined = 0;
- unsigned numUndefined = 0;
-
- for (; numDefined < usedVectorLength; ++numDefined) {
- JSValue* v = storage->m_vector[numDefined];
- if (!v || v->isUndefined())
- break;
- }
- for (unsigned i = numDefined; i < usedVectorLength; ++i) {
- if (JSValue* v = storage->m_vector[i]) {
- if (v->isUndefined())
- ++numUndefined;
- else
- storage->m_vector[numDefined++] = v;
- }
- }
-
- unsigned newUsedVectorLength = numDefined + numUndefined;
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- newUsedVectorLength += map->size();
- if (newUsedVectorLength > m_vectorLength) {
- increaseVectorLength(newUsedVectorLength);
- storage = m_storage;
- }
-
- SparseArrayValueMap::iterator end = map->end();
- for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
- storage->m_vector[numDefined++] = it->second;
-
- delete map;
- storage->m_sparseValueMap = 0;
- }
-
- for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
- storage->m_vector[i] = jsUndefined();
- for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
- storage->m_vector[i] = 0;
-
- return numDefined;
-}
-
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef ARRAY_INSTANCE_H
-#define ARRAY_INSTANCE_H
-
-#include "object.h"
-
-namespace KJS {
-
- struct ArrayStorage;
-
- class ArrayInstance : public JSObject {
- public:
- ArrayInstance(JSObject* prototype, unsigned initialLength);
- ArrayInstance(JSObject* prototype, const List& initialValues);
- ~ArrayInstance();
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValue*, int attributes = None);
- virtual void put(ExecState*, unsigned propertyName, JSValue*, int attributes = None);
- virtual bool deleteProperty(ExecState *, const Identifier& propertyName);
- virtual bool deleteProperty(ExecState *, unsigned propertyName);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual void mark();
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- unsigned getLength() const { return m_length; }
- JSValue* getItem(unsigned) const;
-
- void sort(ExecState*);
- void sort(ExecState*, JSObject* compareFunction);
-
- private:
- static JSValue* lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- bool inlineGetOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-
- void setLength(unsigned);
- void increaseVectorLength(unsigned newLength);
-
- unsigned compactForSorting();
-
- unsigned m_length;
- unsigned m_vectorLength;
- ArrayStorage* m_storage;
- };
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2003 Peter Kelly (pmk@post.com)
- * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- *
- */
-
-#include "config.h"
-#include "array_object.h"
-#include "array_object.lut.h"
-
-#include "error_object.h"
-#include "lookup.h"
-#include "operations.h"
-#include <stdio.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashSet.h>
-
-#include <algorithm> // for std::min
-
-namespace KJS {
-
-// ------------------------------ ArrayPrototype ----------------------------
-
-const ClassInfo ArrayPrototype::info = {"Array", &ArrayInstance::info, &arrayTable};
-
-/* Source for array_object.lut.h
-@begin arrayTable 16
- toString arrayProtoFuncToString DontEnum|Function 0
- toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
- concat arrayProtoFuncConcat DontEnum|Function 1
- join arrayProtoFuncJoin DontEnum|Function 1
- pop arrayProtoFuncPop DontEnum|Function 0
- push arrayProtoFuncPush DontEnum|Function 1
- reverse arrayProtoFuncReverse DontEnum|Function 0
- shift arrayProtoFuncShift DontEnum|Function 0
- slice arrayProtoFuncSlice DontEnum|Function 2
- sort arrayProtoFuncSort DontEnum|Function 1
- splice arrayProtoFuncSplice DontEnum|Function 2
- unshift arrayProtoFuncUnShift DontEnum|Function 1
- every arrayProtoFuncEvery DontEnum|Function 1
- forEach arrayProtoFuncForEach DontEnum|Function 1
- some arrayProtoFuncSome DontEnum|Function 1
- indexOf arrayProtoFuncIndexOf DontEnum|Function 1
- lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
- filter arrayProtoFuncFilter DontEnum|Function 1
- map arrayProtoFuncMap DontEnum|Function 1
-@end
-*/
-
-// ECMA 15.4.4
-ArrayPrototype::ArrayPrototype(ExecState*, ObjectPrototype* objProto)
- : ArrayInstance(objProto, 0)
-{
-}
-
-bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getStaticFunctionSlot<ArrayInstance>(exec, &arrayTable, this, propertyName, slot);
-}
-
-
-// ------------------------------ Array Functions ----------------------------
-
-// Helper function
-static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index)
-{
- PropertySlot slot;
- if (!obj->getPropertySlot(exec, index, slot))
- return 0;
- return slot.getValue(exec, obj, index);
-}
-
-JSValue* arrayProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&ArrayInstance::info))
- return throwError(exec, TypeError);
-
- static HashSet<JSObject*> visitedElems;
- static const UString* empty = new UString("");
- static const UString* comma = new UString(",");
- bool alreadyVisited = !visitedElems.add(thisObj).second;
- if (alreadyVisited)
- return jsString(*empty);
- UString separator = *comma;
- UString str = *empty;
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length; k++) {
- if (k >= 1)
- str += separator;
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
- }
-
- JSValue* element = thisObj->get(exec, k);
- if (element->isUndefinedOrNull())
- continue;
-
- str += element->toString(exec);
-
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- }
-
- if (exec->hadException())
- break;
- }
- visitedElems.remove(thisObj);
- return jsString(str);
-}
-
-JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&ArrayInstance::info))
- return throwError(exec, TypeError);
-
- static HashSet<JSObject*> visitedElems;
- static const UString* empty = new UString("");
- static const UString* comma = new UString(",");
- bool alreadyVisited = !visitedElems.add(thisObj).second;
- if (alreadyVisited)
- return jsString(*empty);
- UString separator = *comma;
- UString str = *empty;
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length; k++) {
- if (k >= 1)
- str += separator;
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
- }
-
- JSValue* element = thisObj->get(exec, k);
- if (element->isUndefinedOrNull())
- continue;
-
- JSObject* o = element->toObject(exec);
- JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
- if (conversionFunction->isObject() && static_cast<JSObject*>(conversionFunction)->implementsCall())
- str += static_cast<JSObject*>(conversionFunction)->call(exec, o, exec->emptyList())->toString(exec);
- else
- str += element->toString(exec);
-
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- }
-
- if (exec->hadException())
- break;
- }
- visitedElems.remove(thisObj);
- return jsString(str);
-}
-
-JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject* thisObj, const List& args)
-{
- static HashSet<JSObject*> visitedElems;
- static const UString* empty = new UString("");
- static const UString* comma = new UString(",");
- bool alreadyVisited = !visitedElems.add(thisObj).second;
- if (alreadyVisited)
- return jsString(*empty);
- UString separator = *comma;
- UString str = *empty;
-
- if (!args[0]->isUndefined())
- separator = args[0]->toString(exec);
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length; k++) {
- if (k >= 1)
- str += separator;
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
- }
-
- JSValue* element = thisObj->get(exec, k);
- if (element->isUndefinedOrNull())
- continue;
-
- str += element->toString(exec);
-
- if (str.isNull()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- }
-
- if (exec->hadException())
- break;
- }
- visitedElems.remove(thisObj);
- return jsString(str);
-}
-
-JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* arr = static_cast<JSObject*>(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList()));
- int n = 0;
- JSValue* curArg = thisObj;
- JSObject* curObj = static_cast<JSObject* >(thisObj);
- List::const_iterator it = args.begin();
- List::const_iterator end = args.end();
- while (1) {
- if (curArg->isObject() && curObj->inherits(&ArrayInstance::info)) {
- unsigned k = 0;
- // Older versions tried to optimize out getting the length of thisObj
- // by checking for n != 0, but that doesn't work if thisObj is an empty array.
- unsigned length = curObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- while (k < length) {
- if (JSValue* v = getProperty(exec, curObj, k))
- arr->put(exec, n, v);
- n++;
- k++;
- }
- } else {
- arr->put(exec, n, curArg);
- n++;
- }
- if (it == end)
- break;
- curArg = *it;
- curObj = static_cast<JSObject*>(curArg); // may be 0
- ++it;
- }
- arr->put(exec, exec->propertyNames().length, jsNumber(n));
- return arr;
-}
-
-JSValue* arrayProtoFuncPop(ExecState* exec, JSObject* thisObj, const List&)
-{
- JSValue* result = 0;
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- if (length == 0) {
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length));
- result = jsUndefined();
- } else {
- result = thisObj->get(exec, length - 1);
- thisObj->deleteProperty(exec, length - 1);
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1));
- }
- return result;
-}
-
-JSValue* arrayProtoFuncPush(ExecState* exec, JSObject* thisObj, const List& args)
-{
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned n = 0; n < args.size(); n++)
- thisObj->put(exec, length + n, args[n]);
- length += args.size();
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length));
- return jsNumber(length);
-}
-
-JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject* thisObj, const List&)
-{
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- unsigned middle = length / 2;
-
- for (unsigned k = 0; k < middle; k++) {
- unsigned lk1 = length - k - 1;
- JSValue* obj2 = getProperty(exec, thisObj, lk1);
- JSValue* obj = getProperty(exec, thisObj, k);
-
- if (obj2)
- thisObj->put(exec, k, obj2);
- else
- thisObj->deleteProperty(exec, k);
-
- if (obj)
- thisObj->put(exec, lk1, obj);
- else
- thisObj->deleteProperty(exec, lk1);
- }
- return thisObj;
-}
-
-JSValue* arrayProtoFuncShift(ExecState* exec, JSObject* thisObj, const List&)
-{
- JSValue* result = 0;
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- if (length == 0) {
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length));
- result = jsUndefined();
- } else {
- result = thisObj->get(exec, 0);
- for (unsigned k = 1; k < length; k++) {
- if (JSValue* obj = getProperty(exec, thisObj, k))
- thisObj->put(exec, k - 1, obj);
- else
- thisObj->deleteProperty(exec, k - 1);
- }
- thisObj->deleteProperty(exec, length - 1);
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length - 1));
- }
- return result;
-}
-
-JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
-
- // We return a new array
- JSObject* resObj = static_cast<JSObject* >(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList()));
- JSValue* result = resObj;
- double begin = args[0]->toInteger(exec);
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- if (begin >= 0) {
- if (begin > length)
- begin = length;
- } else {
- begin += length;
- if (begin < 0)
- begin = 0;
- }
- double end;
- if (args[1]->isUndefined())
- end = length;
- else {
- end = args[1]->toInteger(exec);
- if (end < 0) {
- end += length;
- if (end < 0)
- end = 0;
- } else {
- if (end > length)
- end = length;
- }
- }
-
- int n = 0;
- int b = static_cast<int>(begin);
- int e = static_cast<int>(end);
- for (int k = b; k < e; k++, n++) {
- if (JSValue* v = getProperty(exec, thisObj, k))
- resObj->put(exec, n, v);
- }
- resObj->put(exec, exec->propertyNames().length, jsNumber(n));
- return result;
-}
-
-JSValue* arrayProtoFuncSort(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* sortFunction = 0;
- if (!args[0]->isUndefined()) {
- sortFunction = args[0]->toObject(exec);
- if (!sortFunction->implementsCall())
- sortFunction = 0;
- }
-
- if (thisObj->classInfo() == &ArrayInstance::info) {
- if (sortFunction)
- static_cast<ArrayInstance*>(thisObj)->sort(exec, sortFunction);
- else
- static_cast<ArrayInstance*>(thisObj)->sort(exec);
- return thisObj;
- }
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
-
- if (!length)
- return thisObj;
-
- // "Min" sort. Not the fastest, but definitely less code than heapsort
- // or quicksort, and much less swapping than bubblesort/insertionsort.
- for (unsigned i = 0; i < length - 1; ++i) {
- JSValue* iObj = thisObj->get(exec, i);
- unsigned themin = i;
- JSValue* minObj = iObj;
- for (unsigned j = i + 1; j < length; ++j) {
- JSValue* jObj = thisObj->get(exec, j);
- double compareResult;
- if (jObj->isUndefined())
- compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
- else if (minObj->isUndefined())
- compareResult = -1;
- else if (sortFunction) {
- List l;
- l.append(jObj);
- l.append(minObj);
- compareResult = sortFunction->call(exec, exec->dynamicGlobalObject(), l)->toNumber(exec);
- } else
- compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;
-
- if (compareResult < 0) {
- themin = j;
- minObj = jObj;
- }
- }
- // Swap themin and i
- if (themin > i) {
- thisObj->put(exec, i, minObj);
- thisObj->put(exec, themin, iObj);
- }
- }
- return thisObj;
-}
-
-JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // 15.4.4.12
- JSObject* resObj = static_cast<JSObject* >(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList()));
- JSValue* result = resObj;
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- if (!args.size())
- return jsUndefined();
- int begin = args[0]->toUInt32(exec);
- if (begin < 0)
- begin = std::max<int>(begin + length, 0);
- else
- begin = std::min<int>(begin, length);
-
- unsigned deleteCount;
- if (args.size() > 1)
- deleteCount = std::min<int>(std::max<int>(args[1]->toUInt32(exec), 0), length - begin);
- else
- deleteCount = length - begin;
-
- for (unsigned k = 0; k < deleteCount; k++) {
- if (JSValue* v = getProperty(exec, thisObj, k + begin))
- resObj->put(exec, k, v);
- }
- resObj->put(exec, exec->propertyNames().length, jsNumber(deleteCount));
-
- unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
- if (additionalArgs != deleteCount) {
- if (additionalArgs < deleteCount) {
- for (unsigned k = begin; k < length - deleteCount; ++k) {
- if (JSValue* v = getProperty(exec, thisObj, k + deleteCount))
- thisObj->put(exec, k + additionalArgs, v);
- else
- thisObj->deleteProperty(exec, k + additionalArgs);
- }
- for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
- thisObj->deleteProperty(exec, k - 1);
- } else {
- for (unsigned k = length - deleteCount; (int)k > begin; --k) {
- if (JSValue* obj = getProperty(exec, thisObj, k + deleteCount - 1))
- thisObj->put(exec, k + additionalArgs - 1, obj);
- else
- thisObj->deleteProperty(exec, k + additionalArgs - 1);
- }
- }
- }
- for (unsigned k = 0; k < additionalArgs; ++k)
- thisObj->put(exec, k + begin, args[k + 2]);
-
- thisObj->put(exec, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
- return result;
-}
-
-JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // 15.4.4.13
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- unsigned nrArgs = args.size();
- if (nrArgs) {
- for (unsigned k = length; k > 0; --k) {
- if (JSValue* v = getProperty(exec, thisObj, k - 1))
- thisObj->put(exec, k + nrArgs - 1, v);
- else
- thisObj->deleteProperty(exec, k + nrArgs - 1);
- }
- }
- for (unsigned k = 0; k < nrArgs; ++k)
- thisObj->put(exec, k, args[k]);
- JSValue* result = jsNumber(length + nrArgs);
- thisObj->put(exec, exec->propertyNames().length, result);
- return result;
-}
-
-JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* eachFunction = args[0]->toObject(exec);
-
- if (!eachFunction->implementsCall())
- return throwError(exec, TypeError);
-
- JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
- JSObject* resultArray = static_cast<JSObject*>(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList()));
-
- unsigned filterIndex = 0;
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
- PropertySlot slot;
-
- if (!thisObj->getPropertySlot(exec, k, slot))
- continue;
-
- JSValue* v = slot.getValue(exec, thisObj, k);
-
- List eachArguments;
-
- eachArguments.append(v);
- eachArguments.append(jsNumber(k));
- eachArguments.append(thisObj);
-
- JSValue* result = eachFunction->call(exec, applyThis, eachArguments);
-
- if (result->toBoolean(exec))
- resultArray->put(exec, filterIndex++, v);
- }
- return resultArray;
-}
-
-JSValue* arrayProtoFuncMap(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* eachFunction = args[0]->toObject(exec);
- if (!eachFunction->implementsCall())
- return throwError(exec, TypeError);
-
- JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
-
- List mapArgs;
- mapArgs.append(jsNumber(length));
- JSObject* resultArray = static_cast<JSObject*>(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, mapArgs));
-
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
- PropertySlot slot;
- if (!thisObj->getPropertySlot(exec, k, slot))
- continue;
-
- JSValue* v = slot.getValue(exec, thisObj, k);
-
- List eachArguments;
-
- eachArguments.append(v);
- eachArguments.append(jsNumber(k));
- eachArguments.append(thisObj);
-
- JSValue* result = eachFunction->call(exec, applyThis, eachArguments);
- resultArray->put(exec, k, result);
- }
-
- return resultArray;
-}
-
-// Documentation for these three is available at:
-// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
-// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
-// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
-
-JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* eachFunction = args[0]->toObject(exec);
-
- if (!eachFunction->implementsCall())
- return throwError(exec, TypeError);
-
- JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
-
- JSValue* result = jsBoolean(true);
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
- PropertySlot slot;
-
- if (!thisObj->getPropertySlot(exec, k, slot))
- continue;
-
- List eachArguments;
-
- eachArguments.append(slot.getValue(exec, thisObj, k));
- eachArguments.append(jsNumber(k));
- eachArguments.append(thisObj);
-
- bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec);
-
- if (!predicateResult) {
- result = jsBoolean(false);
- break;
- }
- }
-
- return result;
-}
-
-JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* eachFunction = args[0]->toObject(exec);
-
- if (!eachFunction->implementsCall())
- return throwError(exec, TypeError);
-
- JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
- PropertySlot slot;
- if (!thisObj->getPropertySlot(exec, k, slot))
- continue;
-
- List eachArguments;
- eachArguments.append(slot.getValue(exec, thisObj, k));
- eachArguments.append(jsNumber(k));
- eachArguments.append(thisObj);
-
- eachFunction->call(exec, applyThis, eachArguments);
- }
- return jsUndefined();
-}
-
-JSValue* arrayProtoFuncSome(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSObject* eachFunction = args[0]->toObject(exec);
-
- if (!eachFunction->implementsCall())
- return throwError(exec, TypeError);
-
- JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
-
- JSValue* result = jsBoolean(false);
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
- PropertySlot slot;
- if (!thisObj->getPropertySlot(exec, k, slot))
- continue;
-
- List eachArguments;
- eachArguments.append(slot.getValue(exec, thisObj, k));
- eachArguments.append(jsNumber(k));
- eachArguments.append(thisObj);
-
- bool predicateResult = eachFunction->call(exec, applyThis, eachArguments)->toBoolean(exec);
-
- if (predicateResult) {
- result = jsBoolean(true);
- break;
- }
- }
- return result;
-}
-
-JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // JavaScript 1.5 Extension by Mozilla
- // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
-
- unsigned index = 0;
- double d = args[1]->toInteger(exec);
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- if (d < 0)
- d += length;
- if (d > 0) {
- if (d > length)
- index = length;
- else
- index = static_cast<unsigned>(d);
- }
-
- JSValue* searchElement = args[0];
- for (; index < length; ++index) {
- JSValue* e = getProperty(exec, thisObj, index);
- if (!e)
- continue;
- if (strictEqual(exec, searchElement, e))
- return jsNumber(index);
- }
-
- return jsNumber(-1);
-}
-
-JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // JavaScript 1.6 Extension by Mozilla
- // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
-
- unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- int index = length - 1;
- double d = args[1]->toIntegerPreserveNaN(exec);
-
- if (d < 0) {
- d += length;
- if (d < 0)
- return jsNumber(-1);
- }
- if (d < length)
- index = static_cast<int>(d);
-
- JSValue* searchElement = args[0];
- for (; index >= 0; --index) {
- JSValue* e = getProperty(exec, thisObj, index);
- if (!e)
- continue;
- if (strictEqual(exec, searchElement, e))
- return jsNumber(index);
- }
-
- return jsNumber(-1);
-}
-
-// ------------------------------ ArrayObjectImp -------------------------------
-
-ArrayObjectImp::ArrayObjectImp(ExecState* exec, FunctionPrototype* funcProto, ArrayPrototype* arrayProto)
- : InternalFunctionImp(funcProto, arrayProto->classInfo()->className)
-{
- // ECMA 15.4.3.1 Array.prototype
- putDirect(exec->propertyNames().prototype, arrayProto, DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
-}
-
-bool ArrayObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.4.2
-JSObject* ArrayObjectImp::construct(ExecState* exec, const List& args)
-{
- // a single numeric argument denotes the array size (!)
- if (args.size() == 1 && args[0]->isNumber()) {
- uint32_t n = args[0]->toUInt32(exec);
- if (n != args[0]->toNumber(exec))
- return throwError(exec, RangeError, "Array size is not a small enough positive integer.");
- return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), n);
- }
-
- // otherwise the array is constructed with the arguments in it
- return new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), args);
-}
-
-// ECMA 15.6.1
-JSValue* ArrayObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- // equivalent to 'new Array(....)'
- return construct(exec,args);
-}
-
-}
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef ARRAY_OBJECT_H_
-#define ARRAY_OBJECT_H_
-
-#include "array_instance.h"
-#include "function_object.h"
-#include "lookup.h"
-
-namespace KJS {
-
- class ArrayPrototype : public ArrayInstance {
- public:
- ArrayPrototype(ExecState*, ObjectPrototype*);
-
- bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class ArrayObjectImp : public InternalFunctionImp {
- public:
- ArrayObjectImp(ExecState*, FunctionPrototype*, ArrayPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
-
- };
-
- JSValue* arrayProtoFuncToString(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncConcat(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncJoin(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncPop(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncPush(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncReverse(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncShift(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncSlice(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncSort(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncSplice(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncUnShift(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncEvery(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncForEach(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncSome(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncIndexOf(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncFilter(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncMap(ExecState*, JSObject*, const List&);
- JSValue* arrayProtoFuncLastIndexOf(ExecState*, JSObject*, const List&);
-
-} // namespace KJS
-
-#endif // ARRAY_OBJECT_H_
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "bool_object.h"
-
-#include "JSGlobalObject.h"
-#include "error_object.h"
-#include "operations.h"
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-// ------------------------------ BooleanInstance ---------------------------
-
-const ClassInfo BooleanInstance::info = { "Boolean", 0, 0 };
-
-BooleanInstance::BooleanInstance(JSObject* proto)
- : JSWrapperObject(proto)
-{
-}
-
-// ------------------------------ BooleanPrototype --------------------------
-
-// Functions
-static JSValue* booleanProtoFuncToString(ExecState*, JSObject*, const List&);
-static JSValue* booleanProtoFuncValueOf(ExecState*, JSObject*, const List&);
-
-// ECMA 15.6.4
-
-BooleanPrototype::BooleanPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
- : BooleanInstance(objectPrototype)
-{
- setInternalValue(jsBoolean(false));
-
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
-}
-
-
-// ------------------------------ Functions --------------------------
-
-// ECMA 15.6.4.2 + 15.6.4.3
-
-JSValue* booleanProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&BooleanInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<BooleanInstance*>(thisObj)->internalValue();
- ASSERT(v);
-
- return jsString(v->toString(exec));
-}
-JSValue* booleanProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&BooleanInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<BooleanInstance*>(thisObj)->internalValue();
- ASSERT(v);
-
- // TODO: optimize for bool case
- return jsBoolean(v->toBoolean(exec));
-}
-
-// ------------------------------ BooleanObjectImp -----------------------------
-
-
-BooleanObjectImp::BooleanObjectImp(ExecState* exec, FunctionPrototype* functionPrototype, BooleanPrototype* booleanPrototype)
- : InternalFunctionImp(functionPrototype, booleanPrototype->classInfo()->className)
-{
- putDirect(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
-}
-
-
-bool BooleanObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.6.2
-JSObject* BooleanObjectImp::construct(ExecState* exec, const List& args)
-{
- BooleanInstance* obj(new BooleanInstance(exec->lexicalGlobalObject()->booleanPrototype()));
- obj->setInternalValue(jsBoolean(args[0]->toBoolean(exec)));
- return obj;
-}
-
-// ECMA 15.6.1
-JSValue* BooleanObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- // TODO: optimize for bool case
- return jsBoolean(args[0]->toBoolean(exec));
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef BOOL_OBJECT_H_
-#define BOOL_OBJECT_H_
-
-#include "function_object.h"
-#include "JSWrapperObject.h"
-
-namespace KJS {
-
- class BooleanInstance : public JSWrapperObject {
- public:
- BooleanInstance(JSObject* proto);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * The initial value of Boolean.prototype (and thus all objects created
- * with the Boolean constructor
- */
- class BooleanPrototype : public BooleanInstance {
- public:
- BooleanPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Boolean" property
- */
- class BooleanObjectImp : public InternalFunctionImp {
- public:
- BooleanObjectImp(ExecState*, FunctionPrototype*, BooleanPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
-
-} // namespace KJS
-
-#endif // BOOL_OBJECT_H_
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "collector.h"
-
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "internal.h"
-#include "list.h"
-#include "value.h"
-#include "JSLockC.h"
-#include <algorithm>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/UnusedParam.h>
-
-#if USE(MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
-#if PLATFORM(DARWIN)
-
-#include <mach/mach_port.h>
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/thread_act.h>
-#include <mach/vm_map.h>
-
-#include "CollectorHeapIntrospector.h"
-
-#elif PLATFORM(WIN_OS)
-
-#include <windows.h>
-
-#elif PLATFORM(UNIX)
-
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#if PLATFORM(SOLARIS)
-#include <thread.h>
-#endif
-
-#if HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#else
-#include <pthread.h>
-#endif
-
-#endif
-
-#define DEBUG_COLLECTOR 0
-
-using std::max;
-
-namespace KJS {
-
-// tunable parameters
-
-const size_t SPARE_EMPTY_BLOCKS = 2;
-const size_t MIN_ARRAY_SIZE = 14;
-const size_t GROWTH_FACTOR = 2;
-const size_t LOW_WATER_FACTOR = 4;
-const size_t ALLOCATIONS_PER_COLLECTION = 4000;
-
-enum OperationInProgress { NoOperation, Allocation, Collection };
-
-struct CollectorHeap {
- CollectorBlock** blocks;
- size_t numBlocks;
- size_t usedBlocks;
- size_t firstBlockWithPossibleSpace;
-
- size_t numLiveObjects;
- size_t numLiveObjectsAtLastCollect;
- size_t extraCost;
-
- OperationInProgress operationInProgress;
-};
-
-static CollectorHeap primaryHeap = { 0, 0, 0, 0, 0, 0, 0, NoOperation };
-static CollectorHeap numberHeap = { 0, 0, 0, 0, 0, 0, 0, NoOperation };
-
-// FIXME: I don't think this needs to be a static data member of the Collector class.
-// Just a private global like "heap" above would be fine.
-size_t Collector::mainThreadOnlyObjectCount = 0;
-
-static CollectorBlock* allocateBlock()
-{
-#if PLATFORM(DARWIN)
- vm_address_t address = 0;
- vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
-#elif PLATFORM(WIN_OS)
- // windows virtual address granularity is naturally 64k
- LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-#elif HAVE(POSIX_MEMALIGN)
- void* address;
- posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
- memset(address, 0, BLOCK_SIZE);
-#else
- static size_t pagesize = getpagesize();
-
- size_t extra = 0;
- if (BLOCK_SIZE > pagesize)
- extra = BLOCK_SIZE - pagesize;
-
- void* mmapResult = mmap(NULL, BLOCK_SIZE + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
-
- size_t adjust = 0;
- if ((address & BLOCK_OFFSET_MASK) != 0)
- adjust = BLOCK_SIZE - (address & BLOCK_OFFSET_MASK);
-
- if (adjust > 0)
- munmap(reinterpret_cast<void*>(address), adjust);
-
- if (adjust < extra)
- munmap(reinterpret_cast<void*>(address + adjust + BLOCK_SIZE), extra - adjust);
-
- address += adjust;
- memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
-#endif
-
- return reinterpret_cast<CollectorBlock*>(address);
-}
-
-static void freeBlock(CollectorBlock* block)
-{
-#if PLATFORM(DARWIN)
- vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
-#elif PLATFORM(WIN_OS)
- VirtualFree(block, BLOCK_SIZE, MEM_RELEASE);
-#elif HAVE(POSIX_MEMALIGN)
- free(block);
-#else
- munmap(block, BLOCK_SIZE);
-#endif
-}
-
-void Collector::recordExtraCost(size_t cost)
-{
- // Our frequency of garbage collection tries to balance memory use against speed
- // by collecting based on the number of newly created values. However, for values
- // that hold on to a great deal of memory that's not in the form of other JS values,
- // that is not good enough - in some cases a lot of those objects can pile up and
- // use crazy amounts of memory without a GC happening. So we track these extra
- // memory costs. Only unusually large objects are noted, and we only keep track
- // of this extra cost until the next GC. In garbage collected languages, most values
- // are either very short lived temporaries, or have extremely long lifetimes. So
- // if a large value survives one garbage collection, there is not much point to
- // collecting more frequently as long as it stays alive.
- // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost
-
- primaryHeap.extraCost += cost;
-}
-
-template <Collector::HeapType heapType> struct HeapConstants;
-
-template <> struct HeapConstants<Collector::PrimaryHeap> {
- static const size_t cellSize = CELL_SIZE;
- static const size_t cellsPerBlock = CELLS_PER_BLOCK;
- static const size_t bitmapShift = 0;
- typedef CollectorCell Cell;
- typedef CollectorBlock Block;
-};
-
-template <> struct HeapConstants<Collector::NumberHeap> {
- static const size_t cellSize = SMALL_CELL_SIZE;
- static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
- static const size_t bitmapShift = 1;
- typedef SmallCollectorCell Cell;
- typedef SmallCellCollectorBlock Block;
-};
-
-template <Collector::HeapType heapType> void* Collector::heapAllocate(size_t s)
-{
- typedef typename HeapConstants<heapType>::Block Block;
- typedef typename HeapConstants<heapType>::Cell Cell;
-
- CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
- ASSERT(s <= HeapConstants<heapType>::cellSize);
- UNUSED_PARAM(s); // s is now only used for the above assert
-
- ASSERT(heap.operationInProgress == NoOperation);
- ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
- // FIXME: If another global variable access here doesn't hurt performance
- // too much, we could abort() in NDEBUG builds, which could help ensure we
- // don't spend any time debugging cases where we allocate inside an object's
- // deallocation code.
-
- size_t numLiveObjects = heap.numLiveObjects;
- size_t usedBlocks = heap.usedBlocks;
- size_t i = heap.firstBlockWithPossibleSpace;
-
- // if we have a huge amount of extra cost, we'll try to collect even if we still have
- // free cells left.
- if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) {
- size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
- size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
- const size_t newCost = numNewObjects + heap.extraCost;
- if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect)
- goto collect;
- }
-
- ASSERT(heap.operationInProgress == NoOperation);
-#ifndef NDEBUG
- // FIXME: Consider doing this in NDEBUG builds too (see comment above).
- heap.operationInProgress = Allocation;
-#endif
-
-scan:
- Block* targetBlock;
- size_t targetBlockUsedCells;
- if (i != usedBlocks) {
- targetBlock = (Block*)heap.blocks[i];
- targetBlockUsedCells = targetBlock->usedCells;
- ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
- while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) {
- if (++i == usedBlocks)
- goto collect;
- targetBlock = (Block*)heap.blocks[i];
- targetBlockUsedCells = targetBlock->usedCells;
- ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
- }
- heap.firstBlockWithPossibleSpace = i;
- } else {
-
-collect:
- size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
- size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
- const size_t newCost = numNewObjects + heap.extraCost;
-
- if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) {
-#ifndef NDEBUG
- heap.operationInProgress = NoOperation;
-#endif
- bool collected = collect();
-#ifndef NDEBUG
- heap.operationInProgress = Allocation;
-#endif
- if (collected) {
- numLiveObjects = heap.numLiveObjects;
- usedBlocks = heap.usedBlocks;
- i = heap.firstBlockWithPossibleSpace;
- goto scan;
- }
- }
-
- // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
- size_t numBlocks = heap.numBlocks;
- if (usedBlocks == numBlocks) {
- numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
- heap.numBlocks = numBlocks;
- heap.blocks = static_cast<CollectorBlock **>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock *)));
- }
-
- targetBlock = (Block*)allocateBlock();
- targetBlock->freeList = targetBlock->cells;
- targetBlockUsedCells = 0;
- heap.blocks[usedBlocks] = (CollectorBlock*)targetBlock;
- heap.usedBlocks = usedBlocks + 1;
- heap.firstBlockWithPossibleSpace = usedBlocks;
- }
-
- // find a free spot in the block and detach it from the free list
- Cell *newCell = targetBlock->freeList;
-
- // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized
- targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next;
-
- targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
- heap.numLiveObjects = numLiveObjects + 1;
-
-#ifndef NDEBUG
- // FIXME: Consider doing this in NDEBUG builds too (see comment above).
- heap.operationInProgress = NoOperation;
-#endif
-
- return newCell;
-}
-
-void* Collector::allocate(size_t s)
-{
- return heapAllocate<PrimaryHeap>(s);
-}
-
-void* Collector::allocateNumber(size_t s)
-{
- return heapAllocate<NumberHeap>(s);
-}
-
-static inline void* currentThreadStackBase()
-{
-#if PLATFORM(DARWIN)
- pthread_t thread = pthread_self();
- return pthread_get_stackaddr_np(thread);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- __asm {
- MOV EAX, FS:[18h]
- MOV pTib, EAX
- }
- return (void*)pTib->StackBase;
-#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
- PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
- return (void*)pTib->StackBase;
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- asm ( "movl %%fs:0x18, %0\n"
- : "=r" (pTib)
- );
- return (void*)pTib->StackBase;
-#elif PLATFORM(SOLARIS)
- stack_t s;
- thr_stksegment(&s);
- return s.ss_sp;
-#elif PLATFORM(UNIX)
- static void* stackBase = 0;
- static size_t stackSize = 0;
- static pthread_t stackThread;
- pthread_t thread = pthread_self();
- if (stackBase == 0 || thread != stackThread) {
- pthread_attr_t sattr;
- pthread_attr_init(&sattr);
-#if HAVE(PTHREAD_NP_H)
- // e.g. on FreeBSD 5.4, neundorf@kde.org
- pthread_attr_get_np(thread, &sattr);
-#else
- // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
- pthread_getattr_np(thread, &sattr);
-#endif
- int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
- (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
- ASSERT(stackBase);
- pthread_attr_destroy(&sattr);
- stackThread = thread;
- }
- return static_cast<char*>(stackBase) + stackSize;
-#else
-#error Need a way to get the stack base on this platform
-#endif
-}
-
-#if USE(MULTIPLE_THREADS)
-static pthread_t mainThread;
-#endif
-
-void Collector::registerAsMainThread()
-{
-#if USE(MULTIPLE_THREADS)
- mainThread = pthread_self();
-#endif
-}
-
-static inline bool onMainThread()
-{
-#if USE(MULTIPLE_THREADS)
-#if PLATFORM(DARWIN)
- pthread_t javaScriptCollectionThread = JSJavaScriptCollectionThread();
- return javaScriptCollectionThread == 0 || javaScriptCollectionThread == pthread_self();
-#else
- return !!pthread_equal(pthread_self(), mainThread);
-#endif
-#else
- return true;
-#endif
-}
-
-#if USE(MULTIPLE_THREADS)
-
-#if PLATFORM(DARWIN)
-typedef mach_port_t PlatformThread;
-#elif PLATFORM(WIN_OS)
-struct PlatformThread {
- PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {}
- DWORD id;
- HANDLE handle;
-};
-#endif
-
-static inline PlatformThread getCurrentPlatformThread()
-{
-#if PLATFORM(DARWIN)
- return pthread_mach_thread_np(pthread_self());
-#elif PLATFORM(WIN_OS)
- HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());
- return PlatformThread(GetCurrentThreadId(), threadHandle);
-#endif
-}
-
-class Collector::Thread {
-public:
- Thread(pthread_t pthread, const PlatformThread& platThread, void* base)
- : posixThread(pthread), platformThread(platThread), stackBase(base) {}
- Thread* next;
- pthread_t posixThread;
- PlatformThread platformThread;
- void* stackBase;
-};
-
-pthread_key_t registeredThreadKey;
-pthread_once_t registeredThreadKeyOnce = PTHREAD_ONCE_INIT;
-Collector::Thread* registeredThreads;
-
-static void destroyRegisteredThread(void* data)
-{
- Collector::Thread* thread = (Collector::Thread*)data;
-
- // Can't use JSLock convenience object here because we don't want to re-register
- // an exiting thread.
- JSLock::lock();
-
- if (registeredThreads == thread) {
- registeredThreads = registeredThreads->next;
- } else {
- Collector::Thread *last = registeredThreads;
- Collector::Thread *t;
- for (t = registeredThreads->next; t != NULL; t = t->next) {
- if (t == thread) {
- last->next = t->next;
- break;
- }
- last = t;
- }
- ASSERT(t); // If t is NULL, we never found ourselves in the list.
- }
-
- JSLock::unlock();
-
- delete thread;
-}
-
-static void initializeRegisteredThreadKey()
-{
- pthread_key_create(®isteredThreadKey, destroyRegisteredThread);
-}
-
-void Collector::registerThread()
-{
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- pthread_once(®isteredThreadKeyOnce, initializeRegisteredThreadKey);
-
- if (!pthread_getspecific(registeredThreadKey)) {
-#if PLATFORM(DARWIN)
- if (onMainThread())
- CollectorHeapIntrospector::init(&primaryHeap, &numberHeap);
-#endif
-
- Collector::Thread *thread = new Collector::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
-
- thread->next = registeredThreads;
- registeredThreads = thread;
- pthread_setspecific(registeredThreadKey, thread);
- }
-}
-
-#endif
-
-#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char *) - 1)) == 0)
-
-// cell size needs to be a power of two for this to be valid
-#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)
-
-void Collector::markStackObjectsConservatively(void *start, void *end)
-{
- if (start > end) {
- void* tmp = start;
- start = end;
- end = tmp;
- }
-
- ASSERT(((char*)end - (char*)start) < 0x1000000);
- ASSERT(IS_POINTER_ALIGNED(start));
- ASSERT(IS_POINTER_ALIGNED(end));
-
- char** p = (char**)start;
- char** e = (char**)end;
-
- size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
- size_t usedNumberBlocks = numberHeap.usedBlocks;
- CollectorBlock **primaryBlocks = primaryHeap.blocks;
- CollectorBlock **numberBlocks = numberHeap.blocks;
-
- const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
-
- while (p != e) {
- char* x = *p++;
- if (IS_HALF_CELL_ALIGNED(x) && x) {
- uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
- xAsBits &= CELL_ALIGN_MASK;
- uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
- CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
- // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
- for (size_t block = 0; block < usedNumberBlocks; block++) {
- if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
- Collector::markCell(reinterpret_cast<JSCell*>(xAsBits));
- goto endMarkLoop;
- }
- }
-
- // Mark the primary heap
- for (size_t block = 0; block < usedPrimaryBlocks; block++) {
- if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
- if (((CollectorCell*)xAsBits)->u.freeCell.zeroIfFree != 0) {
- JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
- if (!imp->marked())
- imp->mark();
- }
- break;
- }
- }
- endMarkLoop:
- ;
- }
- }
-}
-
-void Collector::markCurrentThreadConservatively()
-{
- // setjmp forces volatile registers onto the stack
- jmp_buf registers;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
- setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
- void* dummy;
- void* stackPointer = &dummy;
- void* stackBase = currentThreadStackBase();
-
- markStackObjectsConservatively(stackPointer, stackBase);
-}
-
-#if USE(MULTIPLE_THREADS)
-
-static inline void suspendThread(const PlatformThread& platformThread)
-{
-#if PLATFORM(DARWIN)
- thread_suspend(platformThread);
-#elif PLATFORM(WIN_OS)
- SuspendThread(platformThread.handle);
-#else
-#error Need a way to suspend threads on this platform
-#endif
-}
-
-static inline void resumeThread(const PlatformThread& platformThread)
-{
-#if PLATFORM(DARWIN)
- thread_resume(platformThread);
-#elif PLATFORM(WIN_OS)
- ResumeThread(platformThread.handle);
-#else
-#error Need a way to resume threads on this platform
-#endif
-}
-
-typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
-
-#if PLATFORM(DARWIN)
-
-#if PLATFORM(X86)
-typedef i386_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(X86_64)
-typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(PPC)
-typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(PPC64)
-typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(ARM)
-typedef arm_thread_state_t PlatformThreadRegisters;
-#else
-#error Unknown Architecture
-#endif
-
-#elif PLATFORM(WIN_OS)&& PLATFORM(X86)
-typedef CONTEXT PlatformThreadRegisters;
-#else
-#error Need a thread register struct for this platform
-#endif
-
-size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
-{
-#if PLATFORM(DARWIN)
-
-#if PLATFORM(X86)
- unsigned user_count = sizeof(regs)/sizeof(int);
- thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif PLATFORM(X86_64)
- unsigned user_count = x86_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif PLATFORM(PPC)
- unsigned user_count = PPC_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif PLATFORM(PPC64)
- unsigned user_count = PPC_THREAD_STATE64_COUNT;
- thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif PLATFORM(ARM)
- unsigned user_count = ARM_THREAD_STATE_COUNT;
- thread_state_flavor_t flavor = ARM_THREAD_STATE;
-#else
-#error Unknown Architecture
-#endif
-
- kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count);
- if (result != KERN_SUCCESS) {
- WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
- "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
- CRASH();
- }
- return user_count * sizeof(usword_t);
-// end PLATFORM(DARWIN)
-
-#elif PLATFORM(WIN_OS) && PLATFORM(X86)
- regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
- GetThreadContext(platformThread.handle, ®s);
- return sizeof(CONTEXT);
-#else
-#error Need a way to get thread registers on this platform
-#endif
-}
-
-static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
-{
-#if PLATFORM(DARWIN)
-
-#if __DARWIN_UNIX03
-
-#if PLATFORM(X86)
- return (void*)regs.__esp;
-#elif PLATFORM(X86_64)
- return (void*)regs.__rsp;
-#elif PLATFORM(PPC) || PLATFORM(PPC64)
- return (void*)regs.__r1;
-#elif PLATFORM(ARM)
- return (void*)regs.__sp;
-#else
-#error Unknown Architecture
-#endif
-
-#else // !__DARWIN_UNIX03
-
-#if PLATFORM(X86)
- return (void*)regs.esp;
-#elif PLATFORM(X86_64)
- return (void*)regs.rsp;
-#elif (PLATFORM(PPC) || PLATFORM(PPC64))
- return (void*)regs.r1;
-#else
-#error Unknown Architecture
-#endif
-
-#endif // __DARWIN_UNIX03
-
-// end PLATFORM(DARWIN)
-#elif PLATFORM(X86) && PLATFORM(WIN_OS)
- return (void*)(uintptr_t)regs.Esp;
-#else
-#error Need a way to get the stack pointer for another thread on this platform
-#endif
-}
-
-void Collector::markOtherThreadConservatively(Thread* thread)
-{
- suspendThread(thread->platformThread);
-
- PlatformThreadRegisters regs;
- size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
-
- // mark the thread's registers
- markStackObjectsConservatively((void*)®s, (void*)((char*)®s + regSize));
-
- void* stackPointer = otherThreadStackPointer(regs);
- markStackObjectsConservatively(stackPointer, thread->stackBase);
-
- resumeThread(thread->platformThread);
-}
-
-#endif
-
-void Collector::markStackObjectsConservatively()
-{
- markCurrentThreadConservatively();
-
-#if USE(MULTIPLE_THREADS)
- for (Thread *thread = registeredThreads; thread != NULL; thread = thread->next) {
- if (!pthread_equal(thread->posixThread, pthread_self())) {
- markOtherThreadConservatively(thread);
- }
- }
-#endif
-}
-
-typedef HashCountedSet<JSCell*> ProtectCountSet;
-
-static ProtectCountSet& protectedValues()
-{
- static ProtectCountSet staticProtectCountSet;
- return staticProtectCountSet;
-}
-
-void Collector::protect(JSValue *k)
-{
- ASSERT(k);
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (JSImmediate::isImmediate(k))
- return;
-
- protectedValues().add(k->asCell());
-}
-
-void Collector::unprotect(JSValue *k)
-{
- ASSERT(k);
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (JSImmediate::isImmediate(k))
- return;
-
- protectedValues().remove(k->asCell());
-}
-
-void Collector::collectOnMainThreadOnly(JSValue* value)
-{
- ASSERT(value);
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- if (JSImmediate::isImmediate(value))
- return;
-
- JSCell* cell = value->asCell();
- cellBlock(cell)->collectOnMainThreadOnly.set(cellOffset(cell));
- ++mainThreadOnlyObjectCount;
-}
-
-void Collector::markProtectedObjects()
-{
- ProtectCountSet& protectedValues = KJS::protectedValues();
- ProtectCountSet::iterator end = protectedValues.end();
- for (ProtectCountSet::iterator it = protectedValues.begin(); it != end; ++it) {
- JSCell *val = it->first;
- if (!val->marked())
- val->mark();
- }
-}
-
-void Collector::markMainThreadOnlyObjects()
-{
-#if USE(MULTIPLE_THREADS)
- ASSERT(!onMainThread());
-#endif
-
- // Optimization for clients that never register "main thread only" objects.
- if (!mainThreadOnlyObjectCount)
- return;
-
- // FIXME: We can optimize this marking algorithm by keeping an exact set of
- // "main thread only" objects when the "main thread only" object count is
- // small. We don't want to keep an exact set all the time, because WebCore
- // tends to create lots of "main thread only" objects, and all that set
- // thrashing can be expensive.
-
- size_t count = 0;
-
- // We don't look at the numberHeap as primitive values can never be marked as main thread only
- for (size_t block = 0; block < primaryHeap.usedBlocks; block++) {
- ASSERT(count < mainThreadOnlyObjectCount);
-
- CollectorBlock* curBlock = primaryHeap.blocks[block];
- size_t minimumCellsToProcess = curBlock->usedCells;
- for (size_t i = 0; (i < minimumCellsToProcess) & (i < CELLS_PER_BLOCK); i++) {
- CollectorCell* cell = curBlock->cells + i;
- if (cell->u.freeCell.zeroIfFree == 0)
- ++minimumCellsToProcess;
- else {
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- if (!curBlock->marked.get(i)) {
- JSCell* imp = reinterpret_cast<JSCell*>(cell);
- imp->mark();
- }
- if (++count == mainThreadOnlyObjectCount)
- return;
- }
- }
- }
- }
-}
-
-template <Collector::HeapType heapType> size_t Collector::sweep(bool currentThreadIsMainThread)
-{
- typedef typename HeapConstants<heapType>::Block Block;
- typedef typename HeapConstants<heapType>::Cell Cell;
-
- UNUSED_PARAM(currentThreadIsMainThread); // currentThreadIsMainThread is only used in ASSERTs
- // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
- CollectorHeap& heap = heapType == Collector::PrimaryHeap ? primaryHeap : numberHeap;
-
- size_t emptyBlocks = 0;
- size_t numLiveObjects = heap.numLiveObjects;
-
- for (size_t block = 0; block < heap.usedBlocks; block++) {
- Block* curBlock = (Block*)heap.blocks[block];
-
- size_t usedCells = curBlock->usedCells;
- Cell* freeList = curBlock->freeList;
-
- if (usedCells == HeapConstants<heapType>::cellsPerBlock) {
- // special case with a block where all cells are used -- testing indicates this happens often
- for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) {
- if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
- Cell* cell = curBlock->cells + i;
-
- if (heapType != Collector::NumberHeap) {
- JSCell* imp = reinterpret_cast<JSCell*>(cell);
- // special case for allocated but uninitialized object
- // (We don't need this check earlier because nothing prior this point
- // assumes the object has a valid vptr.)
- if (cell->u.freeCell.zeroIfFree == 0)
- continue;
-
- ASSERT(currentThreadIsMainThread || !curBlock->collectOnMainThreadOnly.get(i));
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- curBlock->collectOnMainThreadOnly.clear(i);
- --Collector::mainThreadOnlyObjectCount;
- }
- imp->~JSCell();
- }
-
- --usedCells;
- --numLiveObjects;
-
- // put cell on the free list
- cell->u.freeCell.zeroIfFree = 0;
- cell->u.freeCell.next = freeList - (cell + 1);
- freeList = cell;
- }
- }
- } else {
- size_t minimumCellsToProcess = usedCells;
- for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) {
- Cell *cell = curBlock->cells + i;
- if (cell->u.freeCell.zeroIfFree == 0) {
- ++minimumCellsToProcess;
- } else {
- if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
- if (heapType != Collector::NumberHeap) {
- JSCell *imp = reinterpret_cast<JSCell*>(cell);
- ASSERT(currentThreadIsMainThread || !curBlock->collectOnMainThreadOnly.get(i));
- if (curBlock->collectOnMainThreadOnly.get(i)) {
- curBlock->collectOnMainThreadOnly.clear(i);
- --Collector::mainThreadOnlyObjectCount;
- }
- imp->~JSCell();
- }
- --usedCells;
- --numLiveObjects;
-
- // put cell on the free list
- cell->u.freeCell.zeroIfFree = 0;
- cell->u.freeCell.next = freeList - (cell + 1);
- freeList = cell;
- }
- }
- }
- }
-
- curBlock->usedCells = static_cast<uint32_t>(usedCells);
- curBlock->freeList = freeList;
- curBlock->marked.clearAll();
-
- if (usedCells == 0) {
- emptyBlocks++;
- if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
-#if !DEBUG_COLLECTOR
- freeBlock((CollectorBlock*)curBlock);
-#endif
- // swap with the last block so we compact as we go
- heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
- heap.usedBlocks--;
- block--; // Don't move forward a step in this case
-
- if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
- heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
- heap.blocks = (CollectorBlock**)fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock *));
- }
- }
- }
- }
-
- if (heap.numLiveObjects != numLiveObjects)
- heap.firstBlockWithPossibleSpace = 0;
-
- heap.numLiveObjects = numLiveObjects;
- heap.numLiveObjectsAtLastCollect = numLiveObjects;
- heap.extraCost = 0;
- return numLiveObjects;
-}
-
-bool Collector::collect()
-{
- ASSERT(JSLock::lockCount() > 0);
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
- if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
- abort();
-
- primaryHeap.operationInProgress = Collection;
- numberHeap.operationInProgress = Collection;
-
- bool currentThreadIsMainThread = onMainThread();
-
- // MARK: first mark all referenced objects recursively starting out from the set of root objects
-
-#ifndef NDEBUG
- // Forbid malloc during the mark phase. Marking a thread suspends it, so
- // a malloc inside mark() would risk a deadlock with a thread that had been
- // suspended while holding the malloc lock.
- fastMallocForbid();
-#endif
-
- markStackObjectsConservatively();
- markProtectedObjects();
- ExecState::markActiveExecStates();
- List::markProtectedLists();
-#if USE(MULTIPLE_THREADS)
- if (!currentThreadIsMainThread)
- markMainThreadOnlyObjects();
-#endif
-
-#ifndef NDEBUG
- fastMallocAllow();
-#endif
-
- size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
- size_t numLiveObjects = sweep<PrimaryHeap>(currentThreadIsMainThread);
- numLiveObjects += sweep<NumberHeap>(currentThreadIsMainThread);
-
- primaryHeap.operationInProgress = NoOperation;
- numberHeap.operationInProgress = NoOperation;
-
- return numLiveObjects < originalLiveObjects;
-}
-
-size_t Collector::size()
-{
- return primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
-}
-
-size_t Collector::globalObjectCount()
-{
- size_t count = 0;
- if (JSGlobalObject::head()) {
- JSGlobalObject* o = JSGlobalObject::head();
- do {
- ++count;
- o = o->next();
- } while (o != JSGlobalObject::head());
- }
- return count;
-}
-
-size_t Collector::protectedGlobalObjectCount()
-{
- size_t count = 0;
- if (JSGlobalObject::head()) {
- JSGlobalObject* o = JSGlobalObject::head();
- do {
- if (protectedValues().contains(o))
- ++count;
- o = o->next();
- } while (o != JSGlobalObject::head());
- }
- return count;
-}
-
-size_t Collector::protectedObjectCount()
-{
- return protectedValues().size();
-}
-
-static const char *typeName(JSCell *val)
-{
- const char *name = "???";
- switch (val->type()) {
- case UnspecifiedType:
- break;
- case UndefinedType:
- name = "undefined";
- break;
- case NullType:
- name = "null";
- break;
- case BooleanType:
- name = "boolean";
- break;
- case StringType:
- name = "string";
- break;
- case NumberType:
- name = "number";
- break;
- case ObjectType: {
- const ClassInfo *info = static_cast<JSObject *>(val)->classInfo();
- name = info ? info->className : "Object";
- break;
- }
- case GetterSetterType:
- name = "gettersetter";
- break;
- }
- return name;
-}
-
-HashCountedSet<const char*>* Collector::protectedObjectTypeCounts()
-{
- HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
-
- ProtectCountSet& protectedValues = KJS::protectedValues();
- ProtectCountSet::iterator end = protectedValues.end();
- for (ProtectCountSet::iterator it = protectedValues.begin(); it != end; ++it)
- counts->add(typeName(it->first));
-
- return counts;
-}
-
-bool Collector::isBusy()
-{
- return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
-}
-
-void Collector::reportOutOfMemoryToAllExecStates()
-{
- ExecStateStack::const_iterator end = ExecState::activeExecStates().end();
- for (ExecStateStack::const_iterator it = ExecState::activeExecStates().begin(); it != end; ++it) {
- (*it)->setException(Error::create(*it, GeneralError, "Out of memory"));
- }
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJSCOLLECTOR_H_
-#define KJSCOLLECTOR_H_
-
-#include <string.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/Platform.h>
-
-namespace KJS {
-
- class JSCell;
- class JSValue;
- class CollectorBlock;
-
- class Collector {
- public:
- static void* allocate(size_t s);
- static void* allocateNumber(size_t s);
- static bool collect();
- static bool isBusy(); // true if an allocation or collection is in progress
-
- static const size_t minExtraCostSize = 256;
-
- static void reportExtraMemoryCost(size_t cost);
-
- static size_t size();
-
- static void protect(JSValue*);
- static void unprotect(JSValue*);
-
- static void collectOnMainThreadOnly(JSValue*);
-
- static size_t globalObjectCount();
- static size_t protectedObjectCount();
- static size_t protectedGlobalObjectCount();
- static HashCountedSet<const char*>* protectedObjectTypeCounts();
-
- class Thread;
- static void registerThread();
-
- static void registerAsMainThread();
-
- static bool isCellMarked(const JSCell*);
- static void markCell(JSCell*);
-
- enum HeapType { PrimaryHeap, NumberHeap };
-
- private:
- template <Collector::HeapType heapType> static void* heapAllocate(size_t s);
- template <Collector::HeapType heapType> static size_t sweep(bool);
- static const CollectorBlock* cellBlock(const JSCell*);
- static CollectorBlock* cellBlock(JSCell*);
- static size_t cellOffset(const JSCell*);
-
- Collector();
-
- static void recordExtraCost(size_t);
- static void markProtectedObjects();
- static void markMainThreadOnlyObjects();
- static void markCurrentThreadConservatively();
- static void markOtherThreadConservatively(Thread*);
- static void markStackObjectsConservatively();
- static void markStackObjectsConservatively(void* start, void* end);
-
- static size_t mainThreadOnlyObjectCount;
- static bool memoryFull;
- static void reportOutOfMemoryToAllExecStates();
- };
-
- // tunable parameters
- template<size_t bytesPerWord> struct CellSize;
-
- // cell size needs to be a power of two for certain optimizations in collector.cpp
- template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit
- template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit
- const size_t BLOCK_SIZE = 16 * 4096; // 64k
-
- // derived constants
- const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
- const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
- const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
- const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
- const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
- const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
- const size_t CELL_MASK = CELL_SIZE - 1;
- const size_t CELL_ALIGN_MASK = ~CELL_MASK;
- const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
- const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
- const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
- const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
-
- struct CollectorBitmap {
- uint32_t bits[BITMAP_WORDS];
- bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); }
- void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); }
- void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); }
- void clearAll() { memset(bits, 0, sizeof(bits)); }
- };
-
- struct CollectorCell {
- union {
- double memory[CELL_ARRAY_LENGTH];
- struct {
- void* zeroIfFree;
- ptrdiff_t next;
- } freeCell;
- } u;
- };
-
- struct SmallCollectorCell {
- union {
- double memory[CELL_ARRAY_LENGTH / 2];
- struct {
- void* zeroIfFree;
- ptrdiff_t next;
- } freeCell;
- } u;
- };
-
- class CollectorBlock {
- public:
- CollectorCell cells[CELLS_PER_BLOCK];
- uint32_t usedCells;
- CollectorCell* freeList;
- CollectorBitmap marked;
- CollectorBitmap collectOnMainThreadOnly;
- };
-
- class SmallCellCollectorBlock {
- public:
- SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
- uint32_t usedCells;
- SmallCollectorCell* freeList;
- CollectorBitmap marked;
- CollectorBitmap collectOnMainThreadOnly;
- };
-
- inline const CollectorBlock* Collector::cellBlock(const JSCell* cell)
- {
- return reinterpret_cast<const CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
- }
-
- inline CollectorBlock* Collector::cellBlock(JSCell* cell)
- {
- return const_cast<CollectorBlock*>(cellBlock(const_cast<const JSCell*>(cell)));
- }
-
- inline size_t Collector::cellOffset(const JSCell* cell)
- {
- return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
- }
-
- inline bool Collector::isCellMarked(const JSCell* cell)
- {
- return cellBlock(cell)->marked.get(cellOffset(cell));
- }
-
- inline void Collector::markCell(JSCell* cell)
- {
- cellBlock(cell)->marked.set(cellOffset(cell));
- }
-
- inline void Collector::reportExtraMemoryCost(size_t cost)
- {
- if (cost > minExtraCostSize)
- recordExtraCost(cost / (CELL_SIZE * 2));
- }
-
-} // namespace KJS
-
-#endif /* KJSCOLLECTOR_H_ */
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_COMPLETION_H
-#define KJS_COMPLETION_H
-
-namespace KJS {
-
- class JSValue;
-
- enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted };
-
- /**
- * Completion objects are used to convey the return status and value
- * from functions.
- *
- * See FunctionImp::execute()
- *
- * @see FunctionImp
- *
- * @short Handle for a Completion type.
- */
- class Completion {
- public:
- Completion(ComplType type = Normal, JSValue* value = 0)
- : m_type(type), m_value(value) { }
-
- ComplType complType() const { return m_type; }
- JSValue* value() const { return m_value; }
- void setValue(JSValue* v) { m_value = v; }
- bool isValueCompletion() const { return !!m_value; }
-
- private:
- ComplType m_type;
- JSValue* m_value;
- };
-
-}
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include <wtf/Platform.h>
-
-
-#if PLATFORM(DARWIN)
-
-#define HAVE_ERRNO_H 1
-#define HAVE_MADV_DONTNEED 1
-#define HAVE_MMAP 1
-#define HAVE_MERGESORT 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_TIMEB_H 1
-
-#elif PLATFORM(WIN_OS)
-
-// If we don't define these, they get defined in windef.h.
-// We want to use std::min and std::max
-#define max max
-#define min min
-
-#if !COMPILER(MSVC7)
-// We need to define this before the first #include of stdlib.h or it won't contain rand_s.
-#ifndef _CRT_RAND_S
-#define _CRT_RAND_S
-#endif
-#endif
-
-#define HAVE_FLOAT_H 1
-#define HAVE_SYS_TIMEB_H 1
-#define HAVE_VIRTUALALLOC 1
-
-#else
-
-/* FIXME: is this actually used or do other platforms generate their own config.h? */
-
-#define HAVE_ERRNO_H 1
-#define HAVE_MMAP 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_TIME_H 1
-
-#endif
-
-#if PLATFORM(FREEBSD)
-#define HAVE_PTHREAD_NP_H 1
-#endif
-
-/* FIXME: if all platforms have these, do they really need #defines? */
-#define HAVE_STDINT_H 1
-#define HAVE_STRING_H 1
-
-#define WTF_CHANGES 1
-
-#ifdef __cplusplus
-#undef new
-#undef delete
-#include <wtf/FastMalloc.h>
-#endif
-
-// this breaks compilation of <QFontDatabase>, at least, so turn it off for now
-// Also generates errors on wx on Windows, because these functions
-// are used from wx headers.
-#if !PLATFORM(QT) && !PLATFORM(WX)
-#include <wtf/DisallowCType.h>
-#endif
+++ /dev/null
-#! /usr/bin/perl -w
-#
-# Static Hashtable Generator
-#
-# (c) 2000-2002 by Harri Porten <porten@kde.org> and
-# David Faure <faure@kde.org>
-# Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org>
-# Copyright (C) 2007 Apple Inc. All rights reserved.
-#
-# Part of the KJS library.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-use strict;
-
-my $file = $ARGV[0];
-shift;
-my $includelookup = 0;
-
-# Use -i as second argument to make it include "lookup.h"
-$includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i");
-
-# Use -n as second argument to make it use the third argument as namespace parameter ie. -n KDOM
-my $useNameSpace = $ARGV[1] if (defined($ARGV[0]) && $ARGV[0] eq "-n");
-
-print STDERR "Creating hashtable for $file\n";
-open(IN, $file) or die "No such file $file";
-
-my @keys = ();
-my @values = ();
-my @attrs = ();
-my @params = ();
-my @hashes = ();
-my @table = ();
-my @links = ();
-
-my $inside = 0;
-my $name;
-my $size;
-my $hashSizeMask;
-my $banner = 0;
-sub calcTable();
-sub output();
-sub hashValue($);
-
-while (<IN>) {
- chop;
- s/^\s*//g;
- if (/^\#|^$/) {
- # comment. do nothing
- } elsif (/^\@begin/ && !$inside) {
- if (/^\@begin\s*([:_\w]+)\s*\d*\s*$/) {
- $inside = 1;
- $name = $1;
- } else {
- printf STDERR "WARNING: \@begin without table name and hashsize, skipping $_\n";
- }
- } elsif (/^\@end\s*$/ && $inside) {
-
- calcTable();
-
- output();
- @keys = ();
- @values = ();
- @attrs = ();
- @params = ();
- @table = ();
- @links = ();
- @hashes = ();
- $inside = 0;
- } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) {
- my $key = $1;
- my $val = $2;
- my $att = $3;
- my $param = $4;
- push(@keys, $key);
- push(@values, $val);
- push(@hashes, hashValue($key));
- printf STDERR "WARNING: Number of arguments missing for $key/$val\n"
- if ( $att =~ m/Function/ && length($param) == 0);
- push(@attrs, length($att) > 0 ? $att : "0");
- push(@params, length($param) > 0 ? $param : "0");
- } elsif ($inside) {
- die "invalid data {" . $_ . "}";
- }
-}
-
-die "missing closing \@end" if ($inside);
-
-sub ceilingToPowerOf2
-{
- my ($size) = @_;
-
- my $powerOf2 = 1;
- while ($size > $powerOf2) {
- $powerOf2 <<= 1;
- }
-
- return $powerOf2;
-}
-
-sub calcTable() {
- my $hashsize = ceilingToPowerOf2(2 * @keys);
- $hashSizeMask = $hashsize - 1;
- $size = $hashsize;
- my $collisions = 0;
- my $maxdepth = 0;
- my $i = 0;
- foreach my $key (@keys) {
- my $depth = 0;
- my $h = hashValue($key) % $hashsize;
- while (defined($table[$h])) {
- if (defined($links[$h])) {
- $h = $links[$h];
- $depth++;
- } else {
- $collisions++;
- $links[$h] = $size;
- $h = $size;
- $size++;
- }
- }
- $table[$h] = $i;
- $i++;
- $maxdepth = $depth if ( $depth > $maxdepth);
- }
-
- # Ensure table is big enough (in case of undef entries at the end)
- if ( $#table+1 < $size ) {
- $#table = $size-1;
- }
-}
-
-sub leftShift($$) {
- my ($value, $distance) = @_;
- return (($value << $distance) & 0xFFFFFFFF);
-}
-
-# Paul Hsieh's SuperFastHash
-# http://www.azillionmonkeys.com/qed/hash.html
-# Ported from UString..
-sub hashValue($) {
- my @chars = split(/ */, $_[0]);
-
- # This hash is designed to work on 16-bit chunks at a time. But since the normal case
- # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
- # were 16-bit chunks, which should give matching results
-
- my $EXP2_32 = 4294967296;
-
- my $hash = 0x9e3779b9;
- my $l = scalar @chars; #I wish this was in Ruby --- Maks
- my $rem = $l & 1;
- $l = $l >> 1;
-
- my $s = 0;
-
- # Main loop
- for (; $l > 0; $l--) {
- $hash += ord($chars[$s]);
- my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
- $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
- $s += 2;
- $hash += $hash >> 11;
- $hash %= $EXP2_32;
- }
-
- # Handle end case
- if ($rem !=0) {
- $hash += ord($chars[$s]);
- $hash ^= (leftShift($hash, 11)% $EXP2_32);
- $hash += $hash >> 17;
- }
-
- # Force "avalanching" of final 127 bits
- $hash ^= leftShift($hash, 3);
- $hash += ($hash >> 5);
- $hash = ($hash% $EXP2_32);
- $hash ^= (leftShift($hash, 2)% $EXP2_32);
- $hash += ($hash >> 15);
- $hash = $hash% $EXP2_32;
- $hash ^= (leftShift($hash, 10)% $EXP2_32);
-
- # this avoids ever returning a hash code of 0, since that is used to
- # signal "hash not computed yet", using a value that is likely to be
- # effectively the same as 0 when the low bits are masked
- $hash = 0x80000000 if ($hash == 0);
-
- return $hash;
-}
-
-sub output() {
- if (!$banner) {
- $banner = 1;
- print "/* Automatically generated from $file using $0. DO NOT EDIT ! */\n";
- }
-
- my $nameEntries = "${name}Entries";
- $nameEntries =~ s/:/_/g;
-
- print "\n#include \"lookup.h\"\n" if ($includelookup);
- if ($useNameSpace) {
- print "\nnamespace ${useNameSpace}\n{\n";
- print "\nusing namespace KJS;";
- } else {
- print "\nnamespace KJS {\n";
- }
- print "\nstatic const struct HashEntry ".$nameEntries."[] = {\n";
- my $i = 0;
-
- foreach my $entry (@table) {
- if (defined($entry)) {
- my $key = $keys[$entry];
- print " \{ \"" . $key . "\"";
- print ", { (intptr_t)" . $values[$entry] . " }";
- print ", " . $attrs[$entry];
- print ", " . $params[$entry];
- print ", ";
- if (defined($links[$i])) {
- print "&" . $nameEntries . "[" . $links[$i] . "]" . " \}";
- } else {
- print "0 \}"
- }
- print "/* " . $hashes[$entry] . " */ ";
- } else {
- print " { 0, { 0 }, 0, 0, 0 }";
- }
- print "," unless ($i == $size - 1);
- print "\n";
- $i++;
- }
-
- print "};\n\n";
- print "const struct HashTable $name = ";
- print "\{ 3, $size, $nameEntries, $hashSizeMask \};\n\n";
- print "} // namespace\n";
-}
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- *
- */
-
-#include "config.h"
-#include "date_object.h"
-#include "date_object.lut.h"
-#include "internal.h"
-
-#if HAVE(ERRNO_H)
-#include <errno.h>
-#endif
-
-#if HAVE(SYS_PARAM_H)
-#include <sys/param.h>
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if HAVE(SYS_TIMEB_H)
-#include <sys/timeb.h>
-#endif
-
-#include <float.h>
-#include <limits.h>
-#include <locale.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "error_object.h"
-#include "operations.h"
-#include "DateMath.h"
-
-#include <wtf/ASCIICType.h>
-#include <wtf/Assertions.h>
-#include <wtf/MathExtras.h>
-#include <wtf/StringExtras.h>
-#include <wtf/UnusedParam.h>
-
- #include <CoreFoundation/CoreFoundation.h>
-
-using namespace WTF;
-
-namespace KJS {
-
-static double parseDate(const UString&);
-static double timeClip(double);
-
-inline int gmtoffset(const GregorianDateTime& t)
-{
- return t.utcOffset;
-}
-
-
-/**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Date object
- */
-class DateObjectFuncImp : public InternalFunctionImp {
-public:
- DateObjectFuncImp(ExecState *, FunctionPrototype *, int i, int len, const Identifier& );
-
- virtual JSValue *callAsFunction(ExecState *, JSObject *thisObj, const List &args);
-
- enum { Parse, UTC };
-
-private:
- int id;
-};
-
-
-static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
-{
- if (string == "short")
- return kCFDateFormatterShortStyle;
- if (string == "medium")
- return kCFDateFormatterMediumStyle;
- if (string == "long")
- return kCFDateFormatterLongStyle;
- if (string == "full")
- return kCFDateFormatterFullStyle;
- return defaultStyle;
-}
-
-static UString formatLocaleDate(ExecState *exec, double time, bool includeDate, bool includeTime, const List &args)
-{
- CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
- CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
-
- bool useCustomFormat = false;
- UString customFormatString;
-
- UString arg0String = args[0]->toString(exec);
- if (arg0String == "custom" && !args[1]->isUndefined()) {
- useCustomFormat = true;
- customFormatString = args[1]->toString(exec);
- } else if (includeDate && includeTime && !args[1]->isUndefined()) {
- dateStyle = styleFromArgString(arg0String, dateStyle);
- timeStyle = styleFromArgString(args[1]->toString(exec), timeStyle);
- } else if (includeDate && !args[0]->isUndefined()) {
- dateStyle = styleFromArgString(arg0String, dateStyle);
- } else if (includeTime && !args[0]->isUndefined()) {
- timeStyle = styleFromArgString(arg0String, timeStyle);
- }
-
- CFLocaleRef locale = CFLocaleCopyCurrent();
- CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
- CFRelease(locale);
-
- if (useCustomFormat) {
- CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size());
- CFDateFormatterSetFormat(formatter, customFormatCFString);
- CFRelease(customFormatCFString);
- }
-
- CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970);
-
- CFRelease(formatter);
-
- // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
- // That's not great error handling, but it just won't happen so it doesn't matter.
- UChar buffer[200];
- const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
- size_t length = CFStringGetLength(string);
- ASSERT(length <= bufferLength);
- if (length > bufferLength)
- length = bufferLength;
- CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer));
-
- CFRelease(string);
-
- return UString(buffer, length);
-}
-
-
-static UString formatDate(const GregorianDateTime &t)
-{
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
- weekdayName[(t.weekDay + 6) % 7],
- monthName[t.month], t.monthDay, t.year + 1900);
- return buffer;
-}
-
-static UString formatDateUTCVariant(const GregorianDateTime &t)
-{
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
- weekdayName[(t.weekDay + 6) % 7],
- t.monthDay, monthName[t.month], t.year + 1900);
- return buffer;
-}
-
-static UString formatTime(const GregorianDateTime &t, bool utc)
-{
- char buffer[100];
- if (utc) {
- snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
- } else {
- int offset = abs(gmtoffset(t));
- char tzname[70];
- struct tm gtm = t;
- strftime(tzname, sizeof(tzname), "%Z", >m);
-
- if (tzname[0]) {
- snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
- t.hour, t.minute, t.second,
- gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname);
- } else {
- snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
- t.hour, t.minute, t.second,
- gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
- }
- }
- return UString(buffer);
-}
-
-// Converts a list of arguments sent to a Date member function into milliseconds, updating
-// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
-//
-// Format of member function: f([hour,] [min,] [sec,] [ms])
-static void fillStructuresUsingTimeArgs(ExecState* exec, const List& args, int maxArgs, double* ms, GregorianDateTime* t)
-{
- double milliseconds = 0;
- int idx = 0;
- int numArgs = args.size();
-
- // JS allows extra trailing arguments -- ignore them
- if (numArgs > maxArgs)
- numArgs = maxArgs;
-
- // hours
- if (maxArgs >= 4 && idx < numArgs) {
- t->hour = 0;
- milliseconds += args[idx++]->toInt32(exec) * msPerHour;
- }
-
- // minutes
- if (maxArgs >= 3 && idx < numArgs) {
- t->minute = 0;
- milliseconds += args[idx++]->toInt32(exec) * msPerMinute;
- }
-
- // seconds
- if (maxArgs >= 2 && idx < numArgs) {
- t->second = 0;
- milliseconds += args[idx++]->toInt32(exec) * msPerSecond;
- }
-
- // milliseconds
- if (idx < numArgs)
- milliseconds += args[idx]->toNumber(exec);
- else
- milliseconds += *ms;
-
- *ms = milliseconds;
-}
-
-// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
-// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
-//
-// Format of member function: f([years,] [months,] [days])
-static void fillStructuresUsingDateArgs(ExecState *exec, const List &args, int maxArgs, double *ms, GregorianDateTime *t)
-{
- int idx = 0;
- int numArgs = args.size();
-
- // JS allows extra trailing arguments -- ignore them
- if (numArgs > maxArgs)
- numArgs = maxArgs;
-
- // years
- if (maxArgs >= 3 && idx < numArgs)
- t->year = args[idx++]->toInt32(exec) - 1900;
-
- // months
- if (maxArgs >= 2 && idx < numArgs)
- t->month = args[idx++]->toInt32(exec);
-
- // days
- if (idx < numArgs) {
- t->monthDay = 0;
- *ms += args[idx]->toInt32(exec) * msPerDay;
- }
-}
-
-// ------------------------------ DateInstance ------------------------------
-
-const ClassInfo DateInstance::info = {"Date", 0, 0};
-
-DateInstance::DateInstance(JSObject *proto)
- : JSWrapperObject(proto)
-{
-}
-
-bool DateInstance::getTime(GregorianDateTime &t, int &offset) const
-{
- double milli = internalValue()->getNumber();
- if (isnan(milli))
- return false;
-
- msToGregorianDateTime(milli, false, t);
- offset = gmtoffset(t);
- return true;
-}
-
-bool DateInstance::getUTCTime(GregorianDateTime &t) const
-{
- double milli = internalValue()->getNumber();
- if (isnan(milli))
- return false;
-
- msToGregorianDateTime(milli, true, t);
- return true;
-}
-
-bool DateInstance::getTime(double &milli, int &offset) const
-{
- milli = internalValue()->getNumber();
- if (isnan(milli))
- return false;
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, false, t);
- offset = gmtoffset(t);
- return true;
-}
-
-bool DateInstance::getUTCTime(double &milli) const
-{
- milli = internalValue()->getNumber();
- if (isnan(milli))
- return false;
-
- return true;
-}
-
-static inline bool isTime_tSigned()
-{
- time_t minusOne = (time_t)(-1);
- return minusOne < 0;
-}
-
-// ------------------------------ DatePrototype -----------------------------
-
-const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, &dateTable};
-
-/* Source for date_object.lut.h
- FIXMEL We could use templates to simplify the UTC variants.
-@begin dateTable 61
- toString dateProtoFuncToString DontEnum|Function 0
- toUTCString dateProtoFuncToUTCString DontEnum|Function 0
- toDateString dateProtoFuncToDateString DontEnum|Function 0
- toTimeString dateProtoFuncToTimeString DontEnum|Function 0
- toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
- toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
- toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
- valueOf dateProtoFuncValueOf DontEnum|Function 0
- getTime dateProtoFuncGetTime DontEnum|Function 0
- getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
- getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
- toGMTString dateProtoFuncToGMTString DontEnum|Function 0
- getMonth dateProtoFuncGetMonth DontEnum|Function 0
- getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
- getDate dateProtoFuncGetDate DontEnum|Function 0
- getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
- getDay dateProtoFuncGetDay DontEnum|Function 0
- getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
- getHours dateProtoFuncGetHours DontEnum|Function 0
- getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
- getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
- getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
- getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
- getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
- getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
- getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
- getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
- setTime dateProtoFuncSetTime DontEnum|Function 1
- setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
- setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
- setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
- setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
- setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
- setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
- setHours dateProtoFuncSetHours DontEnum|Function 4
- setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
- setDate dateProtoFuncSetDate DontEnum|Function 1
- setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
- setMonth dateProtoFuncSetMonth DontEnum|Function 2
- setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
- setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
- setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
- setYear dateProtoFuncSetYear DontEnum|Function 1
- getYear dateProtoFuncGetYear DontEnum|Function 0
-@end
-*/
-// ECMA 15.9.4
-
-DatePrototype::DatePrototype(ExecState *, ObjectPrototype *objectProto)
- : DateInstance(objectProto)
-{
- setInternalValue(jsNaN());
- // The constructor will be added later, after DateObjectImp has been built.
-}
-
-bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getStaticFunctionSlot<JSObject>(exec, &dateTable, this, propertyName, slot);
-}
-
-// ------------------------------ DateObjectImp --------------------------------
-
-// TODO: MakeTime (15.9.11.1) etc. ?
-
-DateObjectImp::DateObjectImp(ExecState* exec, FunctionPrototype* funcProto, DatePrototype* dateProto)
- : InternalFunctionImp(funcProto, dateProto->classInfo()->className)
-{
- static const Identifier* parsePropertyName = new Identifier("parse");
- static const Identifier* UTCPropertyName = new Identifier("UTC");
-
- putDirect(exec->propertyNames().prototype, dateProto, DontEnum|DontDelete|ReadOnly);
- putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::Parse, 1, *parsePropertyName), DontEnum);
- putDirectFunction(new DateObjectFuncImp(exec, funcProto, DateObjectFuncImp::UTC, 7, *UTCPropertyName), DontEnum);
- putDirect(exec->propertyNames().length, 7, ReadOnly|DontDelete|DontEnum);
-}
-
-bool DateObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.9.3
-JSObject *DateObjectImp::construct(ExecState *exec, const List &args)
-{
- int numArgs = args.size();
-
- double value;
-
- if (numArgs == 0) { // new Date() ECMA 15.9.3.3
- value = getCurrentUTCTime();
- } else if (numArgs == 1) {
- if (args[0]->isObject(&DateInstance::info))
- value = static_cast<DateInstance*>(args[0])->internalValue()->toNumber(exec);
- else {
- JSValue* primitive = args[0]->toPrimitive(exec);
- if (primitive->isString())
- value = parseDate(primitive->getString());
- else
- value = primitive->toNumber(exec);
- }
- } else {
- if (isnan(args[0]->toNumber(exec))
- || isnan(args[1]->toNumber(exec))
- || (numArgs >= 3 && isnan(args[2]->toNumber(exec)))
- || (numArgs >= 4 && isnan(args[3]->toNumber(exec)))
- || (numArgs >= 5 && isnan(args[4]->toNumber(exec)))
- || (numArgs >= 6 && isnan(args[5]->toNumber(exec)))
- || (numArgs >= 7 && isnan(args[6]->toNumber(exec)))) {
- value = NaN;
- } else {
- GregorianDateTime t;
- int year = args[0]->toInt32(exec);
- t.year = (year >= 0 && year <= 99) ? year : year - 1900;
- t.month = args[1]->toInt32(exec);
- t.monthDay = (numArgs >= 3) ? args[2]->toInt32(exec) : 1;
- t.hour = args[3]->toInt32(exec);
- t.minute = args[4]->toInt32(exec);
- t.second = args[5]->toInt32(exec);
- t.isDST = -1;
- double ms = (numArgs >= 7) ? args[6]->toNumber(exec) : 0;
- value = gregorianDateTimeToMS(t, ms, false);
- }
- }
-
- DateInstance *ret = new DateInstance(exec->lexicalGlobalObject()->datePrototype());
- ret->setInternalValue(jsNumber(timeClip(value)));
- return ret;
-}
-
-// ECMA 15.9.2
-JSValue *DateObjectImp::callAsFunction(ExecState * /*exec*/, JSObject * /*thisObj*/, const List &/*args*/)
-{
- time_t t = time(0);
- GregorianDateTime ts(*localtime(&t));
- return jsString(formatDate(ts) + " " + formatTime(ts, false));
-}
-
-// ------------------------------ DateObjectFuncImp ----------------------------
-
-DateObjectFuncImp::DateObjectFuncImp(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name), id(i)
-{
- putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
-}
-
-// ECMA 15.9.4.2 - 3
-JSValue *DateObjectFuncImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- if (id == Parse) {
- return jsNumber(parseDate(args[0]->toString(exec)));
- }
- else { // UTC
- int n = args.size();
- if (isnan(args[0]->toNumber(exec))
- || isnan(args[1]->toNumber(exec))
- || (n >= 3 && isnan(args[2]->toNumber(exec)))
- || (n >= 4 && isnan(args[3]->toNumber(exec)))
- || (n >= 5 && isnan(args[4]->toNumber(exec)))
- || (n >= 6 && isnan(args[5]->toNumber(exec)))
- || (n >= 7 && isnan(args[6]->toNumber(exec)))) {
- return jsNaN();
- }
-
- GregorianDateTime t;
- memset(&t, 0, sizeof(t));
- int year = args[0]->toInt32(exec);
- t.year = (year >= 0 && year <= 99) ? year : year - 1900;
- t.month = args[1]->toInt32(exec);
- t.monthDay = (n >= 3) ? args[2]->toInt32(exec) : 1;
- t.hour = args[3]->toInt32(exec);
- t.minute = args[4]->toInt32(exec);
- t.second = args[5]->toInt32(exec);
- double ms = (n >= 7) ? args[6]->toNumber(exec) : 0;
- return jsNumber(gregorianDateTimeToMS(t, ms, true));
- }
-}
-
-// -----------------------------------------------------------------------------
-
-// Code originally from krfcdate.cpp, but we don't want to use kdecore, and we want double range.
-
-static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
-{
- double days = (day - 32075)
- + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
- + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
- - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
- - 2440588;
- return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
-}
-
-// We follow the recommendation of RFC 2822 to consider all
-// obsolete time zones not listed here equivalent to "-0000".
-static const struct KnownZone {
-#if !PLATFORM(WIN_OS)
- const
-#endif
- char tzName[4];
- int tzOffset;
-} known_zones[] = {
- { "UT", 0 },
- { "GMT", 0 },
- { "EST", -300 },
- { "EDT", -240 },
- { "CST", -360 },
- { "CDT", -300 },
- { "MST", -420 },
- { "MDT", -360 },
- { "PST", -480 },
- { "PDT", -420 }
-};
-
-inline static void skipSpacesAndComments(const char*& s)
-{
- int nesting = 0;
- char ch;
- while ((ch = *s)) {
- if (!isASCIISpace(ch)) {
- if (ch == '(')
- nesting++;
- else if (ch == ')' && nesting > 0)
- nesting--;
- else if (nesting == 0)
- break;
- }
- s++;
- }
-}
-
-// returns 0-11 (Jan-Dec); -1 on failure
-static int findMonth(const char* monthStr)
-{
- ASSERT(monthStr);
- char needle[4];
- for (int i = 0; i < 3; ++i) {
- if (!*monthStr)
- return -1;
- needle[i] = static_cast<char>(toASCIILower(*monthStr++));
- }
- needle[3] = '\0';
- const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
- const char *str = strstr(haystack, needle);
- if (str) {
- int position = static_cast<int>(str - haystack);
- if (position % 3 == 0)
- return position / 3;
- }
- return -1;
-}
-
-static double parseDate(const UString &date)
-{
- // This parses a date in the form:
- // Tuesday, 09-Nov-99 23:12:40 GMT
- // or
- // Sat, 01-Jan-2000 08:00:00 GMT
- // or
- // Sat, 01 Jan 2000 08:00:00 GMT
- // or
- // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
- // ### non RFC formats, added for Javascript:
- // [Wednesday] January 09 1999 23:12:40 GMT
- // [Wednesday] January 09 23:12:40 GMT 1999
- //
- // We ignore the weekday.
-
- CString dateCString = date.UTF8String();
- const char *dateString = dateCString.c_str();
-
- // Skip leading space
- skipSpacesAndComments(dateString);
-
- long month = -1;
- const char *wordStart = dateString;
- // Check contents of first words if not number
- while (*dateString && !isASCIIDigit(*dateString)) {
- if (isASCIISpace(*dateString) || *dateString == '(') {
- if (dateString - wordStart >= 3)
- month = findMonth(wordStart);
- skipSpacesAndComments(dateString);
- wordStart = dateString;
- } else
- dateString++;
- }
-
- // Missing delimiter between month and day (like "January29")?
- if (month == -1 && wordStart != dateString)
- month = findMonth(wordStart);
-
- skipSpacesAndComments(dateString);
-
- if (!*dateString)
- return NaN;
-
- // ' 09-Nov-99 23:12:40 GMT'
- char *newPosStr;
- errno = 0;
- long day = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
-
- if (!*dateString)
- return NaN;
-
- if (day < 0)
- return NaN;
-
- long year = 0;
- if (day > 31) {
- // ### where is the boundary and what happens below?
- if (*dateString != '/')
- return NaN;
- // looks like a YYYY/MM/DD date
- if (!*++dateString)
- return NaN;
- year = day;
- month = strtol(dateString, &newPosStr, 10) - 1;
- if (errno)
- return NaN;
- dateString = newPosStr;
- if (*dateString++ != '/' || !*dateString)
- return NaN;
- day = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
- } else if (*dateString == '/' && month == -1) {
- dateString++;
- // This looks like a MM/DD/YYYY date, not an RFC date.
- month = day - 1; // 0-based
- day = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- if (day < 1 || day > 31)
- return NaN;
- dateString = newPosStr;
- if (*dateString == '/')
- dateString++;
- if (!*dateString)
- return NaN;
- } else {
- if (*dateString == '-')
- dateString++;
-
- skipSpacesAndComments(dateString);
-
- if (*dateString == ',')
- dateString++;
-
- if (month == -1) { // not found yet
- month = findMonth(dateString);
- if (month == -1)
- return NaN;
-
- while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
- dateString++;
-
- if (!*dateString)
- return NaN;
-
- // '-99 23:12:40 GMT'
- if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
- return NaN;
- dateString++;
- }
- }
-
- if (month < 0 || month > 11)
- return NaN;
-
- // '99 23:12:40 GMT'
- if (year <= 0 && *dateString) {
- year = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- }
-
- // Don't fail if the time is missing.
- long hour = 0;
- long minute = 0;
- long second = 0;
- if (!*newPosStr)
- dateString = newPosStr;
- else {
- // ' 23:12:40 GMT'
- if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
- if (*newPosStr != ':')
- return NaN;
- // There was no year; the number was the hour.
- year = -1;
- } else {
- // in the normal case (we parsed the year), advance to the next number
- dateString = ++newPosStr;
- skipSpacesAndComments(dateString);
- }
-
- hour = strtol(dateString, &newPosStr, 10);
- // Do not check for errno here since we want to continue
- // even if errno was set becasue we are still looking
- // for the timezone!
-
- // Read a number? If not, this might be a timezone name.
- if (newPosStr != dateString) {
- dateString = newPosStr;
-
- if (hour < 0 || hour > 23)
- return NaN;
-
- if (!*dateString)
- return NaN;
-
- // ':12:40 GMT'
- if (*dateString++ != ':')
- return NaN;
-
- minute = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
-
- if (minute < 0 || minute > 59)
- return NaN;
-
- // ':40 GMT'
- if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
- return NaN;
-
- // seconds are optional in rfc822 + rfc2822
- if (*dateString ==':') {
- dateString++;
-
- second = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
-
- if (second < 0 || second > 59)
- return NaN;
- }
-
- skipSpacesAndComments(dateString);
-
- if (strncasecmp(dateString, "AM", 2) == 0) {
- if (hour > 12)
- return NaN;
- if (hour == 12)
- hour = 0;
- dateString += 2;
- skipSpacesAndComments(dateString);
- } else if (strncasecmp(dateString, "PM", 2) == 0) {
- if (hour > 12)
- return NaN;
- if (hour != 12)
- hour += 12;
- dateString += 2;
- skipSpacesAndComments(dateString);
- }
- }
- }
-
- bool haveTZ = false;
- int offset = 0;
-
- // Don't fail if the time zone is missing.
- // Some websites omit the time zone (4275206).
- if (*dateString) {
- if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
- dateString += 3;
- haveTZ = true;
- }
-
- if (*dateString == '+' || *dateString == '-') {
- long o = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
-
- if (o < -9959 || o > 9959)
- return NaN;
-
- int sgn = (o < 0) ? -1 : 1;
- o = abs(o);
- if (*dateString != ':') {
- offset = ((o / 100) * 60 + (o % 100)) * sgn;
- } else { // GMT+05:00
- long o2 = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
- offset = (o * 60 + o2) * sgn;
- }
- haveTZ = true;
- } else {
- for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
- if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
- offset = known_zones[i].tzOffset;
- dateString += strlen(known_zones[i].tzName);
- haveTZ = true;
- break;
- }
- }
- }
- }
-
- skipSpacesAndComments(dateString);
-
- if (*dateString && year == -1) {
- year = strtol(dateString, &newPosStr, 10);
- if (errno)
- return NaN;
- dateString = newPosStr;
- }
-
- skipSpacesAndComments(dateString);
-
- // Trailing garbage
- if (*dateString)
- return NaN;
-
- // Y2K: Handle 2 digit years.
- if (year >= 0 && year < 100) {
- if (year < 50)
- year += 2000;
- else
- year += 1900;
- }
-
- // fall back to local timezone
- if (!haveTZ) {
- GregorianDateTime t;
- memset(&t, 0, sizeof(tm));
- t.monthDay = day;
- t.month = month;
- t.year = year - 1900;
- t.isDST = -1;
- t.second = second;
- t.minute = minute;
- t.hour = hour;
-
- // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
- return gregorianDateTimeToMS(t, 0, false);
- }
-
- return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
-}
-
-double timeClip(double t)
-{
- if (!isfinite(t))
- return NaN;
- if (fabs(t) > 8.64E15)
- return NaN;
- return trunc(t);
-}
-
-// Functions
-
-JSValue* dateProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsString(formatDate(t) + " " + formatTime(t, utc));
-}
-
-JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
-}
-
-JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsString(formatDate(t));
-}
-
-JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsString(formatTime(t, utc));
-}
-
-JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- double secs = floor(milli / msPerSecond);
- return jsString(formatLocaleDate(exec, secs, true, true, args));
-}
-
-JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- double secs = floor(milli / msPerSecond);
- return jsString(formatLocaleDate(exec, secs, true, false, args));
-}
-
-JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- double secs = floor(milli / msPerSecond);
- return jsString(formatLocaleDate(exec, secs, false, true, args));
-}
-
-JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- return jsNumber(milli);
-}
-
-JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- return jsNumber(milli);
-}
-
-JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(1900 + t.year);
-}
-
-JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(1900 + t.year);
-}
-
-JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsString("Invalid Date");
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
-}
-
-JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.month);
-}
-
-JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.month);
-}
-
-JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.monthDay);
-}
-
-JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.monthDay);
-}
-
-JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.weekDay);
-}
-
-JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.weekDay);
-}
-
-JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.hour);
-}
-
-JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.hour);
-}
-
-JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.minute);
-}
-
-JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.minute);
-}
-
-JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.second);
-}
-
-JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = true;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(t.second);
-}
-
-JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- double secs = floor(milli / msPerSecond);
- double ms = milli - secs * msPerSecond;
- return jsNumber(ms);
-}
-
-JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- double secs = floor(milli / msPerSecond);
- double ms = milli - secs * msPerSecond;
- return jsNumber(ms);
-}
-
-JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
- return jsNumber(-gmtoffset(t) / minutesPerHour);
-}
-
-JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
-
- double milli = timeClip(args[0]->toNumber(exec));
- JSValue* result = jsNumber(milli);
- thisDateObj->setInternalValue(result);
- return result;
-}
-
-static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- double secs = floor(milli / msPerSecond);
- double ms = milli - secs * msPerSecond;
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, inputIsUTC, t);
-
- fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t);
-
- JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
- thisDateObj->setInternalValue(result);
- return result;
-}
-
-static JSValue* setNewValueFromDateArgs(ExecState* exec, JSObject* thisObj, const List& args, int numArgsToUse, bool inputIsUTC)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- double secs = floor(milli / msPerSecond);
- double ms = milli - secs * msPerSecond;
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, inputIsUTC, t);
-
- fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t);
-
- JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, inputIsUTC));
- thisDateObj->setInternalValue(result);
- return result;
-}
-
-JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromTimeArgs(exec, thisObj, args, 1, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromTimeArgs(exec, thisObj, args, 2, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromTimeArgs(exec, thisObj, args, 3, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromTimeArgs(exec, thisObj, args, 4, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromDateArgs(exec, thisObj, args, 1, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromDateArgs(exec, thisObj, args, 2, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = false;
- return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject* thisObj, const List& args)
-{
- const bool inputIsUTC = true;
- return setNewValueFromDateArgs(exec, thisObj, args, 3, inputIsUTC);
-}
-
-JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- double secs = floor(milli / msPerSecond);
- double ms = milli - secs * msPerSecond;
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
-
- t.year = (args[0]->toInt32(exec) > 99 || args[0]->toInt32(exec) < 0) ? args[0]->toInt32(exec) - 1900 : args[0]->toInt32(exec);
-
- JSValue* result = jsNumber(gregorianDateTimeToMS(t, ms, utc));
- thisDateObj->setInternalValue(result);
- return result;
-}
-
-JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&DateInstance::info))
- return throwError(exec, TypeError);
-
- const bool utc = false;
-
- DateInstance* thisDateObj = static_cast<DateInstance*>(thisObj);
- JSValue* v = thisDateObj->internalValue();
- double milli = v->toNumber(exec);
- if (isnan(milli))
- return jsNaN();
-
- GregorianDateTime t;
- msToGregorianDateTime(milli, utc, t);
-
- // IE returns the full year even in getYear.
- if (exec->dynamicGlobalObject()->compatMode() == IECompat)
- return jsNumber(1900 + t.year);
- return jsNumber(t.year);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef DATE_OBJECT_H
-#define DATE_OBJECT_H
-
-#include "function.h"
-#include "JSWrapperObject.h"
-#include "lookup.h"
-
-namespace KJS {
-
- struct GregorianDateTime;
-
- class FunctionPrototype;
- class ObjectPrototype;
-
- class DateInstance : public JSWrapperObject {
- public:
- DateInstance(JSObject *proto);
-
- bool getTime(GregorianDateTime&, int& offset) const;
- bool getUTCTime(GregorianDateTime&) const;
- bool getTime(double& milli, int& offset) const;
- bool getUTCTime(double& milli) const;
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * The initial value of Date.prototype (and thus all objects created
- * with the Date constructor
- */
- class DatePrototype : public DateInstance {
- public:
- DatePrototype(ExecState *, ObjectPrototype *);
- virtual bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot&);
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * Functions to implement all methods that are properties of the
- * Date.prototype object
- */
-
- // Non-normative properties (Appendix B)
- // GetYear, SetYear, ToGMTString
-
- JSValue* dateProtoFuncToString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToUTCString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToDateString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToTimeString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToLocaleDateString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncValueOf(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetTime(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetFullYear(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncToGMTString(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetMonth(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCMonth(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetDate(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCDate(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetDay(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCDay(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetHours(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCHours(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetMinutes(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetTime(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetMinutes(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetHours(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCHours(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetDate(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCDate(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetMonth(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCMonth(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetFullYear(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncSetYear(ExecState*, JSObject*, const List&);
- JSValue* dateProtoFuncGetYear(ExecState*, JSObject*, const List&);
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Date" property
- */
- class DateObjectImp : public InternalFunctionImp {
- public:
- DateObjectImp(ExecState *, FunctionPrototype *, DatePrototype *);
-
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *, const List &args);
- virtual JSValue *callAsFunction(ExecState *, JSObject *thisObj, const List &args);
-
- JSObject *construct(const List &);
- };
-
-} // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "debugger.h"
-
-#include "JSGlobalObject.h"
-#include "internal.h"
-#include "ustring.h"
-
-using namespace KJS;
-
-// ------------------------------ Debugger -------------------------------------
-
-namespace KJS {
- struct AttachedGlobalObject
- {
- public:
- AttachedGlobalObject(JSGlobalObject* o, AttachedGlobalObject* ai) : globalObj(o), next(ai) { ++Debugger::debuggersPresent; }
- ~AttachedGlobalObject() { --Debugger::debuggersPresent; }
- JSGlobalObject* globalObj;
- AttachedGlobalObject* next;
- };
-
-}
-
-int Debugger::debuggersPresent = 0;
-
-Debugger::Debugger()
-{
- rep = new DebuggerImp();
-}
-
-Debugger::~Debugger()
-{
- detach(0);
- delete rep;
-}
-
-void Debugger::attach(JSGlobalObject* globalObject)
-{
- Debugger* other = globalObject->debugger();
- if (other == this)
- return;
- if (other)
- other->detach(globalObject);
- globalObject->setDebugger(this);
- rep->globalObjects = new AttachedGlobalObject(globalObject, rep->globalObjects);
-}
-
-void Debugger::detach(JSGlobalObject* globalObj)
-{
- // iterate the addresses where AttachedGlobalObject pointers are stored
- // so we can unlink items from the list
- AttachedGlobalObject **p = &rep->globalObjects;
- AttachedGlobalObject *q;
- while ((q = *p)) {
- if (!globalObj || q->globalObj == globalObj) {
- *p = q->next;
- q->globalObj->setDebugger(0);
- delete q;
- } else
- p = &q->next;
- }
-
- if (globalObj)
- latestExceptions.remove(globalObj);
- else
- latestExceptions.clear();
-}
-
-bool Debugger::hasHandledException(ExecState *exec, JSValue *exception)
-{
- if (latestExceptions.get(exec->dynamicGlobalObject()).get() == exception)
- return true;
-
- latestExceptions.set(exec->dynamicGlobalObject(), exception);
- return false;
-}
-
-bool Debugger::sourceParsed(ExecState*, const SourceCode&, int /*errorLine*/, const UString& /*errorMsg*/)
-{
- return true;
-}
-
-bool Debugger::sourceUnused(ExecState*, intptr_t /*sourceID*/)
-{
- return true;
-}
-
-bool Debugger::exception(ExecState*, intptr_t /*sourceID*/, int /*lineno*/,
- JSValue* /*exception */)
-{
- return true;
-}
-
-bool Debugger::atStatement(ExecState*, intptr_t /*sourceID*/, int /*firstLine*/,
- int /*lastLine*/)
-{
- return true;
-}
-
-bool Debugger::callEvent(ExecState*, intptr_t /*sourceID*/, int /*lineno*/,
- JSObject* /*function*/, const List &/*args*/)
-{
- return true;
-}
-
-bool Debugger::returnEvent(ExecState*, intptr_t /*sourceID*/, int /*lineno*/,
- JSObject* /*function*/)
-{
- return true;
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef _KJSDEBUGGER_H_
-#define _KJSDEBUGGER_H_
-
-#include <wtf/HashMap.h>
-#include "protect.h"
-
-namespace KJS {
-
- class DebuggerImp;
- class ExecState;
- class JSGlobalObject;
- class JSObject;
- class JSValue;
- class SourceCode;
- class UString;
- class List;
-
- /**
- * @internal
- *
- * Provides an interface which receives notification about various
- * script-execution related events such as statement execution and function
- * calls.
- *
- * WARNING: This interface is still a work in progress and is not yet
- * offically publicly available. It is likely to change in binary incompatible
- * (and possibly source incompatible) ways in future versions. It is
- * anticipated that at some stage the interface will be frozen and made
- * available for general use.
- */
- class Debugger {
- public:
-
- /**
- * Creates a new debugger
- */
- Debugger();
-
- /**
- * Destroys the debugger. If the debugger is attached to any global objects,
- * it is automatically detached.
- */
- virtual ~Debugger();
-
- DebuggerImp *imp() const { return rep; }
-
- /**
- * Attaches the debugger to specified global object. This will cause this
- * object to receive notification of events during execution.
- *
- * If the global object is deleted, it will detach the debugger.
- *
- * Note: only one debugger can be attached to a global object at a time.
- * Attaching another debugger to the same global object will cause the
- * original debugger to be detached.
- *
- * @param The global object to attach to.
- *
- * @see detach()
- */
- void attach(JSGlobalObject*);
-
- /**
- * Detach the debugger from a global object.
- *
- * @param The global object to detach from. If 0, the debugger will be
- * detached from all global objects to which it is attached.
- *
- * @see attach()
- */
- void detach(JSGlobalObject*);
-
- /**
- * Called to notify the debugger that some javascript source code has
- * been parsed. For calls to Interpreter::evaluate(), this will be called
- * with the supplied source code before any other code is parsed.
- * Other situations in which this may be called include creation of a
- * function using the Function() constructor, or the eval() function.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code (corresponds to the
- * sourceId supplied in other functions such as atStatement()
- * @param sourceURL Where the source code that was parsed came from
- * @param source The source code that was parsed
- * @param startingLineNumber The line number at which parsing started
- * @param errorLine The line number at which parsing encountered an
- * error, or -1 if the source code was valid and parsed successfully
- * @param errorMsg The error description, or null if the source code
- was valid and parsed successfully
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool sourceParsed(ExecState*, const SourceCode&, int errorLine, const UString& errorMsg) = 0;
-
- /**
- * Called when all functions/programs associated with a particular
- * sourceId have been deleted. After this function has been called for
- * a particular sourceId, that sourceId will not be used again.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code (corresponds to the
- * sourceId supplied in other functions such as atLine()
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool sourceUnused(ExecState *exec, intptr_t sourceID);
-
- /**
- * Called when an exception is thrown during script execution.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line at which the error occurred
- * @param exceptionObj The exception object
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool exception(ExecState *exec, intptr_t sourceID, int lineno,
- JSValue *exception);
-
- bool hasHandledException(ExecState *, JSValue *);
-
- /**
- * Called when a line of the script is reached (before it is executed)
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param firstLine The starting line of the statement that is about to be
- * executed
- * @param lastLine The ending line of the statement that is about to be
- * executed (usually the same as firstLine)
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool atStatement(ExecState *exec, intptr_t sourceID, int firstLine,
- int lastLine);
- /**
- * Called on each function call. Use together with @ref #returnEvent
- * if you want to keep track of the call stack.
- *
- * Note: This only gets called for functions that are declared in ECMAScript
- * source code or passed to eval(), not for internal KJS or
- * application-supplied functions.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line that is about to be executed
- * @param function The function being called
- * @param args The arguments that were passed to the function
- * line is being executed
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool callEvent(ExecState *exec, intptr_t sourceID, int lineno,
- JSObject *function, const List &args);
-
- /**
- * Called on each function exit. The function being returned from is that
- * which was supplied in the last callEvent().
- *
- * Note: This only gets called for functions that are declared in ECMAScript
- * source code or passed to eval(), not for internal KJS or
- * application-supplied functions.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line that is about to be executed
- * @param function The function being called
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool returnEvent(ExecState *exec, intptr_t sourceID, int lineno,
- JSObject *function);
-
- private:
- DebuggerImp *rep;
- HashMap<JSGlobalObject*, ProtectedPtr<JSValue> > latestExceptions;
-
- public:
- static int debuggersPresent;
- };
-
-}
-
-#endif
+++ /dev/null
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to
- David M. Gay
- Bell Laboratories, Room 2C-463
- 600 Mountain Avenue
- Murray Hill, NJ 07974-0636
- U.S.A.
- dmg@bell-labs.com
- */
-
-/* On a machine with IEEE extended-precision registers, it is
- * necessary to specify double-precision (53-bit) rounding precision
- * before invoking strtod or dtoa. If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- * _control87(PC_53, MCW_PC);
- * does this with many compilers. Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule. Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- * 1. We only require IEEE, IBM, or VAX double-precision
- * arithmetic (not IEEE double-extended).
- * 2. We get by with floating-point arithmetic in a case that
- * Clinger missed -- when we're computing d * 10^n
- * for a small integer d and the integer n is not too
- * much larger than 22 (the maximum integer k for which
- * we can represent 10^k exactly), we may be able to
- * compute (d*10^k) * 10^(e-k) with just one roundoff.
- * 3. Rather than a bit-at-a-time adjustment of the binary
- * result in the hard case, we use floating-point
- * arithmetic to determine the adjustment to within
- * one bit; only in really hard cases do we need to
- * compute a second residual.
- * 4. Because of 3., we don't need a large table of powers of 10
- * for ten-to-e (just some small tables, e.g. of 10^k
- * for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_8087 for IEEE-arithmetic machines where the least
- * significant byte has the lowest address.
- * #define IEEE_MC68k for IEEE-arithmetic machines where the most
- * significant byte has the lowest address.
- * #define Long int on machines with 32-bit ints and 64-bit longs.
- * #define IBM for IBM mainframe-style floating-point arithmetic.
- * #define VAX for VAX-style floating-point arithmetic (D_floating).
- * #define No_leftright to omit left-right logic in fast floating-point
- * computation of dtoa.
- * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- * and strtod and dtoa should round accordingly.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- * and Honor_FLT_ROUNDS is not #defined.
- * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
- * that use extended-precision instructions to compute rounded
- * products and quotients) with IBM.
- * #define ROUND_BIASED for IEEE-format with biased rounding.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- * products but inaccurate quotients, e.g., for Intel i860.
- * #define NO_LONG_LONG on machines that do not have a "long long"
- * integer type (of >= 64 bits). On such machines, you can
- * #define Just_16 to store 16 bits per 32-bit Long when doing
- * high-precision integer arithmetic. Whether this speeds things
- * up or slows things down depends on the machine and the number
- * being converted. If long long is available and the name is
- * something other than "long long", #define Llong to be the name,
- * and if "unsigned Llong" does not work as an unsigned version of
- * Llong, #define #ULLong to be the corresponding unsigned type.
- * #define KR_headers for old-style C function headers.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
- * if memory is available and otherwise does something you deem
- * appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
- * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
- * memory allocations from a private pool of memory when possible.
- * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
- * unless #defined to be a different length. This default length
- * suffices to get rid of MALLOC calls except for unusual cases,
- * such as decimal-to-binary conversion of a very long string of
- * digits. The longest string dtoa can return is about 751 bytes
- * long. For conversions by strtod of strings of 800 digits and
- * all dtoa conversions in single-threaded executions with 8-byte
- * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
- * pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- * Infinity and NaN (case insensitively). On some systems (e.g.,
- * some HP systems), it may be necessary to #define NAN_WORD0
- * appropriately -- to the most significant word of a quiet NaN.
- * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- * strtod also accepts (case insensitively) strings of the form
- * NaN(x), where x is a string of hexadecimal digits and spaces;
- * if there is only one string of hexadecimal digits, it is taken
- * for the 52 fraction bits of the resulting NaN; if there are two
- * or more strings of hex digits, the first is for the high 20 bits,
- * the second and subsequent for the low 32 bits, with intervening
- * white space ignored; but if this results in none of the 52
- * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- * and NAN_WORD1 are used instead.
- * #define MULTIPLE_THREADS if the system offers preemptively scheduled
- * multiple threads. In this case, you must provide (or suitably
- * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
- * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
- * in pow5mult, ensures lazy evaluation of only one copy of high
- * powers of 5; omitting this lock would introduce a small
- * probability of wasting memory, but would otherwise be harmless.)
- * You must also invoke freedtoa(s) to free the value s returned by
- * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- * avoids underflows on inputs whose result does not underflow.
- * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- * floating-point numbers and flushes underflows to zero rather
- * than implementing gradual underflow, then you must also #define
- * Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- * computation should be done to set the inexact flag when the
- * result is inexact and avoid setting inexact when the result
- * is exact. In this case, dtoa.c must be compiled in
- * an environment, perhaps provided by #include "dtoa.c" in a
- * suitable wrapper, that defines two functions,
- * int get_inexact(void);
- * void clear_inexact(void);
- * such that get_inexact() returns a nonzero value if the
- * inexact bit is already set, and clear_inexact() sets the
- * inexact bit to 0. When SET_INEXACT is #defined, strtod
- * also does extra computations to set the underflow and overflow
- * flags when appropriate (i.e., when the result is tiny and
- * inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- * the result overflows to +-Infinity or underflows to 0.
- */
-
-#include "config.h"
-#include "dtoa.h"
-
-#if COMPILER(MSVC)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4245)
-#pragma warning(disable: 4554)
-#endif
-
-#if PLATFORM(BIG_ENDIAN)
-#define IEEE_MC68k
-#else
-#define IEEE_8087
-#endif
-#define INFNAN_CHECK
-
-
-
-#ifndef Long
-#define Long int
-#endif
-#ifndef ULong
-typedef unsigned Long ULong;
-#endif
-
-#ifdef DEBUG
-#include <stdio.h>
-#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef MALLOC
-#ifdef KR_headers
-extern char *MALLOC();
-#else
-extern void *MALLOC(size_t);
-#endif
-#else
-#define MALLOC malloc
-#endif
-
-#ifndef Omit_Private_Memory
-#ifndef PRIVATE_MEM
-#define PRIVATE_MEM 2304
-#endif
-#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
-static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
-#endif
-
-#undef IEEE_Arith
-#undef Avoid_Underflow
-#ifdef IEEE_MC68k
-#define IEEE_Arith
-#endif
-#ifdef IEEE_8087
-#define IEEE_Arith
-#endif
-
-#include <errno.h>
-
-#ifdef Bad_float_h
-
-#ifdef IEEE_Arith
-#define DBL_DIG 15
-#define DBL_MAX_10_EXP 308
-#define DBL_MAX_EXP 1024
-#define FLT_RADIX 2
-#endif /*IEEE_Arith*/
-
-#ifdef IBM
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 75
-#define DBL_MAX_EXP 63
-#define FLT_RADIX 16
-#define DBL_MAX 7.2370055773322621e+75
-#endif
-
-#ifdef VAX
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 38
-#define DBL_MAX_EXP 127
-#define FLT_RADIX 2
-#define DBL_MAX 1.7014118346046923e+38
-#endif
-
-#ifndef LONG_MAX
-#define LONG_MAX 2147483647
-#endif
-
-#else /* ifndef Bad_float_h */
-#include <float.h>
-#endif /* Bad_float_h */
-
-#ifndef __MATH_H__
-#include <math.h>
-#endif
-
-#define strtod kjs_strtod
-#define dtoa kjs_dtoa
-#define freedtoa kjs_freedtoa
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef CONST_
-#ifdef KR_headers
-#define CONST_ /* blank */
-#else
-#define CONST_ const
-#endif
-#endif
-
-#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
-Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
-#endif
-
-typedef union { double d; ULong L[2]; } U;
-
-#ifdef YES_ALIAS
-#define dval(x) x
-#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
-#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
-#endif
-#else
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_8087) + defined(VAX)
-#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
-((unsigned short *)a)[0] = (unsigned short)c, a++)
-#else
-#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
-((unsigned short *)a)[1] = (unsigned short)c, a++)
-#endif
-
-/* #define P DBL_MANT_DIG */
-/* Ten_pmax = floor(P*log(2)/log(5)) */
-/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
-/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
-/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
-
-#ifdef IEEE_Arith
-#define Exp_shift 20
-#define Exp_shift1 20
-#define Exp_msk1 0x100000
-#define Exp_msk11 0x100000
-#define Exp_mask 0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1 0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask 0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask 0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-#ifndef NO_IEEE_Scale
-#define Avoid_Underflow
-#ifdef Flush_Denorm /* debugging option */
-#undef Sudden_Underflow
-#endif
-#endif
-
-#ifndef Flt_Rounds
-#ifdef FLT_ROUNDS
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
-#undef Check_FLT_ROUNDS
-#define Check_FLT_ROUNDS
-#else
-#define Rounding Flt_Rounds
-#endif
-
-#else /* ifndef IEEE_Arith */
-#undef Check_FLT_ROUNDS
-#undef Honor_FLT_ROUNDS
-#undef SET_INEXACT
-#undef Sudden_Underflow
-#define Sudden_Underflow
-#ifdef IBM
-#undef Flt_Rounds
-#define Flt_Rounds 0
-#define Exp_shift 24
-#define Exp_shift1 24
-#define Exp_msk1 0x1000000
-#define Exp_msk11 0x1000000
-#define Exp_mask 0x7f000000
-#define P 14
-#define Bias 65
-#define Exp_1 0x41000000
-#define Exp_11 0x41000000
-#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
-#define Frac_mask 0xffffff
-#define Frac_mask1 0xffffff
-#define Bletch 4
-#define Ten_pmax 22
-#define Bndry_mask 0xefffff
-#define Bndry_mask1 0xffffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 4
-#define Tiny0 0x100000
-#define Tiny1 0
-#define Quick_max 14
-#define Int_max 15
-#else /* VAX */
-#undef Flt_Rounds
-#define Flt_Rounds 1
-#define Exp_shift 23
-#define Exp_shift1 7
-#define Exp_msk1 0x80
-#define Exp_msk11 0x800000
-#define Exp_mask 0x7f80
-#define P 56
-#define Bias 129
-#define Exp_1 0x40800000
-#define Exp_11 0x4080
-#define Ebits 8
-#define Frac_mask 0x7fffff
-#define Frac_mask1 0xffff007f
-#define Ten_pmax 24
-#define Bletch 2
-#define Bndry_mask 0xffff007f
-#define Bndry_mask1 0xffff007f
-#define LSB 0x10000
-#define Sign_bit 0x8000
-#define Log2P 1
-#define Tiny0 0x80
-#define Tiny1 0
-#define Quick_max 15
-#define Int_max 15
-#endif /* IBM, VAX */
-#endif /* IEEE_Arith */
-
-#ifndef IEEE_Arith
-#define ROUND_BIASED
-#endif
-
-#ifdef RND_PRODQUOT
-#define rounded_product(a,b) a = rnd_prod(a, b)
-#define rounded_quotient(a,b) a = rnd_quot(a, b)
-#ifdef KR_headers
-extern double rnd_prod(), rnd_quot();
-#else
-extern double rnd_prod(double, double), rnd_quot(double, double);
-#endif
-#else
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
-#endif
-
-#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
-#define Big1 0xffffffff
-
-#ifndef Pack_32
-#define Pack_32
-#endif
-
-#ifdef KR_headers
-#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
-#else
-#define FFFFFFFF 0xffffffffUL
-#endif
-
-#ifdef NO_LONG_LONG
-#undef ULLong
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower. Hence the default is now to store 32 bits per Long.
- */
-#endif
-#else /* long long available */
-#ifndef Llong
-#define Llong long long
-#endif
-#ifndef ULLong
-#define ULLong unsigned Llong
-#endif
-#endif /* NO_LONG_LONG */
-
-#ifndef MULTIPLE_THREADS
-#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
-#define FREE_DTOA_LOCK(n) /*nothing*/
-#endif
-
-#define Kmax 15
-
- struct
-Bigint {
- struct Bigint *next;
- int k, maxwds, sign, wds;
- ULong x[1];
- };
-
- typedef struct Bigint Bigint;
-
- static Bigint *freelist[Kmax+1];
-
- static Bigint *
-Balloc
-#ifdef KR_headers
- (k) int k;
-#else
- (int k)
-#endif
-{
- int x;
- Bigint *rv;
-#ifndef Omit_Private_Memory
- unsigned int len;
-#endif
-
- ACQUIRE_DTOA_LOCK(0);
- if ((rv = freelist[k])) {
- freelist[k] = rv->next;
- }
- else {
- x = 1 << k;
-#ifdef Omit_Private_Memory
- rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
-#else
- len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
- /sizeof(double);
- if (pmem_next - private_mem + len <= (unsigned)PRIVATE_mem) {
- rv = (Bigint*)pmem_next;
- pmem_next += len;
- }
- else
- rv = (Bigint*)MALLOC(len*sizeof(double));
-#endif
- rv->k = k;
- rv->maxwds = x;
- }
- FREE_DTOA_LOCK(0);
- rv->sign = rv->wds = 0;
- return rv;
- }
-
- static void
-Bfree
-#ifdef KR_headers
- (v) Bigint *v;
-#else
- (Bigint *v)
-#endif
-{
- if (v) {
- ACQUIRE_DTOA_LOCK(0);
- v->next = freelist[v->k];
- freelist[v->k] = v;
- FREE_DTOA_LOCK(0);
- }
- }
-
-#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
-y->wds*sizeof(Long) + 2*sizeof(int))
-
- static Bigint *
-multadd
-#ifdef KR_headers
- (b, m, a) Bigint *b; int m, a;
-#else
- (Bigint *b, int m, int a) /* multiply by m and add a */
-#endif
-{
- int i, wds;
-#ifdef ULLong
- ULong *x;
- ULLong carry, y;
-#else
- ULong carry, *x, y;
-#ifdef Pack_32
- ULong xi, z;
-#endif
-#endif
- Bigint *b1;
-
- wds = b->wds;
- x = b->x;
- i = 0;
- carry = a;
- do {
-#ifdef ULLong
- y = *x * (ULLong)m + carry;
- carry = y >> 32;
- *x++ = (ULong)y & FFFFFFFF;
-#else
-#ifdef Pack_32
- xi = *x;
- y = (xi & 0xffff) * m + carry;
- z = (xi >> 16) * m + (y >> 16);
- carry = z >> 16;
- *x++ = (z << 16) + (y & 0xffff);
-#else
- y = *x * m + carry;
- carry = y >> 16;
- *x++ = y & 0xffff;
-#endif
-#endif
- }
- while(++i < wds);
- if (carry) {
- if (wds >= b->maxwds) {
- b1 = Balloc(b->k+1);
- Bcopy(b1, b);
- Bfree(b);
- b = b1;
- }
- b->x[wds++] = (ULong)carry;
- b->wds = wds;
- }
- return b;
- }
-
- static Bigint *
-s2b
-#ifdef KR_headers
- (s, nd0, nd, y9) CONST_ char *s; int nd0, nd; ULong y9;
-#else
- (CONST_ char *s, int nd0, int nd, ULong y9)
-#endif
-{
- Bigint *b;
- int i, k;
- Long x, y;
-
- x = (nd + 8) / 9;
- for(k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
- b = Balloc(k);
- b->x[0] = y9;
- b->wds = 1;
-#else
- b = Balloc(k+1);
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
- i = 9;
- if (9 < nd0) {
- s += 9;
- do b = multadd(b, 10, *s++ - '0');
- while(++i < nd0);
- s++;
- }
- else
- s += 10;
- for(; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
- }
-
- static int
-hi0bits
-#ifdef KR_headers
- (x) register ULong x;
-#else
- (register ULong x)
-#endif
-{
- register int k = 0;
-
- if (!(x & 0xffff0000)) {
- k = 16;
- x <<= 16;
- }
- if (!(x & 0xff000000)) {
- k += 8;
- x <<= 8;
- }
- if (!(x & 0xf0000000)) {
- k += 4;
- x <<= 4;
- }
- if (!(x & 0xc0000000)) {
- k += 2;
- x <<= 2;
- }
- if (!(x & 0x80000000)) {
- k++;
- if (!(x & 0x40000000))
- return 32;
- }
- return k;
- }
-
- static int
-lo0bits
-#ifdef KR_headers
- (y) ULong *y;
-#else
- (ULong *y)
-#endif
-{
- register int k;
- register ULong x = *y;
-
- if (x & 7) {
- if (x & 1)
- return 0;
- if (x & 2) {
- *y = x >> 1;
- return 1;
- }
- *y = x >> 2;
- return 2;
- }
- k = 0;
- if (!(x & 0xffff)) {
- k = 16;
- x >>= 16;
- }
- if (!(x & 0xff)) {
- k += 8;
- x >>= 8;
- }
- if (!(x & 0xf)) {
- k += 4;
- x >>= 4;
- }
- if (!(x & 0x3)) {
- k += 2;
- x >>= 2;
- }
- if (!(x & 1)) {
- k++;
- x >>= 1;
- if (!x & 1)
- return 32;
- }
- *y = x;
- return k;
- }
-
- static Bigint *
-i2b
-#ifdef KR_headers
- (i) int i;
-#else
- (int i)
-#endif
-{
- Bigint *b;
-
- b = Balloc(1);
- b->x[0] = i;
- b->wds = 1;
- return b;
- }
-
- static Bigint *
-mult
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- Bigint *c;
- int k, wa, wb, wc;
- ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
- ULong y;
-#ifdef ULLong
- ULLong carry, z;
-#else
- ULong carry, z;
-#ifdef Pack_32
- ULong z2;
-#endif
-#endif
-
- if (a->wds < b->wds) {
- c = a;
- a = b;
- b = c;
- }
- k = a->k;
- wa = a->wds;
- wb = b->wds;
- wc = wa + wb;
- if (wc > a->maxwds)
- k++;
- c = Balloc(k);
- for(x = c->x, xa = x + wc; x < xa; x++)
- *x = 0;
- xa = a->x;
- xae = xa + wa;
- xb = b->x;
- xbe = xb + wb;
- xc0 = c->x;
-#ifdef ULLong
- for(; xb < xbe; xc0++) {
- if ((y = *xb++)) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * (ULLong)y + *xc + carry;
- carry = z >> 32;
- *xc++ = (ULong)z & FFFFFFFF;
- }
- while(x < xae);
- *xc = (ULong)carry;
- }
- }
-#else
-#ifdef Pack_32
- for(; xb < xbe; xb++, xc0++) {
- if (y = *xb & 0xffff) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
- carry = z >> 16;
- z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
- carry = z2 >> 16;
- Storeinc(xc, z2, z);
- }
- while(x < xae);
- *xc = carry;
- }
- if (y = *xb >> 16) {
- x = xa;
- xc = xc0;
- carry = 0;
- z2 = *xc;
- do {
- z = (*x & 0xffff) * y + (*xc >> 16) + carry;
- carry = z >> 16;
- Storeinc(xc, z, z2);
- z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
- carry = z2 >> 16;
- }
- while(x < xae);
- *xc = z2;
- }
- }
-#else
- for(; xb < xbe; xc0++) {
- if (y = *xb++) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * y + *xc + carry;
- carry = z >> 16;
- *xc++ = z & 0xffff;
- }
- while(x < xae);
- *xc = carry;
- }
- }
-#endif
-#endif
- for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
- c->wds = wc;
- return c;
- }
-
- static Bigint *p5s;
-
- static Bigint *
-pow5mult
-#ifdef KR_headers
- (b, k) Bigint *b; int k;
-#else
- (Bigint *b, int k)
-#endif
-{
- Bigint *b1, *p5, *p51;
- int i;
- static int p05[3] = { 5, 25, 125 };
-
- if ((i = k & 3))
- b = multadd(b, p05[i-1], 0);
-
- if (!(k >>= 2))
- return b;
- if (!(p5 = p5s)) {
- /* first time */
-#ifdef MULTIPLE_THREADS
- ACQUIRE_DTOA_LOCK(1);
- if (!(p5 = p5s)) {
- p5 = p5s = i2b(625);
- p5->next = 0;
- }
- FREE_DTOA_LOCK(1);
-#else
- p5 = p5s = i2b(625);
- p5->next = 0;
-#endif
- }
- for(;;) {
- if (k & 1) {
- b1 = mult(b, p5);
- Bfree(b);
- b = b1;
- }
- if (!(k >>= 1))
- break;
- if (!(p51 = p5->next)) {
-#ifdef MULTIPLE_THREADS
- ACQUIRE_DTOA_LOCK(1);
- if (!(p51 = p5->next)) {
- p51 = p5->next = mult(p5,p5);
- p51->next = 0;
- }
- FREE_DTOA_LOCK(1);
-#else
- p51 = p5->next = mult(p5,p5);
- p51->next = 0;
-#endif
- }
- p5 = p51;
- }
- return b;
- }
-
- static Bigint *
-lshift
-#ifdef KR_headers
- (b, k) Bigint *b; int k;
-#else
- (Bigint *b, int k)
-#endif
-{
- int i, k1, n, n1;
- Bigint *b1;
- ULong *x, *x1, *xe, z;
-
-#ifdef Pack_32
- n = k >> 5;
-#else
- n = k >> 4;
-#endif
- k1 = b->k;
- n1 = n + b->wds + 1;
- for(i = b->maxwds; n1 > i; i <<= 1)
- k1++;
- b1 = Balloc(k1);
- x1 = b1->x;
- for(i = 0; i < n; i++)
- *x1++ = 0;
- x = b->x;
- xe = x + b->wds;
-#ifdef Pack_32
- if (k &= 0x1f) {
- k1 = 32 - k;
- z = 0;
- do {
- *x1++ = *x << k | z;
- z = *x++ >> k1;
- }
- while(x < xe);
- if ((*x1 = z))
- ++n1;
- }
-#else
- if (k &= 0xf) {
- k1 = 16 - k;
- z = 0;
- do {
- *x1++ = *x << k & 0xffff | z;
- z = *x++ >> k1;
- }
- while(x < xe);
- if (*x1 = z)
- ++n1;
- }
-#endif
- else do
- *x1++ = *x++;
- while(x < xe);
- b1->wds = n1 - 1;
- Bfree(b);
- return b1;
- }
-
- static int
-cmp
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- ULong *xa, *xa0, *xb, *xb0;
- int i, j;
-
- i = a->wds;
- j = b->wds;
-#ifdef DEBUG
- if (i > 1 && !a->x[i-1])
- Bug("cmp called with a->x[a->wds-1] == 0");
- if (j > 1 && !b->x[j-1])
- Bug("cmp called with b->x[b->wds-1] == 0");
-#endif
- if (i -= j)
- return i;
- xa0 = a->x;
- xa = xa0 + j;
- xb0 = b->x;
- xb = xb0 + j;
- for(;;) {
- if (*--xa != *--xb)
- return *xa < *xb ? -1 : 1;
- if (xa <= xa0)
- break;
- }
- return 0;
- }
-
- static Bigint *
-diff
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- Bigint *c;
- int i, wa, wb;
- ULong *xa, *xae, *xb, *xbe, *xc;
-#ifdef ULLong
- ULLong borrow, y;
-#else
- ULong borrow, y;
-#ifdef Pack_32
- ULong z;
-#endif
-#endif
-
- i = cmp(a,b);
- if (!i) {
- c = Balloc(0);
- c->wds = 1;
- c->x[0] = 0;
- return c;
- }
- if (i < 0) {
- c = a;
- a = b;
- b = c;
- i = 1;
- }
- else
- i = 0;
- c = Balloc(a->k);
- c->sign = i;
- wa = a->wds;
- xa = a->x;
- xae = xa + wa;
- wb = b->wds;
- xb = b->x;
- xbe = xb + wb;
- xc = c->x;
- borrow = 0;
-#ifdef ULLong
- do {
- y = (ULLong)*xa++ - *xb++ - borrow;
- borrow = y >> 32 & (ULong)1;
- *xc++ = (ULong)y & FFFFFFFF;
- }
- while(xb < xbe);
- while(xa < xae) {
- y = *xa++ - borrow;
- borrow = y >> 32 & (ULong)1;
- *xc++ = (ULong)y & FFFFFFFF;
- }
-#else
-#ifdef Pack_32
- do {
- y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- }
- while(xb < xbe);
- while(xa < xae) {
- y = (*xa & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*xa++ >> 16) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(xc, z, y);
- }
-#else
- do {
- y = *xa++ - *xb++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- }
- while(xb < xbe);
- while(xa < xae) {
- y = *xa++ - borrow;
- borrow = (y & 0x10000) >> 16;
- *xc++ = y & 0xffff;
- }
-#endif
-#endif
- while(!*--xc)
- wa--;
- c->wds = wa;
- return c;
- }
-
- static double
-ulp
-#ifdef KR_headers
- (x) double x;
-#else
- (double x)
-#endif
-{
- register Long L;
- double a;
-
- L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- if (L > 0) {
-#endif
-#endif
-#ifdef IBM
- L |= Exp_msk1 >> 4;
-#endif
- word0(a) = L;
- word1(a) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
- }
- else {
- L = -L >> Exp_shift;
- if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
- }
- else {
- word0(a) = 0;
- L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
- }
- }
-#endif
-#endif
- return dval(a);
- }
-
- static double
-b2d
-#ifdef KR_headers
- (a, e) Bigint *a; int *e;
-#else
- (Bigint *a, int *e)
-#endif
-{
- ULong *xa, *xa0, w, y, z;
- int k;
- double d;
-#ifdef VAX
- ULong d0, d1;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
- xa0 = a->x;
- xa = xa0 + a->wds;
- y = *--xa;
-#ifdef DEBUG
- if (!y) Bug("zero y in b2d");
-#endif
- k = hi0bits(y);
- *e = 32 - k;
-#ifdef Pack_32
- if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
- w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
- }
- else {
- d0 = Exp_1 | y;
- d1 = z;
- }
-#else
- if (k < Ebits + 16) {
- z = xa > xa0 ? *--xa : 0;
- d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
- w = xa > xa0 ? *--xa : 0;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- w = xa > xa0 ? *--xa : 0;
- k -= Ebits + 16;
- d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = w << k + 16 | y << k;
-#endif
- ret_d:
-#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
-#else
-#undef d0
-#undef d1
-#endif
- return dval(d);
- }
-
- static Bigint *
-d2b
-#ifdef KR_headers
- (d, e, bits) double d; int *e, *bits;
-#else
- (double d, int *e, int *bits)
-#endif
-{
- Bigint *b;
- int de, k;
- ULong *x, y, z;
-#ifndef Sudden_Underflow
- int i;
-#endif
-#ifdef VAX
- ULong d0, d1;
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-#ifdef Pack_32
- b = Balloc(1);
-#else
- b = Balloc(2);
-#endif
- x = b->x;
-
- z = d0 & Frac_mask;
- d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
- de = (int)(d0 >> Exp_shift);
-#ifndef IBM
- z |= Exp_msk11;
-#endif
-#else
- if ((de = (int)(d0 >> Exp_shift)))
- z |= Exp_msk1;
-#endif
-#ifdef Pack_32
- if ((y = d1)) {
- if ((k = lo0bits(&y))) {
- x[0] = y | z << 32 - k;
- z >>= k;
- }
- else
- x[0] = y;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = (x[1] = z) ? 2 : 1;
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- x[0] = z;
-#ifndef Sudden_Underflow
- i =
-#endif
- b->wds = 1;
- k += 32;
- }
-#else
- if (y = d1) {
- if (k = lo0bits(&y))
- if (k >= 16) {
- x[0] = y | z << 32 - k & 0xffff;
- x[1] = z >> k - 16 & 0xffff;
- x[2] = z >> k;
- i = 2;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16 | z << 16 - k & 0xffff;
- x[2] = z >> k & 0xffff;
- x[3] = z >> k+16;
- i = 3;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16;
- x[2] = z & 0xffff;
- x[3] = z >> 16;
- i = 3;
- }
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- if (k >= 16) {
- x[0] = z;
- i = 0;
- }
- else {
- x[0] = z & 0xffff;
- x[1] = z >> 16;
- i = 1;
- }
- k += 32;
- }
- while(!x[i])
- --i;
- b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
- if (de) {
-#endif
-#ifdef IBM
- *e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
-#else
- *e = de - Bias - (P-1) + k;
- *bits = P - k;
-#endif
-#ifndef Sudden_Underflow
- }
- else {
- *e = de - Bias - (P-1) + 1 + k;
-#ifdef Pack_32
- *bits = 32*i - hi0bits(x[i-1]);
-#else
- *bits = (i+2)*16 - hi0bits(x[i]);
-#endif
- }
-#endif
- return b;
- }
-#undef d0
-#undef d1
-
- static double
-ratio
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- double da, db;
- int k, ka, kb;
-
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
-#ifdef Pack_32
- k = ka - kb + 32*(a->wds - b->wds);
-#else
- k = ka - kb + 16*(a->wds - b->wds);
-#endif
-#ifdef IBM
- if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(da) *= 1 << k;
- }
- else {
- k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(db) *= 1 << k;
- }
-#else
- if (k > 0)
- word0(da) += k*Exp_msk1;
- else {
- k = -k;
- word0(db) += k*Exp_msk1;
- }
-#endif
- return dval(da) / dval(db);
- }
-
- static CONST_ double
-tens[] = {
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
- 1e20, 1e21, 1e22
-#ifdef VAX
- , 1e23, 1e24
-#endif
- };
-
- static CONST_ double
-#ifdef IEEE_Arith
-bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static CONST_ double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
- 9007199254740992.*9007199254740992.e-256
- /* = 2^106 * 1e-53 */
-#else
- 1e-256
-#endif
- };
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-#else
-#ifdef IBM
-bigtens[] = { 1e16, 1e32, 1e64 };
-static CONST_ double tinytens[] = { 1e-16, 1e-32, 1e-64 };
-#define n_bigtens 3
-#else
-bigtens[] = { 1e16, 1e32 };
-static CONST_ double tinytens[] = { 1e-16, 1e-32 };
-#define n_bigtens 2
-#endif
-#endif
-
-#ifndef IEEE_Arith
-#undef INFNAN_CHECK
-#endif
-
-#ifdef INFNAN_CHECK
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
- static int
-match
-#ifdef KR_headers
- (sp, t) char **sp, *t;
-#else
- (CONST_ char **sp, CONST_ char *t)
-#endif
-{
- int c, d;
- CONST_ char *s = *sp;
-
- while((d = *t++)) {
- if ((c = *++s) >= 'A' && c <= 'Z')
- c += 'a' - 'A';
- if (c != d)
- return 0;
- }
- *sp = s + 1;
- return 1;
- }
-
-#ifndef No_Hex_NaN
- static void
-hexnan
-#ifdef KR_headers
- (rvp, sp) double *rvp; CONST_ char **sp;
-#else
- (double *rvp, CONST_ char **sp)
-#endif
-{
- ULong c, x[2];
- CONST_ char *s;
- int havedig, udx0, xshift;
-
- x[0] = x[1] = 0;
- havedig = xshift = 0;
- udx0 = 1;
- s = *sp;
- while((c = *(CONST_ unsigned char*)++s)) {
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'a' && c <= 'f')
- c += 10 - 'a';
- else if (c >= 'A' && c <= 'F')
- c += 10 - 'A';
- else if (c <= ' ') {
- if (udx0 && havedig) {
- udx0 = 0;
- xshift = 1;
- }
- continue;
- }
- else if (/*(*/ c == ')' && havedig) {
- *sp = s + 1;
- break;
- }
- else
- return; /* invalid form: don't change *sp */
- havedig = 1;
- if (xshift) {
- xshift = 0;
- x[0] = x[1];
- x[1] = 0;
- }
- if (udx0)
- x[0] = (x[0] << 4) | (x[1] >> 28);
- x[1] = (x[1] << 4) | c;
- }
- if ((x[0] &= 0xfffff) || x[1]) {
- word0(*rvp) = Exp_mask | x[0];
- word1(*rvp) = x[1];
- }
- }
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
- double
-strtod
-#ifdef KR_headers
- (s00, se) CONST_ char *s00; char **se;
-#else
- (CONST_ char *s00, char **se)
-#endif
-{
-#ifdef Avoid_Underflow
- int scale;
-#endif
- int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
- e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
- CONST_ char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
- Long L;
- ULong y, z;
- Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
-
- sign = nz0 = nz = 0;
- dval(rv) = 0.;
- for(s = s00;;s++) switch(*s) {
- case '-':
- sign = 1;
- /* no break */
- case '+':
- if (*++s)
- goto break2;
- /* no break */
- case 0:
- goto ret0;
- case '\t':
- case '\n':
- case '\v':
- case '\f':
- case '\r':
- case ' ':
- continue;
- default:
- goto break2;
- }
- break2:
- if (*s == '0') {
- nz0 = 1;
- while(*++s == '0') ;
- if (!*s)
- goto ret;
- }
- s0 = s;
- y = z = 0;
- for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
- if (nd < 9)
- y = 10*y + c - '0';
- else if (nd < 16)
- z = 10*z + c - '0';
- nd0 = nd;
- if (c == '.') {
- c = *++s;
- if (!nd) {
- for(; c == '0'; c = *++s)
- nz++;
- if (c > '0' && c <= '9') {
- s0 = s;
- nf += nz;
- nz = 0;
- goto have_dig;
- }
- goto dig_done;
- }
- for(; c >= '0' && c <= '9'; c = *++s) {
- have_dig:
- nz++;
- if (c -= '0') {
- nf += nz;
- for(i = 1; i < nz; i++)
- if (nd++ < 9)
- y *= 10;
- else if (nd <= DBL_DIG + 1)
- z *= 10;
- if (nd++ < 9)
- y = 10*y + c;
- else if (nd <= DBL_DIG + 1)
- z = 10*z + c;
- nz = 0;
- }
- }
- }
- dig_done:
- e = 0;
- if (c == 'e' || c == 'E') {
- if (!nd && !nz && !nz0) {
- goto ret0;
- }
- s00 = s;
- esign = 0;
- switch(c = *++s) {
- case '-':
- esign = 1;
- case '+':
- c = *++s;
- }
- if (c >= '0' && c <= '9') {
- while(c == '0')
- c = *++s;
- if (c > '0' && c <= '9') {
- L = c - '0';
- s1 = s;
- while((c = *++s) >= '0' && c <= '9')
- L = 10*L + c - '0';
- if (s - s1 > 8 || L > 19999)
- /* Avoid confusion from exponents
- * so large that e might overflow.
- */
- e = 19999; /* safe for 16 bit ints */
- else
- e = (int)L;
- if (esign)
- e = -e;
- }
- else
- e = 0;
- }
- else
- s = s00;
- }
- if (!nd) {
- if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
- /* Check for Nan and Infinity */
- switch(c) {
- case 'i':
- case 'I':
- if (match(&s,"nf")) {
- --s;
- if (!match(&s,"inity"))
- ++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
- goto ret;
- }
- break;
- case 'n':
- case 'N':
- if (match(&s, "an")) {
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
- if (*s == '(') /*)*/
- hexnan(&rv, &s);
-#endif
- goto ret;
- }
- }
-#endif /* INFNAN_CHECK */
- ret0:
- s = s00;
- sign = 0;
- }
- goto ret;
- }
- e1 = e -= nf;
-
- /* Now we have nd0 digits, starting at s0, followed by a
- * decimal point, followed by nd-nd0 digits. The number we're
- * after is the integer represented by those digits times
- * 10**e */
-
- if (!nd0)
- nd0 = nd;
- k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
- if (k > 9) {
-#ifdef SET_INEXACT
- if (k > DBL_DIG)
- oldinexact = get_inexact();
-#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
- }
- bd0 = 0;
- if (nd <= DBL_DIG
-#ifndef RND_PRODQUOT
-#ifndef Honor_FLT_ROUNDS
- && Flt_Rounds == 1
-#endif
-#endif
- ) {
- if (!e)
- goto ret;
- if (e > 0) {
- if (e <= Ten_pmax) {
-#ifdef VAX
- goto vax_ovfl_check;
-#else
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- rv = -rv;
- sign = 0;
- }
-#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
- goto ret;
-#endif
- }
- i = DBL_DIG - nd;
- if (e <= Ten_pmax + i) {
- /* A fancier test would sometimes let us do
- * this for larger i values.
- */
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- rv = -rv;
- sign = 0;
- }
-#endif
- e -= i;
- dval(rv) *= tens[i];
-#ifdef VAX
- /* VAX exponent range is so narrow we must
- * worry about overflow here...
- */
- vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
- goto ovfl;
- word0(rv) += P*Exp_msk1;
-#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
-#endif
- goto ret;
- }
- }
-#ifndef Inaccurate_Divide
- else if (e >= -Ten_pmax) {
-#ifdef Honor_FLT_ROUNDS
- /* round correctly FLT_ROUNDS = 2 or 3 */
- if (sign) {
- rv = -rv;
- sign = 0;
- }
-#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- goto ret;
- }
-#endif
- }
- e1 += nd - k;
-
-#ifdef IEEE_Arith
-#ifdef SET_INEXACT
- inexact = 1;
- if (k <= DBL_DIG)
- oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
- scale = 0;
-#endif
-#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
- if (sign)
- rounding = rounding == 2 ? 0 : 2;
- else
- if (rounding != 2)
- rounding = 0;
- }
-#endif
-#endif /*IEEE_Arith*/
-
- /* Get starting approximation = rv * 10**e1 */
-
- if (e1 > 0) {
- if ((i = e1 & 15))
- dval(rv) *= tens[i];
- if (e1 &= ~15) {
- if (e1 > DBL_MAX_10_EXP) {
- ovfl:
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- /* Can't trust HUGE_VAL */
-#ifdef IEEE_Arith
-#ifdef Honor_FLT_ROUNDS
- switch(rounding) {
- case 0: /* toward 0 */
- case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
- break;
- default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
- }
-#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
-#endif /*Honor_FLT_ROUNDS*/
-#ifdef SET_INEXACT
- /* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
-#endif
-#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
-#endif /*IEEE_Arith*/
- if (bd0)
- goto retfree;
- goto ret;
- }
- e1 >>= 4;
- for(j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= bigtens[j];
- /* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-P))
- goto ovfl;
- if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
- /* set to largest number */
- /* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- }
- else if (e1 < 0) {
- e1 = -e1;
- if ((i = e1 & 15))
- dval(rv) /= tens[i];
- if (e1 >>= 4) {
- if (e1 >= 1 << n_bigtens)
- goto undfl;
-#ifdef Avoid_Underflow
- if (e1 & Scale_Bit)
- scale = 2*P;
- for(j = 0; e1 > 0; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
- >> Exp_shift)) > 0) {
- /* scaled rv is denormal; zap j low bits */
- if (j >= 32) {
- word1(rv) = 0;
- if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
- else
- word0(rv) &= 0xffffffff << j-32;
- }
- else
- word1(rv) &= 0xffffffff << j;
- }
-#else
- for(j = 0; e1 > 1; j++, e1 >>= 1)
- if (e1 & 1)
- dval(rv) *= tinytens[j];
- /* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
-#endif
- if (!dval(rv)) {
- undfl:
- dval(rv) = 0.;
-#ifndef NO_ERRNO
- errno = ERANGE;
-#endif
- if (bd0)
- goto retfree;
- goto ret;
- }
-#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- /* The refinement below will clean
- * this approximation up.
- */
- }
-#endif
- }
- }
-
- /* Now the hard part -- adjusting rv to the correct value.*/
-
- /* Put digits into bd: true value = bd * 10^e */
-
- bd0 = s2b(s0, nd0, nd, y);
-
- for(;;) {
- bd = Balloc(bd0->k);
- Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
- bs = i2b(1);
-
- if (e >= 0) {
- bb2 = bb5 = 0;
- bd2 = bd5 = e;
- }
- else {
- bb2 = bb5 = -e;
- bd2 = bd5 = 0;
- }
- if (bbe >= 0)
- bb2 += bbe;
- else
- bd2 -= bbe;
- bs2 = bb2;
-#ifdef Honor_FLT_ROUNDS
- if (rounding != 1)
- bs2++;
-#endif
-#ifdef Avoid_Underflow
- j = bbe - scale;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
-#ifdef IBM
- j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
-#else
- j = P + 1 - bbbits;
-#endif
-#else /*Sudden_Underflow*/
- j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j += P - Emin;
- else
- j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- bb2 += j;
- bd2 += j;
-#ifdef Avoid_Underflow
- bd2 += scale;
-#endif
- i = bb2 < bd2 ? bb2 : bd2;
- if (i > bs2)
- i = bs2;
- if (i > 0) {
- bb2 -= i;
- bd2 -= i;
- bs2 -= i;
- }
- if (bb5 > 0) {
- bs = pow5mult(bs, bb5);
- bb1 = mult(bs, bb);
- Bfree(bb);
- bb = bb1;
- }
- if (bb2 > 0)
- bb = lshift(bb, bb2);
- if (bd5 > 0)
- bd = pow5mult(bd, bd5);
- if (bd2 > 0)
- bd = lshift(bd, bd2);
- if (bs2 > 0)
- bs = lshift(bs, bs2);
- delta = diff(bb, bd);
- dsign = delta->sign;
- delta->sign = 0;
- i = cmp(delta, bs);
-#ifdef Honor_FLT_ROUNDS
- if (rounding != 1) {
- if (i < 0) {
- /* Error is less than an ulp */
- if (!delta->x[0] && delta->wds <= 1) {
- /* exact */
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- if (rounding) {
- if (dsign) {
- adj = 1.;
- goto apply_adj;
- }
- }
- else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
-#ifdef Avoid_Underflow
- if (!scale || y > 2*P*Exp_msk1)
-#else
- if (y)
-#endif
- {
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) <= 0)
- adj = -0.5;
- }
- }
- apply_adj:
-#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
- <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
- P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
- }
- else
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
- }
- break;
- }
- adj = ratio(delta, bs);
- if (adj < 1.)
- adj = 1.;
- if (adj <= 0x7ffffffe) {
- /* adj = rounding ? ceil(adj) : floor(adj); */
- y = adj;
- if (y != adj) {
- if (!((rounding>>1) ^ dsign))
- y++;
- adj = y;
- }
- }
-#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
- if (dsign)
- dval(rv) += adj;
- else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
- goto cont;
- }
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
- if (dsign)
- dval(rv) += adj;
- else
- dval(rv) -= adj;
- goto cont;
- }
-#endif /*Honor_FLT_ROUNDS*/
-
- if (i < 0) {
- /* Error is less than half an ulp -- check for
- * special case of mantissa a power of two.
- */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
-#ifdef IEEE_Arith
-#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
-#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
-#endif
-#endif
- ) {
-#ifdef SET_INEXACT
- if (!delta->x[0] && delta->wds <= 1)
- inexact = 0;
-#endif
- break;
- }
- if (!delta->x[0] && delta->wds <= 1) {
- /* exact result */
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) > 0)
- goto drop_down;
- break;
- }
- if (i == 0) {
- /* exactly half-way between */
- if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
-#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
-#endif
- 0xffffffff)) {
- /*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
- + Exp_msk1
-#ifdef IBM
- | Exp_msk1 >> 4
-#endif
- ;
- word1(rv) = 0;
-#ifdef Avoid_Underflow
- dsign = 0;
-#endif
- break;
- }
- }
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
- drop_down:
- /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
-#ifdef IBM
- if (L < Exp_msk1)
-#else
-#ifdef Avoid_Underflow
- if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
-#else
- if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
-#endif /*IBM*/
- goto undfl;
- L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
- if (scale) {
- L = word0(rv) & Exp_mask;
- if (L <= (2*P+1)*Exp_msk1) {
- if (L > (P+2)*Exp_msk1)
- /* round even ==> */
- /* accept rv */
- break;
- /* rv = smallest denormal */
- goto undfl;
- }
- }
-#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
-#ifdef IBM
- goto cont;
-#else
- break;
-#endif
- }
-#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
- break;
-#endif
- if (dsign)
- dval(rv) += ulp(dval(rv));
-#ifndef ROUND_BIASED
- else {
- dval(rv) -= ulp(dval(rv));
-#ifndef Sudden_Underflow
- if (!dval(rv))
- goto undfl;
-#endif
- }
-#ifdef Avoid_Underflow
- dsign = 1 - dsign;
-#endif
-#endif
- break;
- }
- if ((aadj = ratio(delta, bs)) <= 2.) {
- if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
- goto undfl;
-#endif
- aadj = 1.;
- aadj1 = -1.;
- }
- else {
- /* special case -- power of FLT_RADIX to be */
- /* rounded down... */
-
- if (aadj < 2./FLT_RADIX)
- aadj = 1./FLT_RADIX;
- else
- aadj *= 0.5;
- aadj1 = -aadj;
- }
- }
- else {
- aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
- switch(Rounding) {
- case 2: /* towards +infinity */
- aadj1 -= 0.5;
- break;
- case 0: /* towards 0 */
- case 3: /* towards -infinity */
- aadj1 += 0.5;
- }
-#else
- if (Flt_Rounds == 0)
- aadj1 += 0.5;
-#endif /*Check_FLT_ROUNDS*/
- }
- y = word0(rv) & Exp_mask;
-
- /* Check for overflow */
-
- if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
- Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
- goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
- goto cont;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- else {
-#ifdef Avoid_Underflow
- if (scale && y <= 2*P*Exp_msk1) {
- if (aadj <= 0x7fffffff) {
- if ((z = (ULong)aadj) <= 0)
- z = 1;
- aadj = z;
- aadj1 = dsign ? aadj : -aadj;
- }
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
- }
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
-#else
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
-#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
-#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
-#endif
- {
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
- goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- goto cont;
- }
- else
- word0(rv) -= P*Exp_msk1;
- }
- else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- }
-#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
- * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
- * trouble from bits lost to denormalization;
- * example: 1.2e-307 .
- */
- if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
- if (!dsign)
- aadj1 = -aadj1;
- }
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
- }
- z = word0(rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
- if (!scale)
-#endif
- if (y == z) {
- /* Can we stop now? */
- L = (Long)aadj;
- aadj -= L;
- /* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
- if (aadj < .4999999 || aadj > .5000001)
- break;
- }
- else if (aadj < .4999999/FLT_RADIX)
- break;
- }
-#endif
- cont:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(delta);
- }
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
- }
- }
- else if (!oldinexact)
- clear_inexact();
-#endif
-#ifdef Avoid_Underflow
- if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
-#ifndef NO_ERRNO
- /* try to avoid the bug of testing an 8087 register value */
- if (word0(rv) == 0 && word1(rv) == 0)
- errno = ERANGE;
-#endif
- }
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
- /* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
- }
-#endif
- retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
- ret:
- if (se)
- *se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
- }
-
- static int
-quorem
-#ifdef KR_headers
- (b, S) Bigint *b, *S;
-#else
- (Bigint *b, Bigint *S)
-#endif
-{
- int n;
- ULong *bx, *bxe, q, *sx, *sxe;
-#ifdef ULLong
- ULLong borrow, carry, y, ys;
-#else
- ULong borrow, carry, y, ys;
-#ifdef Pack_32
- ULong si, z, zs;
-#endif
-#endif
-
- n = S->wds;
-#ifdef DEBUG
- /*debug*/ if (b->wds > n)
- /*debug*/ Bug("oversize b in quorem");
-#endif
- if (b->wds < n)
- return 0;
- sx = S->x;
- sxe = sx + --n;
- bx = b->x;
- bxe = bx + n;
- q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
-#ifdef DEBUG
- /*debug*/ if (q > 9)
- /*debug*/ Bug("oversized quotient in quorem");
-#endif
- if (q) {
- borrow = 0;
- carry = 0;
- do {
-#ifdef ULLong
- ys = *sx++ * (ULLong)q + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = (ULong)y & FFFFFFFF;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) * q + carry;
- zs = (si >> 16) * q + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ * q + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- }
- while(sx <= sxe);
- if (!*bxe) {
- bx = b->x;
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- if (cmp(b, S) >= 0) {
- q++;
- borrow = 0;
- carry = 0;
- bx = b->x;
- sx = S->x;
- do {
-#ifdef ULLong
- ys = *sx++ + carry;
- carry = ys >> 32;
- y = *bx - (ys & FFFFFFFF) - borrow;
- borrow = y >> 32 & (ULong)1;
- *bx++ = (ULong)y & FFFFFFFF;
-#else
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) + carry;
- zs = (si >> 16) + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- z = (*bx >> 16) - (zs & 0xffff) - borrow;
- borrow = (z & 0x10000) >> 16;
- Storeinc(bx, z, y);
-#else
- ys = *sx++ + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) - borrow;
- borrow = (y & 0x10000) >> 16;
- *bx++ = y & 0xffff;
-#endif
-#endif
- }
- while(sx <= sxe);
- bx = b->x;
- bxe = bx + n;
- if (!*bxe) {
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- return q;
- }
-
-#ifndef MULTIPLE_THREADS
- static char *dtoa_result;
-#endif
-
- static char *
-#ifdef KR_headers
-rv_alloc(i) int i;
-#else
-rv_alloc(int i)
-#endif
-{
- int j, k, *r;
-
- j = sizeof(ULong);
- for(k = 0;
- sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned)i;
- j <<= 1)
- k++;
- r = (int*)Balloc(k);
- *r = k;
- return
-#ifndef MULTIPLE_THREADS
- dtoa_result =
-#endif
- (char *)(r+1);
- }
-
- static char *
-#ifdef KR_headers
-nrv_alloc(s, rve, n) char *s, **rve; int n;
-#else
-nrv_alloc(CONST_ char *s, char **rve, int n)
-#endif
-{
- char *rv, *t;
-
- t = rv = rv_alloc(n);
- while((*t = *s++)) t++;
- if (rve)
- *rve = t;
- return rv;
- }
-
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined. It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
- void
-#ifdef KR_headers
-freedtoa(s) char *s;
-#else
-freedtoa(char *s)
-#endif
-{
- Bigint *b = (Bigint *)((int *)s - 1);
- b->maxwds = 1 << (b->k = *(int*)b);
- Bfree(b);
-#ifndef MULTIPLE_THREADS
- if (s == dtoa_result)
- dtoa_result = 0;
-#endif
- }
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- * 1. Rather than iterating, we use a simple numeric overestimate
- * to determine k = floor(log10(d)). We scale relevant
- * quantities using O(log2(k)) rather than O(k) multiplications.
- * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- * try to generate digits strictly left to right. Instead, we
- * compute with fewer bits and propagate the carry if necessary
- * when rounding the final digit up. This is often faster.
- * 3. Under the assumption that input will be rounded nearest,
- * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- * That is, we allow equality in stopping tests when the
- * round-nearest rule will give the same floating-point value
- * as would satisfaction of the stopping test with strict
- * inequality.
- * 4. We remove common factors of powers of 2 from relevant
- * quantities.
- * 5. When converting floating-point integers less than 1e16,
- * we use floating-point arithmetic rather than resorting
- * to multiple-precision integers.
- * 6. When asked to produce fewer than 15 digits, we first try
- * to get by with floating-point arithmetic; we resort to
- * multiple-precision integer arithmetic only if we cannot
- * guarantee that the floating-point calculation has given
- * the correctly rounded result. For k requested digits and
- * "uniformly" distributed input, the probability is
- * something like 10^(k-15) that we must resort to the Long
- * calculation.
- */
-
- char *
-dtoa
-#ifdef KR_headers
- (d, mode, ndigits, decpt, sign, rve)
- double d; int mode, ndigits, *decpt, *sign; char **rve;
-#else
- (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
-#endif
-{
- /* Arguments ndigits, decpt, sign are similar to those
- of ecvt and fcvt; trailing zeros are suppressed from
- the returned string. If not null, *rve is set to point
- to the end of the return value. If d is +-Infinity or NaN,
- then *decpt is set to 9999.
-
- mode:
- 0 ==> shortest string that yields d when read in
- and rounded to nearest.
- 1 ==> like 0, but with Steele & White stopping rule;
- e.g. with IEEE P754 arithmetic , mode 0 gives
- 1e23 whereas mode 1 gives 9.999999999999999e22.
- 2 ==> max(1,ndigits) significant digits. This gives a
- return value similar to that of ecvt, except
- that trailing zeros are suppressed.
- 3 ==> through ndigits past the decimal point. This
- gives a return value similar to that from fcvt,
- except that trailing zeros are suppressed, and
- ndigits can be negative.
- 4,5 ==> similar to 2 and 3, respectively, but (in
- round-nearest mode) with the tests of mode 0 to
- possibly return a shorter string that rounds to d.
- With IEEE arithmetic and compilation with
- -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
- as modes 2 and 3 when FLT_ROUNDS != 1.
- 6-9 ==> Debugging modes similar to mode - 4: don't try
- fast floating-point estimate (if applicable).
-
- Values of mode other than 0-9 are treated as mode 0.
-
- Sufficient space is allocated to the return value
- to hold the suppressed trailing zeros.
- */
-
- int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
- j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
- spec_case, try_quick;
- Long L;
-#ifndef Sudden_Underflow
- int denorm;
- ULong x;
-#endif
- Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
- double d2, ds, eps;
- char *s, *s0;
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
-#ifdef SET_INEXACT
- int inexact, oldinexact;
-#endif
-
-#ifndef MULTIPLE_THREADS
- if (dtoa_result) {
- freedtoa(dtoa_result);
- dtoa_result = 0;
- }
-#endif
-
- if (word0(d) & Sign_bit) {
- /* set sign for everything, including 0's and NaNs */
- *sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
- }
- else
- *sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
-#else
- if (word0(d) == 0x8000)
-#endif
- {
- /* Infinity or NaN */
- *decpt = 9999;
-#ifdef IEEE_Arith
- if (!word1(d) && !(word0(d) & 0xfffff))
- return nrv_alloc("Infinity", rve, 8);
-#endif
- return nrv_alloc("NaN", rve, 3);
- }
-#endif
-#ifdef IBM
- dval(d) += 0; /* normalize */
-#endif
- if (!dval(d)) {
- *decpt = 1;
- return nrv_alloc("0", rve, 1);
- }
-
-#ifdef SET_INEXACT
- try_quick = oldinexact = get_inexact();
- inexact = 1;
-#endif
-#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
- if (*sign)
- rounding = rounding == 2 ? 0 : 2;
- else
- if (rounding != 2)
- rounding = 0;
- }
-#endif
-
- b = d2b(dval(d), &be, &bbits);
-#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
-#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
-#ifdef IBM
- if (j = 11 - hi0bits(word0(d2) & Frac_mask))
- dval(d2) /= 1 << j;
-#endif
-
- /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
- * log10(x) = log(x) / log(10)
- * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
- *
- * This suggests computing an approximation k to log10(d) by
- *
- * k = (i - Bias)*0.301029995663981
- * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
- *
- * We want k to be too large rather than too small.
- * The error in the first-order Taylor series approximation
- * is in our favor, so we just round up the constant enough
- * to compensate for any error in the multiplication of
- * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
- * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
- * adding 1e-13 to the constant term more than suffices.
- * Hence we adjust the constant term to 0.1760912590558.
- * (We could get a more accurate k by invoking log10,
- * but this is probably not worthwhile.)
- */
-
- i -= Bias;
-#ifdef IBM
- i <<= 2;
- i += j;
-#endif
-#ifndef Sudden_Underflow
- denorm = 0;
- }
- else {
- /* d is denormalized */
-
- i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
- dval(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
- i -= (Bias + (P-1) - 1) + 1;
- denorm = 1;
- }
-#endif
- ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
- k = (int)ds;
- if (ds < 0. && ds != k)
- k--; /* want k = floor(ds) */
- k_check = 1;
- if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
- k--;
- k_check = 0;
- }
- j = bbits - i - 1;
- if (j >= 0) {
- b2 = 0;
- s2 = j;
- }
- else {
- b2 = -j;
- s2 = 0;
- }
- if (k >= 0) {
- b5 = 0;
- s5 = k;
- s2 += k;
- }
- else {
- b2 -= k;
- b5 = -k;
- s5 = 0;
- }
- if (mode < 0 || mode > 9)
- mode = 0;
-
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
- try_quick = Rounding == 1;
-#else
- try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
-
- if (mode > 5) {
- mode -= 4;
- try_quick = 0;
- }
- leftright = 1;
- switch(mode) {
- case 0:
- case 1:
- ilim = ilim1 = -1;
- i = 18;
- ndigits = 0;
- break;
- case 2:
- leftright = 0;
- /* no break */
- case 4:
- if (ndigits <= 0)
- ndigits = 1;
- ilim = ilim1 = i = ndigits;
- break;
- case 3:
- leftright = 0;
- /* no break */
- case 5:
- i = ndigits + k + 1;
- ilim = i;
- ilim1 = i - 1;
- if (i <= 0)
- i = 1;
- }
- s = s0 = rv_alloc(i);
-
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1 && rounding != 1)
- leftright = 0;
-#endif
-
- if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
- /* Try to get by with floating-point arithmetic. */
-
- i = 0;
- dval(d2) = dval(d);
- k0 = k;
- ilim0 = ilim;
- ieps = 2; /* conservative */
- if (k > 0) {
- ds = tens[k&0xf];
- j = k >> 4;
- if (j & Bletch) {
- /* prevent overflows */
- j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
- ieps++;
- }
- for(; j; j >>= 1, i++)
- if (j & 1) {
- ieps++;
- ds *= bigtens[i];
- }
- dval(d) /= ds;
- }
- else if ((j1 = -k)) {
- dval(d) *= tens[j1 & 0xf];
- for(j = j1 >> 4; j; j >>= 1, i++)
- if (j & 1) {
- ieps++;
- dval(d) *= bigtens[i];
- }
- }
- if (k_check && dval(d) < 1. && ilim > 0) {
- if (ilim1 <= 0)
- goto fast_failed;
- ilim = ilim1;
- k--;
- dval(d) *= 10.;
- ieps++;
- }
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
- if (ilim == 0) {
- S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
- goto one_digit;
- if (dval(d) < -dval(eps))
- goto no_digits;
- goto fast_failed;
- }
-#ifndef No_leftright
- if (leftright) {
- /* Use Steele & White method of only
- * generating digits needed.
- */
- dval(eps) = 0.5/tens[ilim-1] - dval(eps);
- for(i = 0;;) {
- L = (long int)dval(d);
- dval(d) -= L;
- *s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
- goto ret1;
- if (1. - dval(d) < dval(eps))
- goto bump_up;
- if (++i >= ilim)
- break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
- }
- }
- else {
-#endif
- /* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim-1];
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d));
- if (!(dval(d) -= L))
- ilim = i;
- *s++ = '0' + (int)L;
- if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
- goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
- while (*--s == '0') { }
- s++;
- goto ret1;
- }
- break;
- }
- }
-#ifndef No_leftright
- }
-#endif
- fast_failed:
- s = s0;
- dval(d) = dval(d2);
- k = k0;
- ilim = ilim0;
- }
-
- /* Do we have a "small" integer? */
-
- if (be >= 0 && k <= Int_max) {
- /* Yes. */
- ds = tens[k];
- if (ndigits < 0 && ilim <= 0) {
- S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
- goto no_digits;
- goto one_digit;
- }
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d) / ds);
- dval(d) -= L*ds;
-#ifdef Check_FLT_ROUNDS
- /* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
- L--;
- dval(d) += ds;
- }
-#endif
- *s++ = '0' + (int)L;
- if (!dval(d)) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- break;
- }
- if (i == ilim) {
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1)
- switch(rounding) {
- case 0: goto ret1;
- case 2: goto bump_up;
- }
-#endif
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
- bump_up:
- while(*--s == '9')
- if (s == s0) {
- k++;
- *s = '0';
- break;
- }
- ++*s++;
- }
- break;
- }
- }
- goto ret1;
- }
-
- m2 = b2;
- m5 = b5;
- mhi = mlo = 0;
- if (leftright) {
- i =
-#ifndef Sudden_Underflow
- denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
- 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
- 1 + P - bbits;
-#endif
- b2 += i;
- s2 += i;
- mhi = i2b(1);
- }
- if (m2 > 0 && s2 > 0) {
- i = m2 < s2 ? m2 : s2;
- b2 -= i;
- m2 -= i;
- s2 -= i;
- }
- if (b5 > 0) {
- if (leftright) {
- if (m5 > 0) {
- mhi = pow5mult(mhi, m5);
- b1 = mult(mhi, b);
- Bfree(b);
- b = b1;
- }
- if ((j = b5 - m5))
- b = pow5mult(b, j);
- }
- else
- b = pow5mult(b, b5);
- }
- S = i2b(1);
- if (s5 > 0)
- S = pow5mult(S, s5);
-
- /* Check for special case that d is a normalized power of 2. */
-
- spec_case = 0;
- if ((mode < 2 || leftright)
-#ifdef Honor_FLT_ROUNDS
- && rounding == 1
-#endif
- ) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
-#endif
- ) {
- /* The special case */
- b2 += Log2P;
- s2 += Log2P;
- spec_case = 1;
- }
- }
-
- /* Arrange for convenient computation of quotients:
- * shift left if necessary so divisor has 4 leading 0 bits.
- *
- * Perhaps we should just compute leading 28 bits of S once
- * and for all and pass them and a shift to quorem, so it
- * can do shifts and ors to compute the numerator for q.
- */
-#ifdef Pack_32
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
- i = 32 - i;
-#else
- if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
- i = 16 - i;
-#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
- b = lshift(b, b2);
- if (s2 > 0)
- S = lshift(S, s2);
- if (k_check) {
- if (cmp(b,S) < 0) {
- k--;
- b = multadd(b, 10, 0); /* we botched the k estimate */
- if (leftright)
- mhi = multadd(mhi, 10, 0);
- ilim = ilim1;
- }
- }
- if (ilim <= 0 && (mode == 3 || mode == 5)) {
- if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
- /* no digits, fcvt style */
- no_digits:
- k = -1 - ndigits;
- goto ret;
- }
- one_digit:
- *s++ = '1';
- k++;
- goto ret;
- }
- if (leftright) {
- if (m2 > 0)
- mhi = lshift(mhi, m2);
-
- /* Compute mlo -- check for special case
- * that d is a normalized power of 2.
- */
-
- mlo = mhi;
- if (spec_case) {
- mhi = Balloc(mhi->k);
- Bcopy(mhi, mlo);
- mhi = lshift(mhi, Log2P);
- }
-
- for(i = 1;;i++) {
- dig = quorem(b,S) + '0';
- /* Do we yet have the shortest decimal string
- * that will round to d?
- */
- j = cmp(b, mlo);
- delta = diff(S, mhi);
- j1 = delta->sign ? 1 : cmp(b, delta);
- Bfree(delta);
-#ifndef ROUND_BIASED
- if (j1 == 0 && mode != 1 && !(word1(d) & 1)
-#ifdef Honor_FLT_ROUNDS
- && rounding >= 1
-#endif
- ) {
- if (dig == '9')
- goto round_9_up;
- if (j > 0)
- dig++;
-#ifdef SET_INEXACT
- else if (!b->x[0] && b->wds <= 1)
- inexact = 0;
-#endif
- *s++ = dig;
- goto ret;
- }
-#endif
- if (j < 0 || j == 0 && mode != 1
-#ifndef ROUND_BIASED
- && !(word1(d) & 1)
-#endif
- ) {
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto accept_dig;
- }
-#ifdef Honor_FLT_ROUNDS
- if (mode > 1)
- switch(rounding) {
- case 0: goto accept_dig;
- case 2: goto keep_dig;
- }
-#endif /*Honor_FLT_ROUNDS*/
- if (j1 > 0) {
- b = lshift(b, 1);
- j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
- && dig++ == '9')
- goto round_9_up;
- }
- accept_dig:
- *s++ = dig;
- goto ret;
- }
- if (j1 > 0) {
-#ifdef Honor_FLT_ROUNDS
- if (!rounding)
- goto accept_dig;
-#endif
- if (dig == '9') { /* possible if i == 1 */
- round_9_up:
- *s++ = '9';
- goto roundoff;
- }
- *s++ = dig + 1;
- goto ret;
- }
-#ifdef Honor_FLT_ROUNDS
- keep_dig:
-#endif
- *s++ = dig;
- if (i == ilim)
- break;
- b = multadd(b, 10, 0);
- if (mlo == mhi)
- mlo = mhi = multadd(mhi, 10, 0);
- else {
- mlo = multadd(mlo, 10, 0);
- mhi = multadd(mhi, 10, 0);
- }
- }
- }
- else
- for(i = 1;; i++) {
- *s++ = dig = quorem(b,S) + '0';
- if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
- inexact = 0;
-#endif
- goto ret;
- }
- if (i >= ilim)
- break;
- b = multadd(b, 10, 0);
- }
-
- /* Round off last digit */
-
-#ifdef Honor_FLT_ROUNDS
- switch(rounding) {
- case 0: goto trimzeros;
- case 2: goto roundoff;
- }
-#endif
- b = lshift(b, 1);
- j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
- roundoff:
- while(*--s == '9')
- if (s == s0) {
- k++;
- *s++ = '1';
- goto ret;
- }
- ++*s++;
- }
- else {
-#ifdef Honor_FLT_ROUNDS
-trimzeros:
-#endif
- while (*--s == '0') { }
- s++;
- }
- ret:
- Bfree(S);
- if (mhi) {
- if (mlo && mlo != mhi)
- Bfree(mlo);
- Bfree(mhi);
- }
- ret1:
-#ifdef SET_INEXACT
- if (inexact) {
- if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
- }
- }
- else if (!oldinexact)
- clear_inexact();
-#endif
- Bfree(b);
- *s = 0;
- *decpt = k + 1;
- if (rve)
- *rve = s;
- return s0;
- }
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _KJS_DTOA_H_
-#define _KJS_DTOA_H_
-
-extern "C" double kjs_strtod(const char *s00, char **se);
-extern "C" char *kjs_dtoa(double d, int mode, int ndigits,
- int *decpt, int *sign, char **rve);
-extern "C" void kjs_freedtoa(char *s);
-
-#endif /* _KJS_DTOA_H */
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "error_object.h"
-
-#include "JSGlobalObject.h"
-#include "object.h"
-#include "operations.h"
-#include "types.h"
-#include "value.h"
-
-namespace KJS {
-
-// ------------------------------ ErrorInstance ----------------------------
-
-const ClassInfo ErrorInstance::info = { "Error", 0, 0 };
-
-ErrorInstance::ErrorInstance(JSObject* prototype)
- : JSObject(prototype)
-{
-}
-
-// ------------------------------ ErrorPrototype ----------------------------
-
-// ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
- : ErrorInstance(objectPrototype)
-{
- // The constructor will be added later in ErrorObjectImp's constructor
-
- putDirect(exec->propertyNames().name, jsString("Error"), DontEnum);
- putDirect(exec->propertyNames().message, jsString("Unknown error"), DontEnum);
-
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
-}
-
-JSValue* errorProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- UString s = "Error";
-
- JSValue* v = thisObj->get(exec, exec->propertyNames().name);
- if (!v->isUndefined())
- s = v->toString(exec);
-
- v = thisObj->get(exec, exec->propertyNames().message);
- if (!v->isUndefined())
- // Mozilla compatible format
- s += ": " + v->toString(exec);
-
- return jsString(s);
-}
-
-// ------------------------------ ErrorObjectImp -------------------------------
-
-ErrorObjectImp::ErrorObjectImp(ExecState* exec, FunctionPrototype* funcProto, ErrorPrototype* errorProto)
- : InternalFunctionImp(funcProto, errorProto->classInfo()->className)
-{
- // ECMA 15.11.3.1 Error.prototype
- putDirect(exec->propertyNames().prototype, errorProto, DontEnum|DontDelete|ReadOnly);
- putDirect(exec->propertyNames().length, jsNumber(1), DontDelete|ReadOnly|DontEnum);
-}
-
-bool ErrorObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.9.3
-JSObject* ErrorObjectImp::construct(ExecState* exec, const List& args)
-{
- JSObject* proto = static_cast<JSObject*>(exec->lexicalGlobalObject()->errorPrototype());
- JSObject* imp = new ErrorInstance(proto);
- JSObject* obj(imp);
-
- if (!args[0]->isUndefined())
- imp->putDirect(exec->propertyNames().message, jsString(args[0]->toString(exec)));
-
- return obj;
-}
-
-// ECMA 15.9.2
-JSValue* ErrorObjectImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, const List& args)
-{
- // "Error()" gives the sames result as "new Error()"
- return construct(exec, args);
-}
-
-// ------------------------------ NativeErrorPrototype ----------------------
-
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, ErrorPrototype* errorProto, const UString& name, const UString& message)
- : JSObject(errorProto)
-{
- putDirect(exec->propertyNames().name, jsString(name), 0);
- putDirect(exec->propertyNames().message, jsString(message), 0);
-}
-
-// ------------------------------ NativeErrorImp -------------------------------
-
-const ClassInfo NativeErrorImp::info = { "Function", &InternalFunctionImp::info, 0 };
-
-NativeErrorImp::NativeErrorImp(ExecState* exec, FunctionPrototype* funcProto, NativeErrorPrototype* prot)
- : InternalFunctionImp(funcProto, Identifier(prot->getDirect(exec->propertyNames().name)->getString()))
- , proto(prot)
-{
- putDirect(exec->propertyNames().length, jsNumber(1), DontDelete|ReadOnly|DontEnum); // ECMA 15.11.7.5
- putDirect(exec->propertyNames().prototype, proto, DontDelete|ReadOnly|DontEnum);
-}
-
-bool NativeErrorImp::implementsConstruct() const
-{
- return true;
-}
-
-JSObject* NativeErrorImp::construct(ExecState* exec, const List& args)
-{
- JSObject* imp = new ErrorInstance(proto);
- JSObject* obj(imp);
- if (!args[0]->isUndefined())
- imp->putDirect(exec->propertyNames().message, jsString(args[0]->toString(exec)));
- return obj;
-}
-
-JSValue* NativeErrorImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- return construct(exec, args);
-}
-
-void NativeErrorImp::mark()
-{
- JSObject::mark();
- if (proto && !proto->marked())
- proto->mark();
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef ERROR_OBJECT_H_
-#define ERROR_OBJECT_H_
-
-#include "function_object.h"
-
-namespace KJS {
-
- class ErrorInstance : public JSObject {
- public:
- ErrorInstance(JSObject* prototype);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class ErrorPrototype : public ErrorInstance {
- public:
- ErrorPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
- };
-
- JSValue* errorProtoFuncToString(ExecState*, JSObject*, const List&);
-
- class ErrorObjectImp : public InternalFunctionImp {
- public:
- ErrorObjectImp(ExecState*, FunctionPrototype*, ErrorPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
-
- class NativeErrorPrototype : public JSObject {
- public:
- NativeErrorPrototype(ExecState*, ErrorPrototype*, const UString& name, const UString& message);
- };
-
- class NativeErrorImp : public InternalFunctionImp {
- public:
- NativeErrorImp(ExecState*, FunctionPrototype*, NativeErrorPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
-
- virtual void mark();
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- private:
- JSObject* proto;
- };
-
-} // namespace KJS
-
-#endif // ERROR_OBJECT_H_
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "function.h"
-
-#include "Activation.h"
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "Parser.h"
-#include "PropertyNameArray.h"
-#include "debugger.h"
-#include "dtoa.h"
-#include "function_object.h"
-#include "internal.h"
-#include "lexer.h"
-#include "nodes.h"
-#include "operations.h"
-#include "scope_chain_mark.h"
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/Assertions.h>
-#include <wtf/MathExtras.h>
-#include <wtf/unicode/UTF8.h>
-
-using namespace WTF;
-using namespace Unicode;
-
-namespace KJS {
-
-// ----------------------------- FunctionImp ----------------------------------
-
-const ClassInfo FunctionImp::info = { "Function", &InternalFunctionImp::info, 0 };
-
-FunctionImp::FunctionImp(ExecState* exec, const Identifier& name, FunctionBodyNode* b, const ScopeChain& sc)
- : InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), name)
- , body(b)
- , _scope(sc)
-{
-}
-
-void FunctionImp::mark()
-{
- InternalFunctionImp::mark();
- _scope.mark();
-}
-
-JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
-{
- FunctionExecState newExec(exec->dynamicGlobalObject(), thisObj, body.get(), exec, this, args);
- JSValue* result = body->execute(&newExec);
- if (newExec.completionType() == Throw) {
- exec->setException(result);
- return result;
- }
- if (newExec.completionType() == ReturnValue)
- return result;
- return jsUndefined();
-}
-
-JSValue* FunctionImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
-{
- FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
-
- for (ExecState* e = exec; e; e = e->callingExecState())
- if (e->function() == thisObj) {
- e->dynamicGlobalObject()->tearOffActivation(e, e != exec);
- return e->activationObject()->get(exec, propertyName);
- }
-
- return jsNull();
-}
-
-JSValue* FunctionImp::callerGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
- ExecState* e = exec;
- while (e) {
- if (e->function() == thisObj)
- break;
- e = e->callingExecState();
- }
-
- if (!e)
- return jsNull();
-
- ExecState* callingExecState = e->callingExecState();
- if (!callingExecState)
- return jsNull();
-
- FunctionImp* callingFunction = callingExecState->function();
- if (!callingFunction)
- return jsNull();
-
- return callingFunction;
-}
-
-JSValue* FunctionImp::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
- return jsNumber(thisObj->body->parameters().size());
-}
-
-bool FunctionImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- // Find the arguments from the closest context.
- if (propertyName == exec->propertyNames().arguments) {
- slot.setCustom(this, argumentsGetter);
- return true;
- }
-
- // Compute length of parameters.
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- if (propertyName == exec->propertyNames().caller) {
- slot.setCustom(this, callerGetter);
- return true;
- }
-
- return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-void FunctionImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
-{
- if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
- return;
- InternalFunctionImp::put(exec, propertyName, value, attr);
-}
-
-bool FunctionImp::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
- return false;
- return InternalFunctionImp::deleteProperty(exec, propertyName);
-}
-
-/* Returns the parameter name corresponding to the given index. eg:
- * function f1(x, y, z): getParameterName(0) --> x
- *
- * If a name appears more than once, only the last index at which
- * it appears associates with it. eg:
- * function f2(x, x): getParameterName(0) --> null
- */
-Identifier FunctionImp::getParameterName(int index)
-{
- Vector<Identifier>& parameters = body->parameters();
-
- if (static_cast<size_t>(index) >= body->parameters().size())
- return CommonIdentifiers::shared()->nullIdentifier;
-
- Identifier name = parameters[index];
-
- // Are there any subsequent parameters with the same name?
- size_t size = parameters.size();
- for (size_t i = index + 1; i < size; ++i)
- if (parameters[i] == name)
- return CommonIdentifiers::shared()->nullIdentifier;
-
- return name;
-}
-
-// ECMA 13.2.2 [[Construct]]
-JSObject* FunctionImp::construct(ExecState* exec, const List& args)
-{
- JSObject* proto;
- JSValue* p = get(exec, exec->propertyNames().prototype);
- if (p->isObject())
- proto = static_cast<JSObject*>(p);
- else
- proto = exec->lexicalGlobalObject()->objectPrototype();
-
- JSObject* obj(new JSObject(proto));
-
- JSValue* res = call(exec,obj,args);
-
- if (res->isObject())
- return static_cast<JSObject*>(res);
- else
- return obj;
-}
-
-// ------------------------------ IndexToNameMap ---------------------------------
-
-// We map indexes in the arguments array to their corresponding argument names.
-// Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").
-
-// Once we have an argument name, we can get and set the argument's value in the
-// activation object.
-
-// We use Identifier::null to indicate that a given argument's value
-// isn't stored in the activation object.
-
-IndexToNameMap::IndexToNameMap(FunctionImp* func, const List& args)
-{
- _map = new Identifier[args.size()];
- this->size = args.size();
-
- unsigned i = 0;
- List::const_iterator end = args.end();
- for (List::const_iterator it = args.begin(); it != end; ++i, ++it)
- _map[i] = func->getParameterName(i); // null if there is no corresponding parameter
-}
-
-IndexToNameMap::~IndexToNameMap()
-{
- delete [] _map;
-}
-
-bool IndexToNameMap::isMapped(const Identifier& index) const
-{
- bool indexIsNumber;
- unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
-
- if (!indexIsNumber)
- return false;
-
- if (indexAsNumber >= size)
- return false;
-
- if (_map[indexAsNumber].isNull())
- return false;
-
- return true;
-}
-
-void IndexToNameMap::unMap(const Identifier& index)
-{
- bool indexIsNumber;
- unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
-
- ASSERT(indexIsNumber && indexAsNumber < size);
-
- _map[indexAsNumber] = CommonIdentifiers::shared()->nullIdentifier;
-}
-
-Identifier& IndexToNameMap::operator[](const Identifier& index)
-{
- bool indexIsNumber;
- unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);
-
- ASSERT(indexIsNumber && indexAsNumber < size);
-
- return _map[indexAsNumber];
-}
-
-// ------------------------------ Arguments ---------------------------------
-
-const ClassInfo Arguments::info = { "Arguments", 0, 0 };
-
-// ECMA 10.1.8
-Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, ActivationImp* act)
- : JSObject(exec->lexicalGlobalObject()->objectPrototype())
- , _activationObject(act)
- , indexToNameMap(func, args)
-{
- putDirect(exec->propertyNames().callee, func, DontEnum);
- putDirect(exec->propertyNames().length, args.size(), DontEnum);
-
- int i = 0;
- List::const_iterator end = args.end();
- for (List::const_iterator it = args.begin(); it != end; ++it, ++i) {
- Identifier name = Identifier::from(i);
- if (!indexToNameMap.isMapped(name))
- putDirect(name, *it, DontEnum);
- }
-}
-
-void Arguments::mark()
-{
- JSObject::mark();
- if (_activationObject && !_activationObject->marked())
- _activationObject->mark();
-}
-
-JSValue* Arguments::mappedIndexGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
-{
- Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());
- return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);
-}
-
-bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (indexToNameMap.isMapped(propertyName)) {
- slot.setCustom(this, mappedIndexGetter);
- return true;
- }
-
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
-{
- if (indexToNameMap.isMapped(propertyName)) {
- _activationObject->put(exec, indexToNameMap[propertyName], value, attr);
- } else {
- JSObject::put(exec, propertyName, value, attr);
- }
-}
-
-bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- if (indexToNameMap.isMapped(propertyName)) {
- indexToNameMap.unMap(propertyName);
- return true;
- } else {
- return JSObject::deleteProperty(exec, propertyName);
- }
-}
-
-// ------------------------------ ActivationImp --------------------------------
-
-const ClassInfo ActivationImp::info = { "Activation", 0, 0 };
-
-ActivationImp::ActivationImp(const ActivationData& oldData, bool leaveRelic)
-{
- JSVariableObject::d = new ActivationData(oldData);
- d()->leftRelic = leaveRelic;
-}
-
-ActivationImp::~ActivationImp()
-{
- if (!d()->isOnStack)
- delete d();
-}
-
-void ActivationImp::init(ExecState* exec)
-{
- d()->symbolTable = &exec->function()->body->symbolTable();
- d()->exec = exec;
- d()->function = exec->function();
- d()->argumentsObject = 0;
-}
-
-JSValue* ActivationImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- ActivationImp* thisObj = static_cast<ActivationImp*>(slot.slotBase());
-
- if (!thisObj->d()->argumentsObject)
- thisObj->createArgumentsObject(exec);
-
- return thisObj->d()->argumentsObject;
-}
-
-PropertySlot::GetValueFunc ActivationImp::getArgumentsGetter()
-{
- return ActivationImp::argumentsGetter;
-}
-
-bool ActivationImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (symbolTableGet(propertyName, slot))
- return true;
-
- if (JSValue** location = getDirectLocation(propertyName)) {
- slot.setValueSlot(this, location);
- return true;
- }
-
- // Only return the built-in arguments object if it wasn't overridden above.
- if (propertyName == exec->propertyNames().arguments) {
- for (ExecState* e = exec; e; e = e->callingExecState())
- if (e->function() == d()->function) {
- e->dynamicGlobalObject()->tearOffActivation(e, e != exec);
- ActivationImp* newActivation = e->activationObject();
- slot.setCustom(newActivation, newActivation->getArgumentsGetter());
- return true;
- }
-
- slot.setCustom(this, getArgumentsGetter());
- return true;
- }
-
- // We don't call through to JSObject because there's no way to give an
- // activation object getter properties or a prototype.
- ASSERT(!_prop.hasGetterSetterProperties());
- ASSERT(prototype() == jsNull());
- return false;
-}
-
-bool ActivationImp::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- if (propertyName == exec->propertyNames().arguments)
- return false;
-
- return JSVariableObject::deleteProperty(exec, propertyName);
-}
-
-void ActivationImp::put(ExecState*, const Identifier& propertyName, JSValue* value, int attr)
-{
- // If any bits other than DontDelete are set, then we bypass the read-only check.
- bool checkReadOnly = !(attr & ~DontDelete);
- if (symbolTablePut(propertyName, value, checkReadOnly))
- return;
-
- // We don't call through to JSObject because __proto__ and getter/setter
- // properties are non-standard extensions that other implementations do not
- // expose in the activation object.
- ASSERT(!_prop.hasGetterSetterProperties());
- _prop.put(propertyName, value, attr, checkReadOnly);
-}
-
-void ActivationImp::markChildren()
-{
- LocalStorage& localStorage = d()->localStorage;
- size_t size = localStorage.size();
-
- for (size_t i = 0; i < size; ++i) {
- JSValue* value = localStorage[i].value;
-
- if (!value->marked())
- value->mark();
- }
-
- if (!d()->function->marked())
- d()->function->mark();
-
- if (d()->argumentsObject && !d()->argumentsObject->marked())
- d()->argumentsObject->mark();
-}
-
-void ActivationImp::mark()
-{
- JSObject::mark();
- markChildren();
-}
-
-void ActivationImp::createArgumentsObject(ExecState* exec)
-{
- // Since "arguments" is only accessible while a function is being called,
- // we can retrieve our argument list from the ExecState for our function
- // call instead of storing the list ourselves.
- d()->argumentsObject = new Arguments(exec, d()->exec->function(), *d()->exec->arguments(), this);
-}
-
-ActivationImp::ActivationData::ActivationData(const ActivationData& old)
- : JSVariableObjectData(old)
- , exec(old.exec)
- , function(old.function)
- , argumentsObject(old.argumentsObject)
- , isOnStack(false)
-{
-}
-
-// ------------------------------ Global Functions -----------------------------------
-
-static JSValue* encode(ExecState* exec, const List& args, const char* do_not_escape)
-{
- UString r = "", s, str = args[0]->toString(exec);
- CString cstr = str.UTF8String(true);
- if (!cstr.c_str())
- return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
- const char* p = cstr.c_str();
- for (size_t k = 0; k < cstr.size(); k++, p++) {
- char c = *p;
- if (c && strchr(do_not_escape, c)) {
- r.append(c);
- } else {
- char tmp[4];
- snprintf(tmp, sizeof(tmp), "%%%02X", (unsigned char)c);
- r += tmp;
- }
- }
- return jsString(r);
-}
-
-static JSValue* decode(ExecState* exec, const List& args, const char* do_not_unescape, bool strict)
-{
- UString s = "", str = args[0]->toString(exec);
- int k = 0, len = str.size();
- const UChar* d = str.data();
- UChar u;
- while (k < len) {
- const UChar* p = d + k;
- UChar c = *p;
- if (c == '%') {
- int charLen = 0;
- if (k <= len - 3 && isASCIIHexDigit(p[1].uc) && isASCIIHexDigit(p[2].uc)) {
- const char b0 = Lexer::convertHex(p[1].uc, p[2].uc);
- const int sequenceLen = UTF8SequenceLength(b0);
- if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
- charLen = sequenceLen * 3;
- char sequence[5];
- sequence[0] = b0;
- for (int i = 1; i < sequenceLen; ++i) {
- const UChar* q = p + i * 3;
- if (q[0] == '%' && isASCIIHexDigit(q[1].uc) && isASCIIHexDigit(q[2].uc))
- sequence[i] = Lexer::convertHex(q[1].uc, q[2].uc);
- else {
- charLen = 0;
- break;
- }
- }
- if (charLen != 0) {
- sequence[sequenceLen] = 0;
- const int character = decodeUTF8Sequence(sequence);
- if (character < 0 || character >= 0x110000) {
- charLen = 0;
- } else if (character >= 0x10000) {
- // Convert to surrogate pair.
- s.append(static_cast<unsigned short>(0xD800 | ((character - 0x10000) >> 10)));
- u = static_cast<unsigned short>(0xDC00 | ((character - 0x10000) & 0x3FF));
- } else {
- u = static_cast<unsigned short>(character);
- }
- }
- }
- }
- if (charLen == 0) {
- if (strict)
- return throwError(exec, URIError);
- // The only case where we don't use "strict" mode is the "unescape" function.
- // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
- if (k <= len - 6 && p[1] == 'u'
- && isASCIIHexDigit(p[2].uc) && isASCIIHexDigit(p[3].uc)
- && isASCIIHexDigit(p[4].uc) && isASCIIHexDigit(p[5].uc)) {
- charLen = 6;
- u = Lexer::convertUnicode(p[2].uc, p[3].uc, p[4].uc, p[5].uc);
- }
- }
- if (charLen && (u.uc == 0 || u.uc >= 128 || !strchr(do_not_unescape, u.low()))) {
- c = u;
- k += charLen - 1;
- }
- }
- k++;
- s.append(c);
- }
- return jsString(s);
-}
-
-static bool isStrWhiteSpace(unsigned short c)
-{
- switch (c) {
- case 0x0009:
- case 0x000A:
- case 0x000B:
- case 0x000C:
- case 0x000D:
- case 0x0020:
- case 0x00A0:
- case 0x2028:
- case 0x2029:
- return true;
- default:
- return isSeparatorSpace(c);
- }
-}
-
-static int parseDigit(unsigned short c, int radix)
-{
- int digit = -1;
-
- if (c >= '0' && c <= '9') {
- digit = c - '0';
- } else if (c >= 'A' && c <= 'Z') {
- digit = c - 'A' + 10;
- } else if (c >= 'a' && c <= 'z') {
- digit = c - 'a' + 10;
- }
-
- if (digit >= radix)
- return -1;
- return digit;
-}
-
-double parseIntOverflow(const char* s, int length, int radix)
-{
- double number = 0.0;
- double radixMultiplier = 1.0;
-
- for (const char* p = s + length - 1; p >= s; p--) {
- if (radixMultiplier == Inf) {
- if (*p != '0') {
- number = Inf;
- break;
- }
- } else {
- int digit = parseDigit(*p, radix);
- number += digit * radixMultiplier;
- }
-
- radixMultiplier *= radix;
- }
-
- return number;
-}
-
-static double parseInt(const UString& s, int radix)
-{
- int length = s.size();
- int p = 0;
-
- while (p < length && isStrWhiteSpace(s[p].uc)) {
- ++p;
- }
-
- double sign = 1;
- if (p < length) {
- if (s[p] == '+') {
- ++p;
- } else if (s[p] == '-') {
- sign = -1;
- ++p;
- }
- }
-
- if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {
- radix = 16;
- p += 2;
- } else if (radix == 0) {
- if (p < length && s[p] == '0')
- radix = 8;
- else
- radix = 10;
- }
-
- if (radix < 2 || radix > 36)
- return NaN;
-
- int firstDigitPosition = p;
- bool sawDigit = false;
- double number = 0;
- while (p < length) {
- int digit = parseDigit(s[p].uc, radix);
- if (digit == -1)
- break;
- sawDigit = true;
- number *= radix;
- number += digit;
- ++p;
- }
-
- if (number >= mantissaOverflowLowerBound) {
- if (radix == 10)
- number = kjs_strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);
- else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
- number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);
- }
-
- if (!sawDigit)
- return NaN;
-
- return sign * number;
-}
-
-static double parseFloat(const UString& s)
-{
- // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
- // Need to skip any whitespace and then one + or - sign.
- int length = s.size();
- int p = 0;
- while (p < length && isStrWhiteSpace(s[p].uc)) {
- ++p;
- }
- if (p < length && (s[p] == '+' || s[p] == '-')) {
- ++p;
- }
- if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {
- return 0;
- }
-
- return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );
-}
-
-JSValue* globalFuncEval(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSValue* x = args[0];
- if (!x->isString())
- return x;
-
- UString s = x->toString(exec);
-
- int errLine;
- UString errMsg;
-
- SourceCode source = makeSource(s);
- RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(source, &errLine, &errMsg);
-
- // debugger code removed
-
- // No program node means a syntax occurred
- if (!evalNode)
- return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
-
- bool switchGlobal = thisObj && thisObj != exec->dynamicGlobalObject() && thisObj->isGlobalObject();
-
- // enter a new execution context
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- JSGlobalObject* globalObject = switchGlobal ? static_cast<JSGlobalObject*>(thisObj) : exec->dynamicGlobalObject();
- EvalExecState newExec(globalObject, evalNode.get(), exec);
-
- if (switchGlobal) {
- newExec.pushScope(thisObj);
- newExec.setVariableObject(static_cast<JSGlobalObject*>(thisObj));
- }
- JSValue* value = evalNode->execute(&newExec);
- if (switchGlobal)
- newExec.popScope();
-
- if (newExec.completionType() == Throw) {
- exec->setException(value);
- return value;
- }
-
- return value ? value : jsUndefined();
-}
-
-JSValue* globalFuncParseInt(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));
-}
-
-JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(parseFloat(args[0]->toString(exec)));
-}
-
-JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, const List& args)
-{
- return jsBoolean(isnan(args[0]->toNumber(exec)));
-}
-
-JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, const List& args)
-{
- double n = args[0]->toNumber(exec);
- return jsBoolean(!isnan(n) && !isinf(n));
-}
-
-JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, const List& args)
-{
- static const char do_not_unescape_when_decoding_URI[] =
- "#$&+,/:;=?@";
-
- return decode(exec, args, do_not_unescape_when_decoding_URI, true);
-}
-
-JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, const List& args)
-{
- return decode(exec, args, "", true);
-}
-
-JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, const List& args)
-{
- static const char do_not_escape_when_encoding_URI[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "!#$&'()*+,-./:;=?@_~";
-
- return encode(exec, args, do_not_escape_when_encoding_URI);
-}
-
-JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, const List& args)
-{
- static const char do_not_escape_when_encoding_URI_component[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "!'()*-._~";
-
- return encode(exec, args, do_not_escape_when_encoding_URI_component);
-}
-
-JSValue* globalFuncEscape(ExecState* exec, JSObject*, const List& args)
-{
- static const char do_not_escape[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "*+-./@_";
-
- UString r = "", s, str = args[0]->toString(exec);
- const UChar* c = str.data();
- for (int k = 0; k < str.size(); k++, c++) {
- int u = c->uc;
- if (u > 255) {
- char tmp[7];
- snprintf(tmp, sizeof(tmp), "%%u%04X", u);
- s = UString(tmp);
- } else if (u != 0 && strchr(do_not_escape, (char)u))
- s = UString(c, 1);
- else {
- char tmp[4];
- snprintf(tmp, sizeof(tmp), "%%%02X", u);
- s = UString(tmp);
- }
- r += s;
- }
-
- return jsString(r);
-}
-
-JSValue* globalFuncUnescape(ExecState* exec, JSObject*, const List& args)
-{
- UString s = "", str = args[0]->toString(exec);
- int k = 0, len = str.size();
- while (k < len) {
- const UChar* c = str.data() + k;
- UChar u;
- if (*c == UChar('%') && k <= len - 6 && *(c + 1) == UChar('u')) {
- if (Lexer::isHexDigit((c + 2)->uc) && Lexer::isHexDigit((c + 3)->uc) && Lexer::isHexDigit((c + 4)->uc) && Lexer::isHexDigit((c + 5)->uc)) {
- u = Lexer::convertUnicode((c + 2)->uc, (c + 3)->uc, (c + 4)->uc, (c + 5)->uc);
- c = &u;
- k += 5;
- }
- } else if (*c == UChar('%') && k <= len - 3 && Lexer::isHexDigit((c + 1)->uc) && Lexer::isHexDigit((c + 2)->uc)) {
- u = UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
- c = &u;
- k += 2;
- }
- k++;
- s += UString(c, 1);
- }
-
- return jsString(s);
-}
-
-#ifndef NDEBUG
-JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, const List& args)
-{
- puts(args[0]->toString(exec).ascii());
- return jsUndefined();
-}
-#endif
-
-// ------------------------------ PrototypeFunction -------------------------------
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, JSMemberFunction function)
- : InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), name)
- , m_function(function)
-{
- ASSERT_ARG(function, function);
- putDirect(exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
-}
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, JSMemberFunction function)
- : InternalFunctionImp(functionPrototype, name)
- , m_function(function)
-{
- ASSERT_ARG(function, function);
- putDirect(exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
-}
-
-JSValue* PrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
-{
- return m_function(exec, thisObj, args);
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_FUNCTION_H
-#define KJS_FUNCTION_H
-
-#include "JSVariableObject.h"
-#include "LocalStorage.h"
-#include "SymbolTable.h"
-#include "nodes.h"
-#include "object.h"
-
-namespace KJS {
-
- class ActivationImp;
- class FunctionBodyNode;
- class FunctionPrototype;
- class JSGlobalObject;
-
- class InternalFunctionImp : public JSObject {
- public:
- InternalFunctionImp();
- InternalFunctionImp(FunctionPrototype*, const Identifier&);
-
- virtual bool implementsCall() const;
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObjec, const List& args) = 0;
- virtual bool implementsHasInstance() const;
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- const Identifier& functionName() const { return m_name; }
-
- private:
- Identifier m_name;
- };
-
- class FunctionImp : public InternalFunctionImp {
- friend class ActivationImp;
- public:
- FunctionImp(ExecState*, const Identifier& name, FunctionBodyNode*, const ScopeChain&);
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, int attr = None);
- virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-
- virtual bool implementsConstruct() const { return true; }
- virtual JSObject* construct(ExecState*, const List& args);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
-
- // Note: unlike body->paramName, this returns Identifier::null for parameters
- // that will never get set, due to later param having the same name
- Identifier getParameterName(int index);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- RefPtr<FunctionBodyNode> body;
-
- void setScope(const ScopeChain& s) { _scope = s; }
- const ScopeChain& scope() const { return _scope; }
-
- virtual void mark();
-
- private:
- ScopeChain _scope;
-
- static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- static JSValue* callerGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- static JSValue* lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- };
-
- class IndexToNameMap {
- public:
- IndexToNameMap(FunctionImp*, const List& args);
- ~IndexToNameMap();
-
- Identifier& operator[](const Identifier& index);
- bool isMapped(const Identifier& index) const;
- void unMap(const Identifier& index);
-
- private:
- unsigned size;
- Identifier* _map;
- };
-
- class Arguments : public JSObject {
- public:
- Arguments(ExecState*, FunctionImp* func, const List& args, ActivationImp* act);
- virtual void mark();
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, int attr = None);
- virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- private:
- static JSValue* mappedIndexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
-
- ActivationImp* _activationObject;
- mutable IndexToNameMap indexToNameMap;
- };
-
- class PrototypeFunction : public InternalFunctionImp {
- public:
- typedef KJS::JSValue* (*JSMemberFunction)(ExecState*, JSObject*, const List&);
-
- PrototypeFunction(ExecState*, int len, const Identifier&, JSMemberFunction);
- PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, JSMemberFunction);
-
- virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List&);
-
- private:
- const JSMemberFunction m_function;
- };
-
-
- // Global Functions
- JSValue* globalFuncEval(ExecState*, JSObject*, const List&);
- JSValue* globalFuncParseInt(ExecState*, JSObject*, const List&);
- JSValue* globalFuncParseFloat(ExecState*, JSObject*, const List&);
- JSValue* globalFuncIsNaN(ExecState*, JSObject*, const List&);
- JSValue* globalFuncIsFinite(ExecState*, JSObject*, const List&);
- JSValue* globalFuncDecodeURI(ExecState*, JSObject*, const List&);
- JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, const List&);
- JSValue* globalFuncEncodeURI(ExecState*, JSObject*, const List&);
- JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, const List&);
- JSValue* globalFuncEscape(ExecState*, JSObject*, const List&);
- JSValue* globalFuncUnescape(ExecState*, JSObject*, const List&);
-#ifndef NDEBUG
- JSValue* globalFuncKJSPrint(ExecState*, JSObject*, const List&);
-#endif
-
- static const double mantissaOverflowLowerBound = 9007199254740992.0;
- double parseIntOverflow(const char*, int length, int radix);
-
-} // namespace
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "function_object.h"
-
-#include "JSGlobalObject.h"
-#include "Parser.h"
-#include "array_object.h"
-#include "debugger.h"
-#include "function.h"
-#include "internal.h"
-#include "lexer.h"
-#include "nodes.h"
-#include "object.h"
-#include <stdio.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-// ------------------------------ FunctionPrototype -------------------------
-
-static JSValue* functionProtoFuncToString(ExecState*, JSObject*, const List&);
-static JSValue* functionProtoFuncApply(ExecState*, JSObject*, const List&);
-static JSValue* functionProtoFuncCall(ExecState*, JSObject*, const List&);
-
-FunctionPrototype::FunctionPrototype(ExecState* exec)
-{
- static const Identifier* applyPropertyName = new Identifier("apply");
- static const Identifier* callPropertyName = new Identifier("call");
-
- putDirect(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
-
- putDirectFunction(new PrototypeFunction(exec, this, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, this, 2, *applyPropertyName, functionProtoFuncApply), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, this, 1, *callPropertyName, functionProtoFuncCall), DontEnum);
-}
-
-// ECMA 15.3.4
-JSValue* FunctionPrototype::callAsFunction(ExecState*, JSObject*, const List&)
-{
- return jsUndefined();
-}
-
-// Functions
-
-JSValue* functionProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj || !thisObj->inherits(&InternalFunctionImp::info)) {
-#ifndef NDEBUG
- fprintf(stderr,"attempted toString() call on null or non-function object\n");
-#endif
- return throwError(exec, TypeError);
- }
-
- if (thisObj->inherits(&FunctionImp::info)) {
- FunctionImp* fi = static_cast<FunctionImp*>(thisObj);
- return jsString("function " + fi->functionName().ustring() + "(" + fi->body->paramString() + ") " + fi->body->toString());
- }
-
- return jsString("function " + static_cast<InternalFunctionImp*>(thisObj)->functionName().ustring() + "() {\n [native code]\n}");
-}
-
-JSValue* functionProtoFuncApply(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->implementsCall())
- return throwError(exec, TypeError);
-
- JSValue* thisArg = args[0];
- JSValue* argArray = args[1];
-
- JSObject* applyThis;
- if (thisArg->isUndefinedOrNull())
- applyThis = exec->dynamicGlobalObject();
- else
- applyThis = thisArg->toObject(exec);
-
- List applyArgs;
- if (!argArray->isUndefinedOrNull()) {
- if (argArray->isObject() &&
- (static_cast<JSObject*>(argArray)->inherits(&ArrayInstance::info) ||
- static_cast<JSObject*>(argArray)->inherits(&Arguments::info))) {
-
- JSObject* argArrayObj = static_cast<JSObject*>(argArray);
- unsigned int length = argArrayObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned int i = 0; i < length; i++)
- applyArgs.append(argArrayObj->get(exec, i));
- } else
- return throwError(exec, TypeError);
- }
-
- return thisObj->call(exec, applyThis, applyArgs);
-}
-
-JSValue* functionProtoFuncCall(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->implementsCall())
- return throwError(exec, TypeError);
-
- JSValue* thisArg = args[0];
-
- JSObject* callThis;
- if (thisArg->isUndefinedOrNull())
- callThis = exec->dynamicGlobalObject();
- else
- callThis = thisArg->toObject(exec);
-
- List argsTail;
- args.getSlice(1, argsTail);
- return thisObj->call(exec, callThis, argsTail);
-}
-
-// ------------------------------ FunctionObjectImp ----------------------------
-
-FunctionObjectImp::FunctionObjectImp(ExecState* exec, FunctionPrototype* functionPrototype)
- : InternalFunctionImp(functionPrototype, functionPrototype->classInfo()->className)
-{
- putDirect(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
-
- // Number of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
-}
-
-bool FunctionObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.3.2 The Function Constructor
-JSObject* FunctionObjectImp::construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
-{
- UString p("");
- UString body;
- int argsSize = args.size();
- if (argsSize == 0)
- body = "";
- else if (argsSize == 1)
- body = args[0]->toString(exec);
- else {
- p = args[0]->toString(exec);
- for (int k = 1; k < argsSize - 1; k++)
- p += "," + args[k]->toString(exec);
- body = args[argsSize - 1]->toString(exec);
- }
-
- // parse the source code
- int errLine;
- UString errMsg;
- SourceCode source = makeSource(body, sourceURL, lineNumber);
- RefPtr<FunctionBodyNode> functionBody = parser().parse<FunctionBodyNode>(source, &errLine, &errMsg);
-
- // debugger code removed
-
- // No program node == syntax error - throw a syntax error
- if (!functionBody)
- // We can't return a Completion(Throw) here, so just set the exception
- // and return it
- return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
-
- ScopeChain scopeChain;
- scopeChain.push(exec->lexicalGlobalObject());
-
- FunctionImp* fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain);
-
- // parse parameter list. throw syntax error on illegal identifiers
- int len = p.size();
- const UChar* c = p.data();
- int i = 0, params = 0;
- UString param;
- while (i < len) {
- while (*c == ' ' && i < len)
- c++, i++;
- if (Lexer::isIdentStart(c->uc)) { // else error
- param = UString(c, 1);
- c++, i++;
- while (i < len && (Lexer::isIdentPart(c->uc))) {
- param += UString(c, 1);
- c++, i++;
- }
- while (i < len && *c == ' ')
- c++, i++;
- if (i == len) {
- functionBody->parameters().append(Identifier(param));
- params++;
- break;
- } else if (*c == ',') {
- functionBody->parameters().append(Identifier(param));
- params++;
- c++, i++;
- continue;
- } // else error
- }
- return throwError(exec, SyntaxError, "Syntax error in parameter list");
- }
-
- List consArgs;
-
- JSObject* objCons = exec->lexicalGlobalObject()->objectConstructor();
- JSObject* prototype = objCons->construct(exec, exec->emptyList());
- prototype->putDirect(exec->propertyNames().constructor, fimp, DontEnum | DontDelete | ReadOnly);
- fimp->putDirect(exec->propertyNames().prototype, prototype, Internal | DontDelete);
- return fimp;
-}
-
-// ECMA 15.3.2 The Function Constructor
-JSObject* FunctionObjectImp::construct(ExecState* exec, const List& args)
-{
- return construct(exec, args, "anonymous", UString(), 0);
-}
-
-// ECMA 15.3.1 The Function Constructor Called as a Function
-JSValue* FunctionObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- return construct(exec, args);
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef FUNCTION_OBJECT_H_
-#define FUNCTION_OBJECT_H_
-
-#include "object_object.h"
-#include "function.h"
-
-namespace KJS {
-
- /**
- * @internal
- *
- * The initial value of Function.prototype (and thus all objects created
- * with the Function constructor)
- */
- class FunctionPrototype : public InternalFunctionImp {
- public:
- FunctionPrototype(ExecState*);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Function" property
- */
- class FunctionObjectImp : public InternalFunctionImp {
- public:
- FunctionObjectImp(ExecState*, FunctionPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
- virtual JSObject* construct(ExecState*, const List&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
-
-} // namespace KJS
-
-#endif // _FUNCTION_OBJECT_H_
+++ /dev/null
-%{
-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "nodes.h"
-#include "lexer.h"
-#include "internal.h"
-#include "CommonIdentifiers.h"
-#include "NodeInfo.h"
-#include "Parser.h"
-#include <wtf/MathExtras.h>
-
-// Not sure why, but yacc doesn't add this define along with the others.
-#define yylloc kjsyylloc
-
-#define YYMAXDEPTH 10000
-#define YYENABLE_NLS 0
-
-/* default values for bison */
-#define YYDEBUG 0 // Set to 1 to debug a parse error.
-#define kjsyydebug 0 // Set to 1 to debug a parse error.
-#if !PLATFORM(DARWIN)
- // avoid triggering warnings in older bison
-#define YYERROR_VERBOSE
-#endif
-
-extern int kjsyylex();
-int kjsyyerror(const char *);
-static bool allowAutomaticSemicolon();
-
-#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon()) YYABORT; } while (0)
-#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
-
-using namespace KJS;
-using namespace std;
-
-static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*);
-static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*);
-static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr);
-static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator);
-static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator);
-static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
-static ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode*);
-static ExpressionNode* makeTypeOfNode(ExpressionNode*);
-static ExpressionNode* makeDeleteNode(ExpressionNode*);
-static ExpressionNode* makeNegateNode(ExpressionNode*);
-static NumberNode* makeNumberNode(double);
-static StatementNode* makeVarStatementNode(ExpressionNode*);
-static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init);
-
-
-#if COMPILER(MSVC)
-
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4702)
-
-// At least some of the time, the declarations of malloc and free that bison
-// generates are causing warnings. A way to avoid this is to explicitly define
-// the macros so that bison doesn't try to declare malloc and free.
-#define YYMALLOC malloc
-#define YYFREE free
-
-#endif
-
-template <typename T> NodeInfo<T> createNodeInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
- ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls)
-{
- NodeInfo<T> result = {node, varDecls, funcDecls};
- return result;
-}
-
-template <typename T> T mergeDeclarationLists(T decls1, T decls2)
-{
- // decls1 or both are null
- if (!decls1)
- return decls2;
- // only decls1 is non-null
- if (!decls2)
- return decls1;
-
- // Both are non-null
- decls1->data.append(decls2->data);
-
- // We manually release the declaration lists to avoid accumulating many many
- // unused heap allocated vectors
- decls2->ref();
- decls2->deref();
- return decls1;
-}
-
-static void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
-{
- if (!varDecls)
- varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>;
-
- varDecls->data.append(make_pair(ident, attrs));
-
-}
-
-static inline void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
-{
- unsigned attrs = DeclarationStacks::IsConstant;
- if (decl->m_init)
- attrs |= DeclarationStacks::HasInitializer;
- appendToVarDeclarationList(varDecls, decl->m_ident, attrs);
-}
-
-%}
-
-%union {
- int intValue;
- double doubleValue;
- UString* string;
- Identifier* ident;
-
- // expression subtrees
- ExpressionNode* expressionNode;
- FuncDeclNode* funcDeclNode;
- PropertyNode* propertyNode;
- ArgumentsNode* argumentsNode;
- ConstDeclNode* constDeclNode;
- CaseBlockNodeInfo caseBlockNode;
- CaseClauseNodeInfo caseClauseNode;
- FuncExprNode* funcExprNode;
-
- // statement nodes
- StatementNodeInfo statementNode;
- FunctionBodyNode* functionBodyNode;
- ProgramNode* programNode;
-
- SourceElementsInfo sourceElements;
- PropertyList propertyList;
- ArgumentList argumentList;
- VarDeclListInfo varDeclList;
- ConstDeclListInfo constDeclList;
- ClauseListInfo clauseList;
- ElementList elementList;
- ParameterList parameterList;
-
- Operator op;
-}
-
-%start Program
-
-/* literals */
-%token NULLTOKEN TRUETOKEN FALSETOKEN
-
-/* keywords */
-%token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE
-%token FUNCTION RETURN VOIDTOKEN DELETETOKEN
-%token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF
-%token SWITCH WITH RESERVED
-%token THROW TRY CATCH FINALLY
-%token DEBUGGER
-
-/* give an if without an else higher precedence than an else to resolve the ambiguity */
-%nonassoc IF_WITHOUT_ELSE
-%nonassoc ELSE
-
-/* punctuators */
-%token EQEQ NE /* == and != */
-%token STREQ STRNEQ /* === and !== */
-%token LE GE /* < and > */
-%token OR AND /* || and && */
-%token PLUSPLUS MINUSMINUS /* ++ and -- */
-%token LSHIFT /* << */
-%token RSHIFT URSHIFT /* >> and >>> */
-%token PLUSEQUAL MINUSEQUAL /* += and -= */
-%token MULTEQUAL DIVEQUAL /* *= and /= */
-%token LSHIFTEQUAL /* <<= */
-%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
-%token ANDEQUAL MODEQUAL /* &= and %= */
-%token XOREQUAL OREQUAL /* ^= and |= */
-%token <intValue> OPENBRACE /* { (with char offset) */
-%token <intValue> CLOSEBRACE /* { (with char offset) */
-
-/* terminal types */
-%token <doubleValue> NUMBER
-%token <string> STRING
-%token <ident> IDENT
-
-/* automatically inserted semicolon */
-%token AUTOPLUSPLUS AUTOMINUSMINUS
-
-/* non-terminal types */
-%type <expressionNode> Literal ArrayLiteral
-
-%type <expressionNode> PrimaryExpr PrimaryExprNoBrace
-%type <expressionNode> MemberExpr MemberExprNoBF /* BF => brace or function */
-%type <expressionNode> NewExpr NewExprNoBF
-%type <expressionNode> CallExpr CallExprNoBF
-%type <expressionNode> LeftHandSideExpr LeftHandSideExprNoBF
-%type <expressionNode> PostfixExpr PostfixExprNoBF
-%type <expressionNode> UnaryExpr UnaryExprNoBF UnaryExprCommon
-%type <expressionNode> MultiplicativeExpr MultiplicativeExprNoBF
-%type <expressionNode> AdditiveExpr AdditiveExprNoBF
-%type <expressionNode> ShiftExpr ShiftExprNoBF
-%type <expressionNode> RelationalExpr RelationalExprNoIn RelationalExprNoBF
-%type <expressionNode> EqualityExpr EqualityExprNoIn EqualityExprNoBF
-%type <expressionNode> BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
-%type <expressionNode> BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
-%type <expressionNode> BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
-%type <expressionNode> LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
-%type <expressionNode> LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
-%type <expressionNode> ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
-%type <expressionNode> AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
-%type <expressionNode> Expr ExprNoIn ExprNoBF
-
-%type <expressionNode> ExprOpt ExprNoInOpt
-
-%type <statementNode> Statement Block
-%type <statementNode> VariableStatement ConstStatement EmptyStatement ExprStatement
-%type <statementNode> IfStatement IterationStatement ContinueStatement
-%type <statementNode> BreakStatement ReturnStatement WithStatement
-%type <statementNode> SwitchStatement LabelledStatement
-%type <statementNode> ThrowStatement TryStatement
-%type <statementNode> DebuggerStatement
-%type <statementNode> SourceElement
-
-%type <expressionNode> Initializer InitializerNoIn
-%type <funcDeclNode> FunctionDeclaration
-%type <funcExprNode> FunctionExpr
-%type <functionBodyNode> FunctionBody
-%type <sourceElements> SourceElements
-%type <parameterList> FormalParameterList
-%type <op> AssignmentOperator
-%type <argumentsNode> Arguments
-%type <argumentList> ArgumentList
-%type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn
-%type <constDeclList> ConstDeclarationList
-%type <constDeclNode> ConstDeclaration
-%type <caseBlockNode> CaseBlock
-%type <caseClauseNode> CaseClause DefaultClause
-%type <clauseList> CaseClauses CaseClausesOpt
-%type <intValue> Elision ElisionOpt
-%type <elementList> ElementList
-%type <propertyNode> Property
-%type <propertyList> PropertyList
-%%
-
-Literal:
- NULLTOKEN { $$ = new NullNode; }
- | TRUETOKEN { $$ = new TrueNode; }
- | FALSETOKEN { $$ = new FalseNode; }
- | NUMBER { $$ = makeNumberNode($1); }
- | STRING { $$ = new StringNode($1); }
- | '/' /* regexp */ {
- Lexer& l = lexer();
- if (!l.scanRegExp())
- YYABORT;
- $$ = new RegExpNode(l.pattern(), l.flags());
- }
- | DIVEQUAL /* regexp with /= */ {
- Lexer& l = lexer();
- if (!l.scanRegExp())
- YYABORT;
- $$ = new RegExpNode("=" + l.pattern(), l.flags());
- }
-;
-
-Property:
- IDENT ':' AssignmentExpr { $$ = new PropertyNode(*$1, $3, PropertyNode::Constant); }
- | STRING ':' AssignmentExpr { $$ = new PropertyNode(Identifier(*$1), $3, PropertyNode::Constant); }
- | NUMBER ':' AssignmentExpr { $$ = new PropertyNode(Identifier(UString::from($1)), $3, PropertyNode::Constant); }
- | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, 0, $6, lexer().sourceCode($5, $7, @5.first_line)); DBG($6, @5, @7); if (!$$) YYABORT; }
- | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $7, lexer().sourceCode($6, $8, @6.first_line)); DBG($7, @6, @8); if (!$$) YYABORT; }
-;
-
-PropertyList:
- Property { $$.head = new PropertyListNode($1);
- $$.tail = $$.head; }
- | PropertyList ',' Property { $$.head = $1.head;
- $$.tail = new PropertyListNode($3, $1.tail); }
-;
-
-PrimaryExpr:
- PrimaryExprNoBrace
- | OPENBRACE CLOSEBRACE { $$ = new ObjectLiteralNode(); }
- | OPENBRACE PropertyList CLOSEBRACE { $$ = new ObjectLiteralNode($2.head); }
- /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
- | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = new ObjectLiteralNode($2.head); }
-;
-
-PrimaryExprNoBrace:
- THISTOKEN { $$ = new ThisNode(); }
- | Literal
- | ArrayLiteral
- | IDENT { $$ = new ResolveNode(*$1); }
- | '(' Expr ')' { $$ = $2; }
-;
-
-ArrayLiteral:
- '[' ElisionOpt ']' { $$ = new ArrayNode($2); }
- | '[' ElementList ']' { $$ = new ArrayNode($2.head); }
- | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2.head); }
-;
-
-ElementList:
- ElisionOpt AssignmentExpr { $$.head = new ElementNode($1, $2);
- $$.tail = $$.head; }
- | ElementList ',' ElisionOpt AssignmentExpr
- { $$.head = $1.head;
- $$.tail = new ElementNode($1.tail, $3, $4); }
-;
-
-ElisionOpt:
- /* nothing */ { $$ = 0; }
- | Elision
-;
-
-Elision:
- ',' { $$ = 1; }
- | Elision ',' { $$ = $1 + 1; }
-;
-
-MemberExpr:
- PrimaryExpr
- | FunctionExpr { $$ = $1; }
- | MemberExpr '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); }
- | MemberExpr '.' IDENT { $$ = new DotAccessorNode($1, *$3); }
- | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
-;
-
-MemberExprNoBF:
- PrimaryExprNoBrace
- | MemberExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); }
- | MemberExprNoBF '.' IDENT { $$ = new DotAccessorNode($1, *$3); }
- | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
-;
-
-NewExpr:
- MemberExpr
- | NEW NewExpr { $$ = new NewExprNode($2); }
-;
-
-NewExprNoBF:
- MemberExprNoBF
- | NEW NewExpr { $$ = new NewExprNode($2); }
-;
-
-CallExpr:
- MemberExpr Arguments { $$ = makeFunctionCallNode($1, $2); }
- | CallExpr Arguments { $$ = makeFunctionCallNode($1, $2); }
- | CallExpr '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); }
- | CallExpr '.' IDENT { $$ = new DotAccessorNode($1, *$3); }
-;
-
-CallExprNoBF:
- MemberExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); }
- | CallExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); }
- | CallExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); }
- | CallExprNoBF '.' IDENT { $$ = new DotAccessorNode($1, *$3); }
-;
-
-Arguments:
- '(' ')' { $$ = new ArgumentsNode(); }
- | '(' ArgumentList ')' { $$ = new ArgumentsNode($2.head); }
-;
-
-ArgumentList:
- AssignmentExpr { $$.head = new ArgumentListNode($1);
- $$.tail = $$.head; }
- | ArgumentList ',' AssignmentExpr { $$.head = $1.head;
- $$.tail = new ArgumentListNode($1.tail, $3); }
-;
-
-LeftHandSideExpr:
- NewExpr
- | CallExpr
-;
-
-LeftHandSideExprNoBF:
- NewExprNoBF
- | CallExprNoBF
-;
-
-PostfixExpr:
- LeftHandSideExpr
- | LeftHandSideExpr PLUSPLUS { $$ = makePostfixNode($1, OpPlusPlus); }
- | LeftHandSideExpr MINUSMINUS { $$ = makePostfixNode($1, OpMinusMinus); }
-;
-
-PostfixExprNoBF:
- LeftHandSideExprNoBF
- | LeftHandSideExprNoBF PLUSPLUS { $$ = makePostfixNode($1, OpPlusPlus); }
- | LeftHandSideExprNoBF MINUSMINUS { $$ = makePostfixNode($1, OpMinusMinus); }
-;
-
-UnaryExprCommon:
- DELETETOKEN UnaryExpr { $$ = makeDeleteNode($2); }
- | VOIDTOKEN UnaryExpr { $$ = new VoidNode($2); }
- | TYPEOF UnaryExpr { $$ = makeTypeOfNode($2); }
- | PLUSPLUS UnaryExpr { $$ = makePrefixNode($2, OpPlusPlus); }
- | AUTOPLUSPLUS UnaryExpr { $$ = makePrefixNode($2, OpPlusPlus); }
- | MINUSMINUS UnaryExpr { $$ = makePrefixNode($2, OpMinusMinus); }
- | AUTOMINUSMINUS UnaryExpr { $$ = makePrefixNode($2, OpMinusMinus); }
- | '+' UnaryExpr { $$ = new UnaryPlusNode($2); }
- | '-' UnaryExpr { $$ = makeNegateNode($2); }
- | '~' UnaryExpr { $$ = new BitwiseNotNode($2); }
- | '!' UnaryExpr { $$ = new LogicalNotNode($2); }
-
-UnaryExpr:
- PostfixExpr
- | UnaryExprCommon
-;
-
-UnaryExprNoBF:
- PostfixExprNoBF
- | UnaryExprCommon
-;
-
-MultiplicativeExpr:
- UnaryExpr
- | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3); }
- | MultiplicativeExpr '/' UnaryExpr { $$ = new DivNode($1, $3); }
- | MultiplicativeExpr '%' UnaryExpr { $$ = new ModNode($1, $3); }
-;
-
-MultiplicativeExprNoBF:
- UnaryExprNoBF
- | MultiplicativeExprNoBF '*' UnaryExpr
- { $$ = new MultNode($1, $3); }
- | MultiplicativeExprNoBF '/' UnaryExpr
- { $$ = new DivNode($1, $3); }
- | MultiplicativeExprNoBF '%' UnaryExpr
- { $$ = new ModNode($1, $3); }
-;
-
-AdditiveExpr:
- MultiplicativeExpr
- | AdditiveExpr '+' MultiplicativeExpr { $$ = makeAddNode($1, $3); }
- | AdditiveExpr '-' MultiplicativeExpr { $$ = new SubNode($1, $3); }
-;
-
-AdditiveExprNoBF:
- MultiplicativeExprNoBF
- | AdditiveExprNoBF '+' MultiplicativeExpr
- { $$ = makeAddNode($1, $3); }
- | AdditiveExprNoBF '-' MultiplicativeExpr
- { $$ = new SubNode($1, $3); }
-;
-
-ShiftExpr:
- AdditiveExpr
- | ShiftExpr LSHIFT AdditiveExpr { $$ = new LeftShiftNode($1, $3); }
- | ShiftExpr RSHIFT AdditiveExpr { $$ = new RightShiftNode($1, $3); }
- | ShiftExpr URSHIFT AdditiveExpr { $$ = new UnsignedRightShiftNode($1, $3); }
-;
-
-ShiftExprNoBF:
- AdditiveExprNoBF
- | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = new LeftShiftNode($1, $3); }
- | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = new RightShiftNode($1, $3); }
- | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = new UnsignedRightShiftNode($1, $3); }
-;
-
-RelationalExpr:
- ShiftExpr
- | RelationalExpr '<' ShiftExpr { $$ = makeLessNode($1, $3); }
- | RelationalExpr '>' ShiftExpr { $$ = new GreaterNode($1, $3); }
- | RelationalExpr LE ShiftExpr { $$ = new LessEqNode($1, $3); }
- | RelationalExpr GE ShiftExpr { $$ = new GreaterEqNode($1, $3); }
- | RelationalExpr INSTANCEOF ShiftExpr { $$ = new InstanceOfNode($1, $3); }
- | RelationalExpr INTOKEN ShiftExpr { $$ = new InNode($1, $3); }
-;
-
-RelationalExprNoIn:
- ShiftExpr
- | RelationalExprNoIn '<' ShiftExpr { $$ = makeLessNode($1, $3); }
- | RelationalExprNoIn '>' ShiftExpr { $$ = new GreaterNode($1, $3); }
- | RelationalExprNoIn LE ShiftExpr { $$ = new LessEqNode($1, $3); }
- | RelationalExprNoIn GE ShiftExpr { $$ = new GreaterEqNode($1, $3); }
- | RelationalExprNoIn INSTANCEOF ShiftExpr
- { $$ = new InstanceOfNode($1, $3); }
-;
-
-RelationalExprNoBF:
- ShiftExprNoBF
- | RelationalExprNoBF '<' ShiftExpr { $$ = makeLessNode($1, $3); }
- | RelationalExprNoBF '>' ShiftExpr { $$ = new GreaterNode($1, $3); }
- | RelationalExprNoBF LE ShiftExpr { $$ = new LessEqNode($1, $3); }
- | RelationalExprNoBF GE ShiftExpr { $$ = new GreaterEqNode($1, $3); }
- | RelationalExprNoBF INSTANCEOF ShiftExpr
- { $$ = new InstanceOfNode($1, $3); }
- | RelationalExprNoBF INTOKEN ShiftExpr { $$ = new InNode($1, $3); }
-;
-
-EqualityExpr:
- RelationalExpr
- | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, $3); }
- | EqualityExpr NE RelationalExpr { $$ = new NotEqualNode($1, $3); }
- | EqualityExpr STREQ RelationalExpr { $$ = new StrictEqualNode($1, $3); }
- | EqualityExpr STRNEQ RelationalExpr { $$ = new NotStrictEqualNode($1, $3); }
-;
-
-EqualityExprNoIn:
- RelationalExprNoIn
- | EqualityExprNoIn EQEQ RelationalExprNoIn
- { $$ = new EqualNode($1, $3); }
- | EqualityExprNoIn NE RelationalExprNoIn
- { $$ = new NotEqualNode($1, $3); }
- | EqualityExprNoIn STREQ RelationalExprNoIn
- { $$ = new StrictEqualNode($1, $3); }
- | EqualityExprNoIn STRNEQ RelationalExprNoIn
- { $$ = new NotStrictEqualNode($1, $3); }
-;
-
-EqualityExprNoBF:
- RelationalExprNoBF
- | EqualityExprNoBF EQEQ RelationalExpr
- { $$ = new EqualNode($1, $3); }
- | EqualityExprNoBF NE RelationalExpr { $$ = new NotEqualNode($1, $3); }
- | EqualityExprNoBF STREQ RelationalExpr
- { $$ = new StrictEqualNode($1, $3); }
- | EqualityExprNoBF STRNEQ RelationalExpr
- { $$ = new NotStrictEqualNode($1, $3); }
-;
-
-BitwiseANDExpr:
- EqualityExpr
- | BitwiseANDExpr '&' EqualityExpr { $$ = new BitAndNode($1, $3); }
-;
-
-BitwiseANDExprNoIn:
- EqualityExprNoIn
- | BitwiseANDExprNoIn '&' EqualityExprNoIn
- { $$ = new BitAndNode($1, $3); }
-;
-
-BitwiseANDExprNoBF:
- EqualityExprNoBF
- | BitwiseANDExprNoBF '&' EqualityExpr { $$ = new BitAndNode($1, $3); }
-;
-
-BitwiseXORExpr:
- BitwiseANDExpr
- | BitwiseXORExpr '^' BitwiseANDExpr { $$ = new BitXOrNode($1, $3); }
-;
-
-BitwiseXORExprNoIn:
- BitwiseANDExprNoIn
- | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
- { $$ = new BitXOrNode($1, $3); }
-;
-
-BitwiseXORExprNoBF:
- BitwiseANDExprNoBF
- | BitwiseXORExprNoBF '^' BitwiseANDExpr
- { $$ = new BitXOrNode($1, $3); }
-;
-
-BitwiseORExpr:
- BitwiseXORExpr
- | BitwiseORExpr '|' BitwiseXORExpr { $$ = new BitOrNode($1, $3); }
-;
-
-BitwiseORExprNoIn:
- BitwiseXORExprNoIn
- | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
- { $$ = new BitOrNode($1, $3); }
-;
-
-BitwiseORExprNoBF:
- BitwiseXORExprNoBF
- | BitwiseORExprNoBF '|' BitwiseXORExpr
- { $$ = new BitOrNode($1, $3); }
-;
-
-LogicalANDExpr:
- BitwiseORExpr
- | LogicalANDExpr AND BitwiseORExpr { $$ = new LogicalAndNode($1, $3); }
-;
-
-LogicalANDExprNoIn:
- BitwiseORExprNoIn
- | LogicalANDExprNoIn AND BitwiseORExprNoIn
- { $$ = new LogicalAndNode($1, $3); }
-;
-
-LogicalANDExprNoBF:
- BitwiseORExprNoBF
- | LogicalANDExprNoBF AND BitwiseORExpr
- { $$ = new LogicalAndNode($1, $3); }
-;
-
-LogicalORExpr:
- LogicalANDExpr
- | LogicalORExpr OR LogicalANDExpr { $$ = new LogicalOrNode($1, $3); }
-;
-
-LogicalORExprNoIn:
- LogicalANDExprNoIn
- | LogicalORExprNoIn OR LogicalANDExprNoIn
- { $$ = new LogicalOrNode($1, $3); }
-;
-
-LogicalORExprNoBF:
- LogicalANDExprNoBF
- | LogicalORExprNoBF OR LogicalANDExpr { $$ = new LogicalOrNode($1, $3); }
-;
-
-ConditionalExpr:
- LogicalORExpr
- | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
- { $$ = new ConditionalNode($1, $3, $5); }
-;
-
-ConditionalExprNoIn:
- LogicalORExprNoIn
- | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn
- { $$ = new ConditionalNode($1, $3, $5); }
-;
-
-ConditionalExprNoBF:
- LogicalORExprNoBF
- | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr
- { $$ = new ConditionalNode($1, $3, $5); }
-;
-
-AssignmentExpr:
- ConditionalExpr
- | LeftHandSideExpr AssignmentOperator AssignmentExpr
- { $$ = makeAssignNode($1, $2, $3); }
-;
-
-AssignmentExprNoIn:
- ConditionalExprNoIn
- | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
- { $$ = makeAssignNode($1, $2, $3); }
-;
-
-AssignmentExprNoBF:
- ConditionalExprNoBF
- | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
- { $$ = makeAssignNode($1, $2, $3); }
-;
-
-AssignmentOperator:
- '=' { $$ = OpEqual; }
- | PLUSEQUAL { $$ = OpPlusEq; }
- | MINUSEQUAL { $$ = OpMinusEq; }
- | MULTEQUAL { $$ = OpMultEq; }
- | DIVEQUAL { $$ = OpDivEq; }
- | LSHIFTEQUAL { $$ = OpLShift; }
- | RSHIFTEQUAL { $$ = OpRShift; }
- | URSHIFTEQUAL { $$ = OpURShift; }
- | ANDEQUAL { $$ = OpAndEq; }
- | XOREQUAL { $$ = OpXOrEq; }
- | OREQUAL { $$ = OpOrEq; }
- | MODEQUAL { $$ = OpModEq; }
-;
-
-Expr:
- AssignmentExpr
- | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
-;
-
-ExprNoIn:
- AssignmentExprNoIn
- | ExprNoIn ',' AssignmentExprNoIn { $$ = new CommaNode($1, $3); }
-;
-
-ExprNoBF:
- AssignmentExprNoBF
- | ExprNoBF ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
-;
-
-Statement:
- Block
- | VariableStatement
- | ConstStatement
- | EmptyStatement
- | ExprStatement
- | IfStatement
- | IterationStatement
- | ContinueStatement
- | BreakStatement
- | ReturnStatement
- | WithStatement
- | SwitchStatement
- | LabelledStatement
- | ThrowStatement
- | TryStatement
- | DebuggerStatement
-;
-
-Block:
- OPENBRACE CLOSEBRACE { $$ = createNodeInfo<StatementNode*>(new BlockNode(0), 0, 0);
- DBG($$.m_node, @1, @2); }
- | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeInfo<StatementNode*>(new BlockNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @3); }
-;
-
-VariableStatement:
- VAR VariableDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @3); }
- | VAR VariableDeclarationList error { $$ = createNodeInfo<StatementNode*>(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @2);
- AUTO_SEMICOLON; }
-;
-
-VariableDeclarationList:
- IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
- appendToVarDeclarationList($$.m_varDeclarations, *$1, 0);
- $$.m_funcDeclarations = 0;
- }
- | IDENT Initializer { $$.m_node = new AssignResolveNode(*$1, $2);
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
- appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- }
- | VariableDeclarationList ',' IDENT
- { $$.m_node = $1.m_node;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList($$.m_varDeclarations, *$3, 0);
- $$.m_funcDeclarations = 0;
- }
- | VariableDeclarationList ',' IDENT Initializer
- { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4));
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- }
-;
-
-VariableDeclarationListNoIn:
- IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
- appendToVarDeclarationList($$.m_varDeclarations, *$1, 0);
- $$.m_funcDeclarations = 0;
- }
- | IDENT InitializerNoIn { $$.m_node = new AssignResolveNode(*$1, $2);
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
- appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- }
- | VariableDeclarationListNoIn ',' IDENT
- { $$.m_node = $1.m_node;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList($$.m_varDeclarations, *$3, 0);
- $$.m_funcDeclarations = 0;
- }
- | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
- { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4));
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
- $$.m_funcDeclarations = 0;
- }
-;
-
-ConstStatement:
- CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @3); }
- | CONSTTOKEN ConstDeclarationList error
- { $$ = createNodeInfo<StatementNode*>(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ConstDeclarationList:
- ConstDeclaration { $$.m_node.head = $1;
- $$.m_node.tail = $$.m_node.head;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
- appendToVarDeclarationList($$.m_varDeclarations, $1);
- $$.m_funcDeclarations = 0; }
- | ConstDeclarationList ',' ConstDeclaration
- { $$.m_node.head = $1.m_node.head;
- $1.m_node.tail->m_next = $3;
- $$.m_node.tail = $3;
- $$.m_varDeclarations = $1.m_varDeclarations;
- appendToVarDeclarationList($$.m_varDeclarations, $3);
- $$.m_funcDeclarations = 0; }
-;
-
-ConstDeclaration:
- IDENT { $$ = new ConstDeclNode(*$1, 0); }
- | IDENT Initializer { $$ = new ConstDeclNode(*$1, $2); }
-;
-
-Initializer:
- '=' AssignmentExpr { $$ = $2; }
-;
-
-InitializerNoIn:
- '=' AssignmentExprNoIn { $$ = $2; }
-;
-
-EmptyStatement:
- ';' { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0); }
-;
-
-ExprStatement:
- ExprNoBF ';' { $$ = createNodeInfo<StatementNode*>(new ExprStatementNode($1), 0, 0);
- DBG($$.m_node, @1, @2); }
- | ExprNoBF error { $$ = createNodeInfo<StatementNode*>(new ExprStatementNode($1), 0, 0);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-IfStatement:
- IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
- { $$ = createNodeInfo<StatementNode*>(new IfNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
- DBG($$.m_node, @1, @4); }
- | IF '(' Expr ')' Statement ELSE Statement
- { $$ = createNodeInfo<StatementNode*>(new IfElseNode($3, $5.m_node, $7.m_node), mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations));
- DBG($$.m_node, @1, @4); }
-;
-
-IterationStatement:
- DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeInfo<StatementNode*>(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @3); }
- | DO Statement WHILE '(' Expr ')' error { $$ = createNodeInfo<StatementNode*>(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations);
- DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
- | WHILE '(' Expr ')' Statement { $$ = createNodeInfo<StatementNode*>(new WhileNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
- DBG($$.m_node, @1, @4); }
- | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
- { $$ = createNodeInfo<StatementNode*>(new ForNode($3, $5, $7, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations);
- DBG($$.m_node, @1, @8);
- }
- | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
- { $$ = createNodeInfo<StatementNode*>(new ForNode($4.m_node, $6, $8, $10.m_node, true),
- mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
- mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations));
- DBG($$.m_node, @1, @9); }
- | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
- {
- ExpressionNode* n = $3;
- if (!n->isLocation())
- YYABORT;
- $$ = createNodeInfo<StatementNode*>(new ForInNode(n, $5, $7.m_node), $7.m_varDeclarations, $7.m_funcDeclarations);
- DBG($$.m_node, @1, @6);
- }
- | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
- { ForInNode *forIn = new ForInNode(*$4, 0, $6, $8.m_node);
- appendToVarDeclarationList($8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
- $$ = createNodeInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations);
- DBG($$.m_node, @1, @7); }
- | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
- { ForInNode *forIn = new ForInNode(*$4, $5, $7, $9.m_node);
- appendToVarDeclarationList($9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
- $$ = createNodeInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations);
- DBG($$.m_node, @1, @8); }
-;
-
-ExprOpt:
- /* nothing */ { $$ = 0; }
- | Expr
-;
-
-ExprNoInOpt:
- /* nothing */ { $$ = 0; }
- | ExprNoIn
-;
-
-ContinueStatement:
- CONTINUE ';' { $$ = createNodeInfo<StatementNode*>(new ContinueNode(), 0, 0);
- DBG($$.m_node, @1, @2); }
- | CONTINUE error { $$ = createNodeInfo<StatementNode*>(new ContinueNode(), 0, 0);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | CONTINUE IDENT ';' { $$ = createNodeInfo<StatementNode*>(new ContinueNode(*$2), 0, 0);
- DBG($$.m_node, @1, @3); }
- | CONTINUE IDENT error { $$ = createNodeInfo<StatementNode*>(new ContinueNode(*$2), 0, 0);
- DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-BreakStatement:
- BREAK ';' { $$ = createNodeInfo<StatementNode*>(new BreakNode(), 0, 0); DBG($$.m_node, @1, @2); }
- | BREAK error { $$ = createNodeInfo<StatementNode*>(new BreakNode(), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | BREAK IDENT ';' { $$ = createNodeInfo<StatementNode*>(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @3); }
- | BREAK IDENT error { $$ = createNodeInfo<StatementNode*>(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ReturnStatement:
- RETURN ';' { $$ = createNodeInfo<StatementNode*>(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @2); }
- | RETURN error { $$ = createNodeInfo<StatementNode*>(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
- | RETURN Expr ';' { $$ = createNodeInfo<StatementNode*>(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @3); }
- | RETURN Expr error { $$ = createNodeInfo<StatementNode*>(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-WithStatement:
- WITH '(' Expr ')' Statement { $$ = createNodeInfo<StatementNode*>(new WithNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
- DBG($$.m_node, @1, @4); }
-;
-
-SwitchStatement:
- SWITCH '(' Expr ')' CaseBlock { $$ = createNodeInfo<StatementNode*>(new SwitchNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations);
- DBG($$.m_node, @1, @4); }
-;
-
-CaseBlock:
- OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations); }
- | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
- { $$ = createNodeInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, $3.m_node, $4.m_node.head),
- mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
- mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations)); }
-;
-
-CaseClausesOpt:
- /* nothing */ { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; }
- | CaseClauses
-;
-
-CaseClauses:
- CaseClause { $$.m_node.head = new ClauseListNode($1.m_node);
- $$.m_node.tail = $$.m_node.head;
- $$.m_varDeclarations = $1.m_varDeclarations;
- $$.m_funcDeclarations = $1.m_funcDeclarations; }
- | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head;
- $$.m_node.tail = new ClauseListNode($1.m_node.tail, $2.m_node);
- $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
- $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
- }
-;
-
-CaseClause:
- CASE Expr ':' { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode($2), 0, 0); }
- | CASE Expr ':' SourceElements { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode($2, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations); }
-;
-
-DefaultClause:
- DEFAULT ':' { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode(0), 0, 0); }
- | DEFAULT ':' SourceElements { $$ = createNodeInfo<CaseClauseNode*>(new CaseClauseNode(0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations); }
-;
-
-LabelledStatement:
- IDENT ':' Statement { $3.m_node->pushLabel(*$1);
- $$ = createNodeInfo<StatementNode*>(new LabelNode(*$1, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations); }
-;
-
-ThrowStatement:
- THROW Expr ';' { $$ = createNodeInfo<StatementNode*>(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @3); }
- | THROW Expr error { $$ = createNodeInfo<StatementNode*>(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-TryStatement:
- TRY Block FINALLY Block { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, CommonIdentifiers::shared()->nullIdentifier, 0, $4.m_node),
- mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
- mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations));
- DBG($$.m_node, @1, @2); }
- | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, *$5, $7.m_node, 0),
- mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
- mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations));
- DBG($$.m_node, @1, @2); }
- | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
- { $$ = createNodeInfo<StatementNode*>(new TryNode($2.m_node, *$5, $7.m_node, $9.m_node),
- mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
- mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations));
- DBG($$.m_node, @1, @2); }
-;
-
-DebuggerStatement:
- DEBUGGER ';' { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0);
- DBG($$.m_node, @1, @2); }
- | DEBUGGER error { $$ = createNodeInfo<StatementNode*>(new EmptyStatementNode(), 0, 0);
- DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-FunctionDeclaration:
- FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncDeclNode(*$2, $6, lexer().sourceCode($5, $7, @5.first_line)); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
- { $$ = new FuncDeclNode(*$2, $7, lexer().sourceCode($6, $8, @6.first_line), $4.head); DBG($7, @6, @8); }
-;
-
-FunctionExpr:
- FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5, lexer().sourceCode($4, $6, @4.first_line)); DBG($5, @4, @6); }
- | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, lexer().sourceCode($5, $7, @5.first_line), $3.head); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncExprNode(*$2, $6, lexer().sourceCode($5, $7, @5.first_line)); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncExprNode(*$2, $7, lexer().sourceCode($6, $8, @6.first_line), $4.head); DBG($7, @6, @8); }
-;
-
-FormalParameterList:
- IDENT { $$.head = new ParameterNode(*$1);
- $$.tail = $$.head; }
- | FormalParameterList ',' IDENT { $$.head = $1.head;
- $$.tail = new ParameterNode($1.tail, *$3); }
-;
-
-FunctionBody:
- /* not in spec */ { $$ = FunctionBodyNode::create(); }
- | SourceElements_NoNode { $$ = FunctionBodyNode::create(); }
-;
-
-Program:
- /* not in spec */ { parser().didFinishParsing(0, 0, 0, @0.last_line); }
- | SourceElements { parser().didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, @1.last_line); }
-;
-
-SourceElements:
- SourceElement { $$.m_node = new SourceElements;
- $$.m_node->append($1.m_node);
- $$.m_varDeclarations = $1.m_varDeclarations;
- $$.m_funcDeclarations = $1.m_funcDeclarations;
- }
- | SourceElements SourceElement { $$.m_node->append($2.m_node);
- $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
- $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
- }
-;
-
-SourceElement:
- FunctionDeclaration { $$ = createNodeInfo<StatementNode*>($1, 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>); $$.m_funcDeclarations->data.append($1); }
- | Statement { $$ = $1; }
-;
-
-// Start NoNodes
-
-Literal_NoNode:
- NULLTOKEN
- | TRUETOKEN
- | FALSETOKEN
- | NUMBER { }
- | STRING { }
- | '/' /* regexp */ { Lexer& l = lexer(); if (!l.scanRegExp()) YYABORT; }
- | DIVEQUAL /* regexp with /= */ { Lexer& l = lexer(); if (!l.scanRegExp()) YYABORT; }
-;
-
-Property_NoNode:
- IDENT ':' AssignmentExpr_NoNode { }
- | STRING ':' AssignmentExpr_NoNode { }
- | NUMBER ':' AssignmentExpr_NoNode { }
- | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
- | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
-;
-
-PropertyList_NoNode:
- Property_NoNode
- | PropertyList_NoNode ',' Property_NoNode
-;
-
-PrimaryExpr_NoNode:
- PrimaryExprNoBrace_NoNode
- | OPENBRACE CLOSEBRACE { }
- | OPENBRACE PropertyList_NoNode CLOSEBRACE { }
- /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
- | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE { }
-;
-
-PrimaryExprNoBrace_NoNode:
- THISTOKEN
- | Literal_NoNode
- | ArrayLiteral_NoNode
- | IDENT { }
- | '(' Expr_NoNode ')'
-;
-
-ArrayLiteral_NoNode:
- '[' ElisionOpt_NoNode ']'
- | '[' ElementList_NoNode ']'
- | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']'
-;
-
-ElementList_NoNode:
- ElisionOpt_NoNode AssignmentExpr_NoNode
- | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode
-;
-
-ElisionOpt_NoNode:
- /* nothing */
- | Elision_NoNode
-;
-
-Elision_NoNode:
- ','
- | Elision_NoNode ','
-;
-
-MemberExpr_NoNode:
- PrimaryExpr_NoNode
- | FunctionExpr_NoNode
- | MemberExpr_NoNode '[' Expr_NoNode ']'
- | MemberExpr_NoNode '.' IDENT
- | NEW MemberExpr_NoNode Arguments_NoNode
-;
-
-MemberExprNoBF_NoNode:
- PrimaryExprNoBrace_NoNode
- | MemberExprNoBF_NoNode '[' Expr_NoNode ']'
- | MemberExprNoBF_NoNode '.' IDENT
- | NEW MemberExpr_NoNode Arguments_NoNode
-;
-
-NewExpr_NoNode:
- MemberExpr_NoNode
- | NEW NewExpr_NoNode
-;
-
-NewExprNoBF_NoNode:
- MemberExprNoBF_NoNode
- | NEW NewExpr_NoNode
-;
-
-CallExpr_NoNode:
- MemberExpr_NoNode Arguments_NoNode
- | CallExpr_NoNode Arguments_NoNode
- | CallExpr_NoNode '[' Expr_NoNode ']'
- | CallExpr_NoNode '.' IDENT
-;
-
-CallExprNoBF_NoNode:
- MemberExprNoBF_NoNode Arguments_NoNode
- | CallExprNoBF_NoNode Arguments_NoNode
- | CallExprNoBF_NoNode '[' Expr_NoNode ']'
- | CallExprNoBF_NoNode '.' IDENT
-;
-
-Arguments_NoNode:
- '(' ')'
- | '(' ArgumentList_NoNode ')'
-;
-
-ArgumentList_NoNode:
- AssignmentExpr_NoNode
- | ArgumentList_NoNode ',' AssignmentExpr_NoNode
-;
-
-LeftHandSideExpr_NoNode:
- NewExpr_NoNode
- | CallExpr_NoNode
-;
-
-LeftHandSideExprNoBF_NoNode:
- NewExprNoBF_NoNode
- | CallExprNoBF_NoNode
-;
-
-PostfixExpr_NoNode:
- LeftHandSideExpr_NoNode
- | LeftHandSideExpr_NoNode PLUSPLUS
- | LeftHandSideExpr_NoNode MINUSMINUS
-;
-
-PostfixExprNoBF_NoNode:
- LeftHandSideExprNoBF_NoNode
- | LeftHandSideExprNoBF_NoNode PLUSPLUS
- | LeftHandSideExprNoBF_NoNode MINUSMINUS
-;
-
-UnaryExprCommon_NoNode:
- DELETETOKEN UnaryExpr_NoNode
- | VOIDTOKEN UnaryExpr_NoNode
- | TYPEOF UnaryExpr_NoNode
- | PLUSPLUS UnaryExpr_NoNode
- | AUTOPLUSPLUS UnaryExpr_NoNode
- | MINUSMINUS UnaryExpr_NoNode
- | AUTOMINUSMINUS UnaryExpr_NoNode
- | '+' UnaryExpr_NoNode
- | '-' UnaryExpr_NoNode
- | '~' UnaryExpr_NoNode
- | '!' UnaryExpr_NoNode
-
-UnaryExpr_NoNode:
- PostfixExpr_NoNode
- | UnaryExprCommon_NoNode
-;
-
-UnaryExprNoBF_NoNode:
- PostfixExprNoBF_NoNode
- | UnaryExprCommon_NoNode
-;
-
-MultiplicativeExpr_NoNode:
- UnaryExpr_NoNode
- | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode
- | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode
- | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode
-;
-
-MultiplicativeExprNoBF_NoNode:
- UnaryExprNoBF_NoNode
- | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode
- | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode
- | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode
-;
-
-AdditiveExpr_NoNode:
- MultiplicativeExpr_NoNode
- | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode
- | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode
-;
-
-AdditiveExprNoBF_NoNode:
- MultiplicativeExprNoBF_NoNode
- | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode
- | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode
-;
-
-ShiftExpr_NoNode:
- AdditiveExpr_NoNode
- | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode
- | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode
- | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode
-;
-
-ShiftExprNoBF_NoNode:
- AdditiveExprNoBF_NoNode
- | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode
- | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode
- | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode
-;
-
-RelationalExpr_NoNode:
- ShiftExpr_NoNode
- | RelationalExpr_NoNode '<' ShiftExpr_NoNode
- | RelationalExpr_NoNode '>' ShiftExpr_NoNode
- | RelationalExpr_NoNode LE ShiftExpr_NoNode
- | RelationalExpr_NoNode GE ShiftExpr_NoNode
- | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode
- | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode
-;
-
-RelationalExprNoIn_NoNode:
- ShiftExpr_NoNode
- | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode
- | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode
- | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode
- | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode
- | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode
-;
-
-RelationalExprNoBF_NoNode:
- ShiftExprNoBF_NoNode
- | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode
- | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode
- | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode
- | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode
- | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode
- | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode
-;
-
-EqualityExpr_NoNode:
- RelationalExpr_NoNode
- | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode
- | EqualityExpr_NoNode NE RelationalExpr_NoNode
- | EqualityExpr_NoNode STREQ RelationalExpr_NoNode
- | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode
-;
-
-EqualityExprNoIn_NoNode:
- RelationalExprNoIn_NoNode
- | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode
- | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode
- | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode
- | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode
-;
-
-EqualityExprNoBF_NoNode:
- RelationalExprNoBF_NoNode
- | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode
- | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode
- | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode
- | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode
-;
-
-BitwiseANDExpr_NoNode:
- EqualityExpr_NoNode
- | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode
-;
-
-BitwiseANDExprNoIn_NoNode:
- EqualityExprNoIn_NoNode
- | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode
-;
-
-BitwiseANDExprNoBF_NoNode:
- EqualityExprNoBF_NoNode
- | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode
-;
-
-BitwiseXORExpr_NoNode:
- BitwiseANDExpr_NoNode
- | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode
-;
-
-BitwiseXORExprNoIn_NoNode:
- BitwiseANDExprNoIn_NoNode
- | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode
-;
-
-BitwiseXORExprNoBF_NoNode:
- BitwiseANDExprNoBF_NoNode
- | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode
-;
-
-BitwiseORExpr_NoNode:
- BitwiseXORExpr_NoNode
- | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode
-;
-
-BitwiseORExprNoIn_NoNode:
- BitwiseXORExprNoIn_NoNode
- | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode
-;
-
-BitwiseORExprNoBF_NoNode:
- BitwiseXORExprNoBF_NoNode
- | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode
-;
-
-LogicalANDExpr_NoNode:
- BitwiseORExpr_NoNode
- | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode
-;
-
-LogicalANDExprNoIn_NoNode:
- BitwiseORExprNoIn_NoNode
- | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode
-;
-
-LogicalANDExprNoBF_NoNode:
- BitwiseORExprNoBF_NoNode
- | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode
-;
-
-LogicalORExpr_NoNode:
- LogicalANDExpr_NoNode
- | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode
-;
-
-LogicalORExprNoIn_NoNode:
- LogicalANDExprNoIn_NoNode
- | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode
-;
-
-LogicalORExprNoBF_NoNode:
- LogicalANDExprNoBF_NoNode
- | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode
-;
-
-ConditionalExpr_NoNode:
- LogicalORExpr_NoNode
- | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
-;
-
-ConditionalExprNoIn_NoNode:
- LogicalORExprNoIn_NoNode
- | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode
-;
-
-ConditionalExprNoBF_NoNode:
- LogicalORExprNoBF_NoNode
- | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
-;
-
-AssignmentExpr_NoNode:
- ConditionalExpr_NoNode
- | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
-;
-
-AssignmentExprNoIn_NoNode:
- ConditionalExprNoIn_NoNode
- | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode
-;
-
-AssignmentExprNoBF_NoNode:
- ConditionalExprNoBF_NoNode
- | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
-;
-
-AssignmentOperator_NoNode:
- '='
- | PLUSEQUAL
- | MINUSEQUAL
- | MULTEQUAL
- | DIVEQUAL
- | LSHIFTEQUAL
- | RSHIFTEQUAL
- | URSHIFTEQUAL
- | ANDEQUAL
- | XOREQUAL
- | OREQUAL
- | MODEQUAL
-;
-
-Expr_NoNode:
- AssignmentExpr_NoNode
- | Expr_NoNode ',' AssignmentExpr_NoNode
-;
-
-ExprNoIn_NoNode:
- AssignmentExprNoIn_NoNode
- | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode
-;
-
-ExprNoBF_NoNode:
- AssignmentExprNoBF_NoNode
- | ExprNoBF_NoNode ',' AssignmentExpr_NoNode
-;
-
-Statement_NoNode:
- Block_NoNode
- | VariableStatement_NoNode
- | ConstStatement_NoNode
- | EmptyStatement_NoNode
- | ExprStatement_NoNode
- | IfStatement_NoNode
- | IterationStatement_NoNode
- | ContinueStatement_NoNode
- | BreakStatement_NoNode
- | ReturnStatement_NoNode
- | WithStatement_NoNode
- | SwitchStatement_NoNode
- | LabelledStatement_NoNode
- | ThrowStatement_NoNode
- | TryStatement_NoNode
- | DebuggerStatement_NoNode
-;
-
-Block_NoNode:
- OPENBRACE CLOSEBRACE { }
- | OPENBRACE SourceElements_NoNode CLOSEBRACE { }
-;
-
-VariableStatement_NoNode:
- VAR VariableDeclarationList_NoNode ';'
- | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; }
-;
-
-VariableDeclarationList_NoNode:
- IDENT { }
- | IDENT Initializer_NoNode { }
- | VariableDeclarationList_NoNode ',' IDENT
- | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode
-;
-
-VariableDeclarationListNoIn_NoNode:
- IDENT { }
- | IDENT InitializerNoIn_NoNode { }
- | VariableDeclarationListNoIn_NoNode ',' IDENT
- | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode
-;
-
-ConstStatement_NoNode:
- CONSTTOKEN ConstDeclarationList_NoNode ';'
- | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; }
-;
-
-ConstDeclarationList_NoNode:
- ConstDeclaration_NoNode
- | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode
-;
-
-ConstDeclaration_NoNode:
- IDENT { }
- | IDENT Initializer_NoNode { }
-;
-
-Initializer_NoNode:
- '=' AssignmentExpr_NoNode
-;
-
-InitializerNoIn_NoNode:
- '=' AssignmentExprNoIn_NoNode
-;
-
-EmptyStatement_NoNode:
- ';'
-;
-
-ExprStatement_NoNode:
- ExprNoBF_NoNode ';'
- | ExprNoBF_NoNode error { AUTO_SEMICOLON; }
-;
-
-IfStatement_NoNode:
- IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE
- | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode
-;
-
-IterationStatement_NoNode:
- DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';'
- | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion
- | WHILE '(' Expr_NoNode ')' Statement_NoNode
- | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
- | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
- | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
- | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode
- | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
-;
-
-ExprOpt_NoNode:
- /* nothing */
- | Expr_NoNode
-;
-
-ExprNoInOpt_NoNode:
- /* nothing */
- | ExprNoIn_NoNode
-;
-
-ContinueStatement_NoNode:
- CONTINUE ';'
- | CONTINUE error { AUTO_SEMICOLON; }
- | CONTINUE IDENT ';'
- | CONTINUE IDENT error { AUTO_SEMICOLON; }
-;
-
-BreakStatement_NoNode:
- BREAK ';'
- | BREAK error { AUTO_SEMICOLON; }
- | BREAK IDENT ';'
- | BREAK IDENT error { AUTO_SEMICOLON; }
-;
-
-ReturnStatement_NoNode:
- RETURN ';'
- | RETURN error { AUTO_SEMICOLON; }
- | RETURN Expr_NoNode ';'
- | RETURN Expr_NoNode error { AUTO_SEMICOLON; }
-;
-
-WithStatement_NoNode:
- WITH '(' Expr_NoNode ')' Statement_NoNode
-;
-
-SwitchStatement_NoNode:
- SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode
-;
-
-CaseBlock_NoNode:
- OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE { }
- | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE { }
-;
-
-CaseClausesOpt_NoNode:
- /* nothing */
- | CaseClauses_NoNode
-;
-
-CaseClauses_NoNode:
- CaseClause_NoNode
- | CaseClauses_NoNode CaseClause_NoNode
-;
-
-CaseClause_NoNode:
- CASE Expr_NoNode ':'
- | CASE Expr_NoNode ':' SourceElements_NoNode
-;
-
-DefaultClause_NoNode:
- DEFAULT ':'
- | DEFAULT ':' SourceElements_NoNode
-;
-
-LabelledStatement_NoNode:
- IDENT ':' Statement_NoNode { }
-;
-
-ThrowStatement_NoNode:
- THROW Expr_NoNode ';'
- | THROW Expr_NoNode error { AUTO_SEMICOLON; }
-;
-
-TryStatement_NoNode:
- TRY Block_NoNode FINALLY Block_NoNode
- | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode
- | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode
-;
-
-DebuggerStatement_NoNode:
- DEBUGGER ';'
- | DEBUGGER error { AUTO_SEMICOLON; }
-;
-
-FunctionDeclaration_NoNode:
- FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
- | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-;
-
-FunctionExpr_NoNode:
- FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
- | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
- | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
- | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-;
-
-FormalParameterList_NoNode:
- IDENT { }
- | FormalParameterList_NoNode ',' IDENT
-;
-
-FunctionBody_NoNode:
- /* not in spec */
- | SourceElements_NoNode
-;
-
-SourceElements_NoNode:
- SourceElement_NoNode
- | SourceElements_NoNode SourceElement_NoNode
-;
-
-SourceElement_NoNode:
- FunctionDeclaration_NoNode
- | Statement_NoNode
-;
-
-// End NoNodes
-
-%%
-
-static AddNode* makeAddNode(ExpressionNode* left, ExpressionNode* right)
-{
- JSType t1 = left->expectedReturnType();
- JSType t2 = right->expectedReturnType();
-
- if (t1 == NumberType && t2 == NumberType)
- return new AddNumbersNode(left, right);
- if (t1 == StringType && t2 == StringType)
- return new AddStringsNode(left, right);
- if (t1 == StringType)
- return new AddStringLeftNode(left, right);
- if (t2 == StringType)
- return new AddStringRightNode(left, right);
- return new AddNode(left, right);
-}
-
-static LessNode* makeLessNode(ExpressionNode* left, ExpressionNode* right)
-{
- JSType t1 = left->expectedReturnType();
- JSType t2 = right->expectedReturnType();
-
- if (t1 == StringType && t2 == StringType)
- return new LessStringsNode(left, right);
-
- // There are certainly more efficient ways to do this type check if necessary
- if (t1 == NumberType || t1 == BooleanType || t1 == UndefinedType || t1 == NullType ||
- t2 == NumberType || t2 == BooleanType || t2 == UndefinedType || t2 == NullType)
- return new LessNumbersNode(left, right);
-
- // Neither is certain to be a number, nor were both certain to be strings, so we use the default (slow) implementation.
- return new LessNode(left, right);
-}
-
-static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr)
-{
- if (!loc->isLocation())
- return new AssignErrorNode(loc, op, expr);
-
- if (loc->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(loc);
- if (op == OpEqual)
- return new AssignResolveNode(resolve->identifier(), expr);
- else
- return new ReadModifyResolveNode(resolve->identifier(), op, expr);
- }
- if (loc->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
- if (op == OpEqual)
- return new AssignBracketNode(bracket->base(), bracket->subscript(), expr);
- else
- return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr);
- }
- ASSERT(loc->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
- if (op == OpEqual)
- return new AssignDotNode(dot->base(), dot->identifier(), expr);
- return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr);
-}
-
-static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator op)
-{
- if (!expr->isLocation())
- return new PrefixErrorNode(expr, op);
-
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- if (op == OpPlusPlus)
- return new PreIncResolveNode(resolve->identifier());
- else
- return new PreDecResolveNode(resolve->identifier());
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- if (op == OpPlusPlus)
- return new PreIncBracketNode(bracket->base(), bracket->subscript());
- else
- return new PreDecBracketNode(bracket->base(), bracket->subscript());
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- if (op == OpPlusPlus)
- return new PreIncDotNode(dot->base(), dot->identifier());
- return new PreDecDotNode(dot->base(), dot->identifier());
-}
-
-static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator op)
-{
- if (!expr->isLocation())
- return new PostfixErrorNode(expr, op);
-
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- if (op == OpPlusPlus)
- return new PostIncResolveNode(resolve->identifier());
- else
- return new PostDecResolveNode(resolve->identifier());
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- if (op == OpPlusPlus)
- return new PostIncBracketNode(bracket->base(), bracket->subscript());
- else
- return new PostDecBracketNode(bracket->base(), bracket->subscript());
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-
- if (op == OpPlusPlus)
- return new PostIncDotNode(dot->base(), dot->identifier());
- return new PostDecDotNode(dot->base(), dot->identifier());
-}
-
-static ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args)
-{
- if (!func->isLocation())
- return new FunctionCallValueNode(func, args);
- if (func->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(func);
- return new FunctionCallResolveNode(resolve->identifier(), args);
- }
- if (func->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func);
- return new FunctionCallBracketNode(bracket->base(), bracket->subscript(), args);
- }
- ASSERT(func->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
- return new FunctionCallDotNode(dot->base(), dot->identifier(), args);
-}
-
-static ExpressionNode* makeTypeOfNode(ExpressionNode* expr)
-{
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new TypeOfResolveNode(resolve->identifier());
- }
- return new TypeOfValueNode(expr);
-}
-
-static ExpressionNode* makeDeleteNode(ExpressionNode* expr)
-{
- if (!expr->isLocation())
- return new DeleteValueNode(expr);
- if (expr->isResolveNode()) {
- ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new DeleteResolveNode(resolve->identifier());
- }
- if (expr->isBracketAccessorNode()) {
- BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
- return new DeleteBracketNode(bracket->base(), bracket->subscript());
- }
- ASSERT(expr->isDotAccessorNode());
- DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
- return new DeleteDotNode(dot->base(), dot->identifier());
-}
-
-static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
-{
- PropertyNode::Type type;
- if (getOrSet == "get")
- type = PropertyNode::Getter;
- else if (getOrSet == "set")
- type = PropertyNode::Setter;
- else
- return 0;
- return new PropertyNode(name, new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, source, params), type);
-}
-
-static ExpressionNode* makeNegateNode(ExpressionNode* n)
-{
- if (n->isNumber()) {
- NumberNode* number = static_cast<NumberNode*>(n);
-
- if (number->value() > 0.0) {
- number->setValue(-number->value());
- return number;
- }
- }
-
- return new NegateNode(n);
-}
-
-static NumberNode* makeNumberNode(double d)
-{
- JSValue* value = JSImmediate::from(d);
- if (value)
- return new ImmediateNumberNode(value, d);
- return new NumberNode(d);
-}
-
-/* called by yyparse on error */
-int yyerror(const char *)
-{
- return 1;
-}
-
-/* may we automatically insert a semicolon ? */
-static bool allowAutomaticSemicolon()
-{
- return yychar == CLOSEBRACE || yychar == 0 || lexer().prevTerminator();
-}
-
-static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init)
-{
- if (!list)
- return init;
- return new VarDeclCommaNode(list, init);
-}
-
-// We turn variable declarations into either assignments or empty
-// statements (which later get stripped out), because the actual
-// declaration work is hoisted up to the start of the function body
-static StatementNode* makeVarStatementNode(ExpressionNode* expr)
-{
- if (!expr)
- return new EmptyStatementNode();
- return new VarStatementNode(expr);
-}
-
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#include "identifier.h"
-
-#include "JSLock.h"
-#include <new> // for placement new
-#include <string.h> // for strlen
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashSet.h>
-
-namespace WTF {
-
- template<typename T> struct DefaultHash;
- template<typename T> struct StrHash;
-
- template<> struct StrHash<KJS::UString::Rep *> {
- static unsigned hash(const KJS::UString::Rep *key) { return key->hash(); }
- static bool equal(const KJS::UString::Rep *a, const KJS::UString::Rep *b) { return KJS::Identifier::equal(a, b); }
- static const bool safeToCompareToEmptyOrDeleted = false;
- };
-
- template<> struct DefaultHash<KJS::UString::Rep *> {
- typedef StrHash<KJS::UString::Rep *> Hash;
- };
-
-}
-
-namespace KJS {
-
-typedef HashSet<UString::Rep *> IdentifierTable;
-static IdentifierTable *table;
-
-static inline IdentifierTable& identifierTable()
-{
- ASSERT(JSLock::lockCount() > 0);
-
- if (!table)
- table = new IdentifierTable;
- return *table;
-}
-
-
-bool Identifier::equal(const UString::Rep *r, const char *s)
-{
- int length = r->len;
- const UChar *d = r->data();
- for (int i = 0; i != length; ++i)
- if (d[i].uc != (unsigned char)s[i])
- return false;
- return s[length] == 0;
-}
-
-bool Identifier::equal(const UString::Rep *r, const UChar *s, int length)
-{
- if (r->len != length)
- return false;
- const UChar *d = r->data();
- for (int i = 0; i != length; ++i)
- if (d[i].uc != s[i].uc)
- return false;
- return true;
-}
-
-bool Identifier::equal(const UString::Rep *r, const UString::Rep *b)
-{
- int length = r->len;
- if (length != b->len)
- return false;
- const UChar *d = r->data();
- const UChar *s = b->data();
- for (int i = 0; i != length; ++i)
- if (d[i].uc != s[i].uc)
- return false;
- return true;
-}
-
-struct CStringTranslator
-{
- static unsigned hash(const char *c)
- {
- return UString::Rep::computeHash(c);
- }
-
- static bool equal(UString::Rep *r, const char *s)
- {
- return Identifier::equal(r, s);
- }
-
- static void translate(UString::Rep*& location, const char *c, unsigned hash)
- {
- size_t length = strlen(c);
- UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * length));
- for (size_t i = 0; i != length; i++)
- d[i] = c[i];
-
- UString::Rep *r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
- r->isIdentifier = 1;
- r->rc = 0;
- r->_hash = hash;
-
- location = r;
- }
-};
-
-PassRefPtr<UString::Rep> Identifier::add(const char *c)
-{
- if (!c) {
- UString::Rep::null.hash();
- return &UString::Rep::null;
- }
-
- if (!c[0]) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
-
- return *identifierTable().add<const char *, CStringTranslator>(c).first;
-}
-
-struct UCharBuffer {
- const UChar *s;
- unsigned int length;
-};
-
-struct UCharBufferTranslator
-{
- static unsigned hash(const UCharBuffer& buf)
- {
- return UString::Rep::computeHash(buf.s, buf.length);
- }
-
- static bool equal(UString::Rep *str, const UCharBuffer& buf)
- {
- return Identifier::equal(str, buf.s, buf.length);
- }
-
- static void translate(UString::Rep *& location, const UCharBuffer& buf, unsigned hash)
- {
- UChar *d = static_cast<UChar *>(fastMalloc(sizeof(UChar) * buf.length));
- for (unsigned i = 0; i != buf.length; i++)
- d[i] = buf.s[i];
-
- UString::Rep *r = UString::Rep::create(d, buf.length).releaseRef();
- r->isIdentifier = 1;
- r->rc = 0;
- r->_hash = hash;
-
- location = r;
- }
-};
-
-PassRefPtr<UString::Rep> Identifier::add(const UChar *s, int length)
-{
- if (!length) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
-
- UCharBuffer buf = {s, length};
- return *identifierTable().add<UCharBuffer, UCharBufferTranslator>(buf).first;
-}
-
-PassRefPtr<UString::Rep> Identifier::addSlowCase(UString::Rep *r)
-{
- ASSERT(!r->isIdentifier);
-
- if (r->len == 0) {
- UString::Rep::empty.hash();
- return &UString::Rep::empty;
- }
-
- UString::Rep *result = *identifierTable().add(r).first;
- if (result == r)
- r->isIdentifier = true;
- return result;
-}
-
-void Identifier::remove(UString::Rep *r)
-{
- identifierTable().remove(r);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_IDENTIFIER_H
-#define KJS_IDENTIFIER_H
-
-#include "ustring.h"
-
-namespace KJS {
-
- class Identifier {
- friend class PropertyMap;
- public:
- Identifier() { }
- Identifier(const char* s) : _ustring(add(s)) { }
- Identifier(const UChar* s, int length) : _ustring(add(s, length)) { }
- explicit Identifier(UString::Rep* rep) : _ustring(add(rep)) { }
- explicit Identifier(const UString& s) : _ustring(add(s.rep())) { }
-
- // Special constructor for cases where we overwrite an object in place.
- Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { }
-
- const UString& ustring() const { return _ustring; }
- DOM::DOMString domString() const;
-
- const UChar* data() const { return _ustring.data(); }
- int size() const { return _ustring.size(); }
-
- const char* ascii() const { return _ustring.ascii(); }
-
- static Identifier from(unsigned y) { return Identifier(UString::from(y)); }
-
- bool isNull() const { return _ustring.isNull(); }
- bool isEmpty() const { return _ustring.isEmpty(); }
-
- uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); }
- uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); };
- uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); }
- unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); }
- double toDouble() const { return _ustring.toDouble(); }
-
- friend bool operator==(const Identifier&, const Identifier&);
- friend bool operator!=(const Identifier&, const Identifier&);
-
- friend bool operator==(const Identifier&, const char*);
-
- static void remove(UString::Rep* );
-
- static bool equal(const UString::Rep*, const char*);
- static bool equal(const UString::Rep*, const UChar*, int length);
- static bool equal(const UString::Rep*, const UString::Rep*);
-
- private:
- UString _ustring;
-
- static bool equal(const Identifier& a, const Identifier& b)
- { return a._ustring.rep() == b._ustring.rep(); }
- static bool equal(const Identifier& a, const char* b)
- { return equal(a._ustring.rep(), b); }
-
- static PassRefPtr<UString::Rep> add(const char*);
- static PassRefPtr<UString::Rep> add(const UChar*, int length);
- static PassRefPtr<UString::Rep> add(UString::Rep* r)
- {
- if (r->isIdentifier)
- return r;
- return addSlowCase(r);
- }
- static PassRefPtr<UString::Rep> addSlowCase(UString::Rep *r);
- };
-
- inline bool operator==(const Identifier& a, const Identifier& b)
- { return Identifier::equal(a, b); }
-
- inline bool operator!=(const Identifier& a, const Identifier& b)
- { return !Identifier::equal(a, b); }
-
- inline bool operator==(const Identifier& a, const char* b)
- { return Identifier::equal(a, b); }
-
-} // namespace KJS
-
-#endif // KJS_IDENTIFIER_H
+++ /dev/null
-/*
- * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "internal.h"
-
-#include "ExecState.h"
-#include "array_object.h"
-#include "bool_object.h"
-#include "collector.h"
-#include "date_object.h"
-#include "debugger.h"
-#include "error_object.h"
-#include "function_object.h"
-#include "lexer.h"
-#include "math_object.h"
-#include "nodes.h"
-#include "number_object.h"
-#include "object.h"
-#include "object_object.h"
-#include "operations.h"
-#include "regexp_object.h"
-#include "string_object.h"
-#include <math.h>
-#include <stdio.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashMap.h>
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-
-// ------------------------------ StringImp ------------------------------------
-
-JSValue* StringImp::toPrimitive(ExecState*, JSType) const
-{
- return const_cast<StringImp*>(this);
-}
-
-bool StringImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
-{
- value = this;
- number = val.toDouble();
- return false;
-}
-
-bool StringImp::toBoolean(ExecState *) const
-{
- return (val.size() > 0);
-}
-
-double StringImp::toNumber(ExecState *) const
-{
- return val.toDouble();
-}
-
-UString StringImp::toString(ExecState *) const
-{
- return val;
-}
-
-JSObject* StringImp::toObject(ExecState *exec) const
-{
- return new StringInstance(exec->lexicalGlobalObject()->stringPrototype(), const_cast<StringImp*>(this));
-}
-
-// ------------------------------ NumberImp ------------------------------------
-
-JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
-{
- return const_cast<NumberImp*>(this);
-}
-
-bool NumberImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
-{
- number = val;
- value = this;
- return true;
-}
-
-bool NumberImp::toBoolean(ExecState *) const
-{
- return val < 0.0 || val > 0.0; // false for NaN
-}
-
-double NumberImp::toNumber(ExecState *) const
-{
- return val;
-}
-
-UString NumberImp::toString(ExecState *) const
-{
- if (val == 0.0) // +0.0 or -0.0
- return "0";
- return UString::from(val);
-}
-
-JSObject *NumberImp::toObject(ExecState *exec) const
-{
- List args;
- args.append(const_cast<NumberImp*>(this));
- return static_cast<JSObject *>(exec->lexicalGlobalObject()->numberConstructor()->construct(exec,args));
-}
-
-bool NumberImp::getUInt32(uint32_t& uint32) const
-{
- uint32 = static_cast<uint32_t>(val);
- return uint32 == val;
-}
-
-bool NumberImp::getTruncatedInt32(int32_t& int32) const
-{
- if (!(val >= -2147483648.0 && val < 2147483648.0))
- return false;
- int32 = static_cast<int32_t>(val);
- return true;
-}
-
-bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
-{
- if (!(val >= 0.0 && val < 4294967296.0))
- return false;
- uint32 = static_cast<uint32_t>(val);
- return true;
-}
-
-// --------------------------- GetterSetterImp ---------------------------------
-void GetterSetterImp::mark()
-{
- JSCell::mark();
-
- if (getter && !getter->marked())
- getter->mark();
- if (setter && !setter->marked())
- setter->mark();
-}
-
-JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
-{
- ASSERT(false);
- return jsNull();
-}
-
-bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
-{
- ASSERT_NOT_REACHED();
- number = 0;
- value = 0;
- return true;
-}
-
-bool GetterSetterImp::toBoolean(ExecState*) const
-{
- ASSERT(false);
- return false;
-}
-
-double GetterSetterImp::toNumber(ExecState *) const
-{
- ASSERT(false);
- return 0.0;
-}
-
-UString GetterSetterImp::toString(ExecState *) const
-{
- ASSERT(false);
- return UString::null();
-}
-
-JSObject *GetterSetterImp::toObject(ExecState *exec) const
-{
- ASSERT(false);
- return jsNull()->toObject(exec);
-}
-
-// ------------------------------ LabelStack -----------------------------------
-
-bool LabelStack::push(const Identifier &id)
-{
- if (contains(id))
- return false;
-
- StackElem *newtos = new StackElem;
- newtos->id = id;
- newtos->prev = tos;
- tos = newtos;
- return true;
-}
-
-bool LabelStack::contains(const Identifier &id) const
-{
- if (id.isEmpty())
- return true;
-
- for (StackElem *curr = tos; curr; curr = curr->prev)
- if (curr->id == id)
- return true;
-
- return false;
-}
-
-// ------------------------------ InternalFunctionImp --------------------------
-
-const ClassInfo InternalFunctionImp::info = { "Function", 0, 0 };
-
-InternalFunctionImp::InternalFunctionImp()
-{
-}
-
-InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
- : JSObject(funcProto)
- , m_name(name)
-{
-}
-
-bool InternalFunctionImp::implementsCall() const
-{
- return true;
-}
-
-bool InternalFunctionImp::implementsHasInstance() const
-{
- return true;
-}
-
-// ------------------------------ global functions -----------------------------
-
-#ifndef NDEBUG
-#include <stdio.h>
-void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
-{
- if (!o)
- fprintf(stderr, "KJS: %s: (null)", s);
- else {
- JSValue *v = o;
-
- UString name;
- switch (v->type()) {
- case UnspecifiedType:
- name = "Unspecified";
- break;
- case UndefinedType:
- name = "Undefined";
- break;
- case NullType:
- name = "Null";
- break;
- case BooleanType:
- name = "Boolean";
- break;
- case StringType:
- name = "String";
- break;
- case NumberType:
- name = "Number";
- break;
- case ObjectType:
- name = static_cast<JSObject *>(v)->className();
- if (name.isNull())
- name = "(unknown class)";
- break;
- case GetterSetterType:
- name = "GetterSetter";
- break;
- }
- UString vString = v->toString(exec);
- if ( vString.size() > 50 )
- vString = vString.substr( 0, 50 ) + "...";
- // Can't use two UString::ascii() in the same fprintf call
- CString tempString( vString.cstring() );
-
- fprintf(stderr, "KJS: %s: %s : %s (%p)",
- s, tempString.c_str(), name.ascii(), (void*)v);
-
- if (lineno >= 0)
- fprintf(stderr, ", line %d\n",lineno);
- else
- fprintf(stderr, "\n");
- }
-}
-#endif
-
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef INTERNAL_H
-#define INTERNAL_H
-
-#include "JSType.h"
-#include "object.h"
-#include "protect.h"
-#include "scope_chain.h"
-#include "types.h"
-#include "ustring.h"
-
-#include <wtf/Noncopyable.h>
-
-#define I18N_NOOP(s) s
-
-namespace KJS {
-
- class FunctionPrototype;
-
- // ---------------------------------------------------------------------------
- // Primitive impls
- // ---------------------------------------------------------------------------
-
- class StringImp : public JSCell {
- public:
- StringImp(const UString& v) : val(v) { Collector::reportExtraMemoryCost(v.cost()); }
- enum HasOtherOwnerType { HasOtherOwner };
- StringImp(const UString& value, HasOtherOwnerType) : val(value) { }
- const UString& value() const { return val; }
-
- private:
- virtual JSType type() const { return StringType; }
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState *exec) const;
- virtual double toNumber(ExecState *exec) const;
- virtual JSObject *toObject(ExecState *exec) const;
- virtual UString toString(ExecState*) const;
-
- UString val;
- };
-
- class NumberImp : public JSCell {
- friend class ConstantValues;
- friend JSValue *jsNumberCell(double);
- public:
- double value() const { return val; }
-
- virtual JSType type() const { return NumberType; }
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState *exec) const;
- virtual double toNumber(ExecState *exec) const;
- virtual UString toString(ExecState *exec) const;
- virtual JSObject *toObject(ExecState *exec) const;
-
- void* operator new(size_t size)
- {
- return Collector::allocateNumber(size);
- }
- private:
- NumberImp(double v) : val(v) { }
-
- virtual bool getUInt32(uint32_t&) const;
- virtual bool getTruncatedInt32(int32_t&) const;
- virtual bool getTruncatedUInt32(uint32_t&) const;
-
- double val;
- };
-
-
- // ---------------------------------------------------------------------------
- // Evaluation
- // ---------------------------------------------------------------------------
-
- struct AttachedGlobalObject;
- class DebuggerImp {
- public:
-
- DebuggerImp() {
- globalObjects = 0;
- isAborted = false;
- }
-
- void abort() { isAborted = true; }
- bool aborted() const { return isAborted; }
-
- AttachedGlobalObject* globalObjects;
- bool isAborted;
- };
-
-#ifndef NDEBUG
- void printInfo(ExecState *exec, const char *s, JSValue *, int lineno = -1);
-#endif
-
-} // namespace
-
-#endif // INTERNAL_H
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "interpreter.h"
-
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "Parser.h"
-#include "SavedBuiltins.h"
-#include "array_object.h"
-#include "bool_object.h"
-#include "collector.h"
-#include "date_object.h"
-#include "debugger.h"
-#include "error_object.h"
-#include "function_object.h"
-#include "internal.h"
-#include "math_object.h"
-#include "nodes.h"
-#include "number_object.h"
-#include "object.h"
-#include "object_object.h"
-#include "operations.h"
-#include "regexp_object.h"
-#include "runtime.h"
-#include "string_object.h"
-#include "types.h"
-#include "value.h"
-#include <math.h>
-#include <stdio.h>
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-Completion Interpreter::checkSyntax(ExecState* exec, const SourceCode& source)
-{
- JSLock lock;
-
- int errLine;
- UString errMsg;
- RefPtr<ProgramNode> progNode = parser().parse<ProgramNode>(source, &errLine, &errMsg);
- if (!progNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
- return Completion(Normal);
-}
-
-Completion Interpreter::evaluate(ExecState* exec, const SourceCode& source, JSValue* thisV)
-{
- JSLock lock;
-
- JSGlobalObject* globalObject = exec->dynamicGlobalObject();
-
- if (globalObject->recursion() >= 20)
- return Completion(Throw, Error::create(exec, GeneralError, "Recursion too deep"));
-
- // parse the source code
- int errLine;
- UString errMsg;
- RefPtr<ProgramNode> progNode = parser().parse<ProgramNode>(source, &errLine, &errMsg);
-
- // removed debugger support
-
- // no program node means a syntax error occurred
- if (!progNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
-
- exec->clearException();
-
- globalObject->incRecursion();
-
- JSObject* thisObj = globalObject;
-
- // "this" must be an object... use same rules as Function.prototype.apply()
- if (thisV && !thisV->isUndefinedOrNull())
- thisObj = thisV->toObject(exec);
-
- Completion res;
- if (exec->hadException())
- // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
- res = Completion(Throw, exec->exception());
- else {
- // execute the code
- InterpreterExecState newExec(globalObject, thisObj, progNode.get());
- JSValue* value = progNode->execute(&newExec);
- res = Completion(newExec.completionType(), value);
- }
-
- globalObject->decRecursion();
-
- if (shouldPrintExceptions() && res.complType() == Throw) {
- JSLock lock;
- ExecState* exec = globalObject->globalExec();
- CString f = source.provider()->url().UTF8String();
- CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
- int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
-#if PLATFORM(WIN_OS)
- printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
-#else
- printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
-#endif
- }
-
- return res;
-}
-
-static bool printExceptions = false;
-
-bool Interpreter::shouldPrintExceptions()
-{
- return printExceptions;
-}
-
-void Interpreter::setShouldPrintExceptions(bool print)
-{
- printExceptions = print;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_Interpreter_h
-#define KJS_Interpreter_h
-
-#include <wtf/PassRefPtr.h>
-
-namespace KJS {
-
- class Completion;
- class ExecState;
- class JSValue;
- class SourceCode;
- class UString;
-
- struct UChar;
-
- class Interpreter {
- public:
- /**
- * Parses the supplied ECMAScript code and checks for syntax errors.
- *
- * @param code The code to check
- * @return A normal completion if there were no syntax errors in the code,
- * otherwise a throw completion with the syntax error as its value.
- */
- static Completion checkSyntax(ExecState*, const SourceCode&);
-
- /**
- * Evaluates the supplied ECMAScript code.
- *
- * Since this method returns a Completion, you should check the type of
- * completion to detect an error or before attempting to access the returned
- * value. For example, if an error occurs during script execution and is not
- * caught by the script, the completion type will be Throw.
- *
- * If the supplied code is invalid, a SyntaxError will be thrown.
- *
- * @param code The code to evaluate
- * @param thisV The value to pass in as the "this" value for the script
- * execution. This should either be jsNull() or an Object.
- * @return A completion object representing the result of the execution.
- */
- static Completion evaluate(ExecState*, const SourceCode&, JSValue* thisV = 0);
-
- static bool shouldPrintExceptions();
- static void setShouldPrintExceptions(bool);
- };
-
-} // namespace KJS
-
-#endif // KJS_Interpreter_h
+++ /dev/null
-# main keywords
-@begin mainTable 41
-
-# types
-null NULLTOKEN
-true TRUETOKEN
-false FALSETOKEN
-
-# keywords
-break BREAK
-case CASE
-catch CATCH
-const CONSTTOKEN
-default DEFAULT
-finally FINALLY
-for FOR
-instanceof INSTANCEOF
-new NEW
-var VAR
-continue CONTINUE
-function FUNCTION
-return RETURN
-void VOIDTOKEN
-delete DELETETOKEN
-if IF
-this THISTOKEN
-do DO
-while WHILE
-else ELSE
-in INTOKEN
-switch SWITCH
-throw THROW
-try TRY
-typeof TYPEOF
-with WITH
-debugger DEBUGGER
-
-# reserved for future use
-class RESERVED
-enum RESERVED
-export RESERVED
-extends RESERVED
-import RESERVED
-super RESERVED
-
-# these words are reserved for future use in the ECMA spec, but not in WinIE
-# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
-# abstract RESERVED
-# boolean RESERVED
-# byte RESERVED
-# char RESERVED
-# double RESERVED
-# final RESERVED
-# float RESERVED
-# goto RESERVED
-# implements RESERVED
-# int RESERVED
-# interface RESERVED
-# long RESERVED
-# native RESERVED
-# package RESERVED
-# private RESERVED
-# protected RESERVED
-# public RESERVED
-# short RESERVED
-# static RESERVED
-# synchronized RESERVED
-# throws RESERVED
-# transient RESERVED
-# volatile RESERVED
-@end
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "lexer.h"
-
-#include "dtoa.h"
-#include "function.h"
-#include "nodes.h"
-#include "NodeInfo.h"
-#include <ctype.h>
-#include <limits.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-#include <wtf/unicode/Unicode.h>
-
-using namespace WTF;
-using namespace Unicode;
-
-// we can't specify the namespace in yacc's C output, so do it here
-using namespace KJS;
-
-#ifndef KDE_USE_FINAL
-#include "grammar.h"
-#endif
-
-#include "lookup.h"
-#include "lexer.lut.h"
-
-extern YYLTYPE kjsyylloc; // global bison variable holding token info
-
-// a bridge for yacc from the C world to C++
-int kjsyylex()
-{
- return lexer().lex();
-}
-
-namespace KJS {
-
-static bool isDecimalDigit(int);
-
-static const size_t initialReadBufferCapacity = 32;
-static const size_t initialStringTableCapacity = 64;
-
-Lexer& lexer()
-{
- ASSERT(JSLock::currentThreadIsHoldingLock());
-
- // FIXME: We'd like to avoid calling new here, but we don't currently
- // support tearing down the Lexer at app quit time, since that would involve
- // tearing down its UString data members without holding the JSLock.
- static Lexer* staticLexer = new Lexer;
- return *staticLexer;
-}
-
-Lexer::Lexer()
- : yylineno(1)
- , restrKeyword(false)
- , eatNextIdentifier(false)
- , stackToken(-1)
- , lastToken(-1)
- , pos(0)
- , code(0)
- , length(0)
- , atLineStart(true)
- , current(0)
- , next1(0)
- , next2(0)
- , next3(0)
- , m_currentOffset(0)
- , m_nextOffset1(0)
- , m_nextOffset2(0)
- , m_nextOffset3(0)
-{
- m_buffer8.reserveCapacity(initialReadBufferCapacity);
- m_buffer16.reserveCapacity(initialReadBufferCapacity);
- m_strings.reserveCapacity(initialStringTableCapacity);
- m_identifiers.reserveCapacity(initialStringTableCapacity);
-}
-
-void Lexer::setCode(const SourceCode& source)
-{
- yylineno = source.firstLine();
- restrKeyword = false;
- delimited = false;
- eatNextIdentifier = false;
- stackToken = -1;
- lastToken = -1;
- pos = 0;
- m_source = &source;
- code = source.provider()->data() + source.startOffset();
- length = source.length();
- skipLF = false;
- skipCR = false;
- error = false;
- atLineStart = true;
-
- // read first characters
- shift(4);
-}
-
-void Lexer::shift(unsigned p)
-{
- // ECMA-262 calls for stripping Cf characters here, but we only do this for BOM,
- // see <https://bugs.webkit.org/show_bug.cgi?id=4931>.
-
- while (p--) {
- current = next1;
- next1 = next2;
- next2 = next3;
- m_currentOffset = m_nextOffset1;
- m_nextOffset1 = m_nextOffset2;
- m_nextOffset2 = m_nextOffset3;
- do {
- if (pos >= length) {
- m_nextOffset3 = pos;
- pos++;
- next3 = -1;
- break;
- }
- m_nextOffset3 = pos;
- next3 = code[pos++].uc;
- } while (next3 == 0xFEFF);
- }
-}
-
-// called on each new line
-void Lexer::nextLine()
-{
- yylineno++;
- atLineStart = true;
-}
-
-void Lexer::setDone(State s)
-{
- state = s;
- done = true;
-}
-
-int Lexer::lex()
-{
- int token = 0;
- state = Start;
- unsigned short stringType = 0; // either single or double quotes
- m_buffer8.clear();
- m_buffer16.clear();
- done = false;
- terminator = false;
- skipLF = false;
- skipCR = false;
-
- // did we push a token on the stack previously ?
- // (after an automatic semicolon insertion)
- if (stackToken >= 0) {
- setDone(Other);
- token = stackToken;
- stackToken = 0;
- }
-
- int startOffset = m_currentOffset;
- while (!done) {
- if (skipLF && current != '\n') // found \r but not \n afterwards
- skipLF = false;
- if (skipCR && current != '\r') // found \n but not \r afterwards
- skipCR = false;
- if (skipLF || skipCR) // found \r\n or \n\r -> eat the second one
- {
- skipLF = false;
- skipCR = false;
- shift(1);
- }
- switch (state) {
- case Start:
- startOffset = m_currentOffset;
- if (isWhiteSpace()) {
- // do nothing
- } else if (current == '/' && next1 == '/') {
- shift(1);
- state = InSingleLineComment;
- } else if (current == '/' && next1 == '*') {
- shift(1);
- state = InMultiLineComment;
- } else if (current == -1) {
- if (!terminator && !delimited) {
- // automatic semicolon insertion if program incomplete
- token = ';';
- stackToken = 0;
- setDone(Other);
- } else
- setDone(Eof);
- } else if (isLineTerminator()) {
- nextLine();
- terminator = true;
- if (restrKeyword) {
- token = ';';
- setDone(Other);
- }
- } else if (current == '"' || current == '\'') {
- state = InString;
- stringType = static_cast<unsigned short>(current);
- } else if (isIdentStart(current)) {
- record16(current);
- state = InIdentifierOrKeyword;
- } else if (current == '\\') {
- state = InIdentifierStartUnicodeEscapeStart;
- } else if (current == '0') {
- record8(current);
- state = InNum0;
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InNum;
- } else if (current == '.' && isDecimalDigit(next1)) {
- record8(current);
- state = InDecimal;
- // <!-- marks the beginning of a line comment (for www usage)
- } else if (current == '<' && next1 == '!' &&
- next2 == '-' && next3 == '-') {
- shift(3);
- state = InSingleLineComment;
- // same for -->
- } else if (atLineStart && current == '-' && next1 == '-' && next2 == '>') {
- shift(2);
- state = InSingleLineComment;
- } else {
- token = matchPunctuator(kjsyylval.intValue, current, next1, next2, next3);
- if (token != -1) {
- setDone(Other);
- } else {
- // cerr << "encountered unknown character" << endl;
- setDone(Bad);
- }
- }
- break;
- case InString:
- if (current == stringType) {
- shift(1);
- setDone(String);
- } else if (isLineTerminator() || current == -1) {
- setDone(Bad);
- } else if (current == '\\') {
- state = InEscapeSequence;
- } else {
- record16(current);
- }
- break;
- // Escape Sequences inside of strings
- case InEscapeSequence:
- if (isOctalDigit(current)) {
- if (current >= '0' && current <= '3' &&
- isOctalDigit(next1) && isOctalDigit(next2)) {
- record16(convertOctal(current, next1, next2));
- shift(2);
- state = InString;
- } else if (isOctalDigit(current) && isOctalDigit(next1)) {
- record16(convertOctal('0', current, next1));
- shift(1);
- state = InString;
- } else if (isOctalDigit(current)) {
- record16(convertOctal('0', '0', current));
- state = InString;
- } else {
- setDone(Bad);
- }
- } else if (current == 'x')
- state = InHexEscape;
- else if (current == 'u')
- state = InUnicodeEscape;
- else if (isLineTerminator()) {
- nextLine();
- state = InString;
- } else {
- record16(singleEscape(static_cast<unsigned short>(current)));
- state = InString;
- }
- break;
- case InHexEscape:
- if (isHexDigit(current) && isHexDigit(next1)) {
- state = InString;
- record16(convertHex(current, next1));
- shift(1);
- } else if (current == stringType) {
- record16('x');
- shift(1);
- setDone(String);
- } else {
- record16('x');
- record16(current);
- state = InString;
- }
- break;
- case InUnicodeEscape:
- if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) {
- record16(convertUnicode(current, next1, next2, next3));
- shift(3);
- state = InString;
- } else if (current == stringType) {
- record16('u');
- shift(1);
- setDone(String);
- } else {
- setDone(Bad);
- }
- break;
- case InSingleLineComment:
- if (isLineTerminator()) {
- nextLine();
- terminator = true;
- if (restrKeyword) {
- token = ';';
- setDone(Other);
- } else
- state = Start;
- } else if (current == -1) {
- setDone(Eof);
- }
- break;
- case InMultiLineComment:
- if (current == -1) {
- setDone(Bad);
- } else if (isLineTerminator()) {
- nextLine();
- } else if (current == '*' && next1 == '/') {
- state = Start;
- shift(1);
- }
- break;
- case InIdentifierOrKeyword:
- case InIdentifier:
- if (isIdentPart(current))
- record16(current);
- else if (current == '\\')
- state = InIdentifierPartUnicodeEscapeStart;
- else
- setDone(state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
- break;
- case InNum0:
- if (current == 'x' || current == 'X') {
- record8(current);
- state = InHex;
- } else if (current == '.') {
- record8(current);
- state = InDecimal;
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else if (isOctalDigit(current)) {
- record8(current);
- state = InOctal;
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InDecimal;
- } else {
- setDone(Number);
- }
- break;
- case InHex:
- if (isHexDigit(current)) {
- record8(current);
- } else {
- setDone(Hex);
- }
- break;
- case InOctal:
- if (isOctalDigit(current)) {
- record8(current);
- }
- else if (isDecimalDigit(current)) {
- record8(current);
- state = InDecimal;
- } else
- setDone(Octal);
- break;
- case InNum:
- if (isDecimalDigit(current)) {
- record8(current);
- } else if (current == '.') {
- record8(current);
- state = InDecimal;
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InDecimal:
- if (isDecimalDigit(current)) {
- record8(current);
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InExponentIndicator:
- if (current == '+' || current == '-') {
- record8(current);
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InExponent;
- } else
- setDone(Bad);
- break;
- case InExponent:
- if (isDecimalDigit(current)) {
- record8(current);
- } else
- setDone(Number);
- break;
- case InIdentifierStartUnicodeEscapeStart:
- if (current == 'u')
- state = InIdentifierStartUnicodeEscape;
- else
- setDone(Bad);
- break;
- case InIdentifierPartUnicodeEscapeStart:
- if (current == 'u')
- state = InIdentifierPartUnicodeEscape;
- else
- setDone(Bad);
- break;
- case InIdentifierStartUnicodeEscape:
- if (!isHexDigit(current) || !isHexDigit(next1) || !isHexDigit(next2) || !isHexDigit(next3)) {
- setDone(Bad);
- break;
- }
- token = convertUnicode(current, next1, next2, next3).uc;
- shift(3);
- if (!isIdentStart(token)) {
- setDone(Bad);
- break;
- }
- record16(token);
- state = InIdentifier;
- break;
- case InIdentifierPartUnicodeEscape:
- if (!isHexDigit(current) || !isHexDigit(next1) || !isHexDigit(next2) || !isHexDigit(next3)) {
- setDone(Bad);
- break;
- }
- token = convertUnicode(current, next1, next2, next3).uc;
- shift(3);
- if (!isIdentPart(token)) {
- setDone(Bad);
- break;
- }
- record16(token);
- state = InIdentifier;
- break;
- default:
- ASSERT(!"Unhandled state in switch statement");
- }
-
- // move on to the next character
- if (!done)
- shift(1);
- if (state != Start && state != InSingleLineComment)
- atLineStart = false;
- }
-
- // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
- if ((state == Number || state == Octal || state == Hex) && isIdentStart(current))
- state = Bad;
-
- // terminate string
- m_buffer8.append('\0');
-
-#ifdef KJS_DEBUG_LEX
- fprintf(stderr, "line: %d ", lineNo());
- fprintf(stderr, "yytext (%x): ", m_buffer8[0]);
- fprintf(stderr, "%s ", buffer8.data());
-#endif
-
- double dval = 0;
- if (state == Number) {
- dval = kjs_strtod(m_buffer8.data(), 0L);
- } else if (state == Hex) { // scan hex numbers
- const char* p = m_buffer8.data() + 2;
- while (char c = *p++) {
- dval *= 16;
- dval += convertHex(c);
- }
-
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16);
-
- state = Number;
- } else if (state == Octal) { // scan octal number
- const char* p = m_buffer8.data() + 1;
- while (char c = *p++) {
- dval *= 8;
- dval += c - '0';
- }
-
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8);
-
- state = Number;
- }
-
-#ifdef KJS_DEBUG_LEX
- switch (state) {
- case Eof:
- printf("(EOF)\n");
- break;
- case Other:
- printf("(Other)\n");
- break;
- case Identifier:
- printf("(Identifier)/(Keyword)\n");
- break;
- case String:
- printf("(String)\n");
- break;
- case Number:
- printf("(Number)\n");
- break;
- default:
- printf("(unknown)");
- }
-#endif
-
- if (state != Identifier && eatNextIdentifier)
- eatNextIdentifier = false;
-
- restrKeyword = false;
- delimited = false;
- kjsyylloc.first_line = yylineno; // ???
- kjsyylloc.last_line = yylineno;
-
- switch (state) {
- case Eof:
- token = 0;
- break;
- case Other:
- if(token == '}' || token == ';') {
- delimited = true;
- }
- break;
- case IdentifierOrKeyword:
- if ((token = Lookup::find(&mainTable, m_buffer16.data(), m_buffer16.size())) < 0) {
- case Identifier:
- // Lookup for keyword failed, means this is an identifier
- // Apply anonymous-function hack below (eat the identifier)
- if (eatNextIdentifier) {
- eatNextIdentifier = false;
- token = lex();
- break;
- }
- kjsyylval.ident = makeIdentifier(m_buffer16);
- token = IDENT;
- break;
- }
-
- eatNextIdentifier = false;
- // Hack for "f = function somename() { ... }", too hard to get into the grammar
- if (token == FUNCTION && lastToken == '=' )
- eatNextIdentifier = true;
-
- if (token == CONTINUE || token == BREAK ||
- token == RETURN || token == THROW)
- restrKeyword = true;
- break;
- case String:
- kjsyylval.string = makeUString(m_buffer16);
- token = STRING;
- break;
- case Number:
- kjsyylval.doubleValue = dval;
- token = NUMBER;
- break;
- case Bad:
-#ifdef KJS_DEBUG_LEX
- fprintf(stderr, "yylex: ERROR.\n");
-#endif
- error = true;
- return -1;
- default:
- ASSERT(!"unhandled numeration value in switch");
- error = true;
- return -1;
- }
- lastToken = token;
- return token;
-}
-
-bool Lexer::isWhiteSpace() const
-{
- return current == '\t' || current == 0x0b || current == 0x0c || isSeparatorSpace(current);
-}
-
-bool Lexer::isLineTerminator()
-{
- bool cr = (current == '\r');
- bool lf = (current == '\n');
- if (cr)
- skipLF = true;
- else if (lf)
- skipCR = true;
- return cr || lf || current == 0x2028 || current == 0x2029;
-}
-
-bool Lexer::isIdentStart(int c)
-{
- return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other))
- || c == '$' || c == '_';
-}
-
-bool Lexer::isIdentPart(int c)
-{
- return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
- | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector))
- || c == '$' || c == '_';
-}
-
-static bool isDecimalDigit(int c)
-{
- return (c >= '0' && c <= '9');
-}
-
-bool Lexer::isHexDigit(int c)
-{
- return (c >= '0' && c <= '9' ||
- c >= 'a' && c <= 'f' ||
- c >= 'A' && c <= 'F');
-}
-
-bool Lexer::isOctalDigit(int c)
-{
- return (c >= '0' && c <= '7');
-}
-
-int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4)
-{
- if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
- shift(4);
- return URSHIFTEQUAL;
- } else if (c1 == '=' && c2 == '=' && c3 == '=') {
- shift(3);
- return STREQ;
- } else if (c1 == '!' && c2 == '=' && c3 == '=') {
- shift(3);
- return STRNEQ;
- } else if (c1 == '>' && c2 == '>' && c3 == '>') {
- shift(3);
- return URSHIFT;
- } else if (c1 == '<' && c2 == '<' && c3 == '=') {
- shift(3);
- return LSHIFTEQUAL;
- } else if (c1 == '>' && c2 == '>' && c3 == '=') {
- shift(3);
- return RSHIFTEQUAL;
- } else if (c1 == '<' && c2 == '=') {
- shift(2);
- return LE;
- } else if (c1 == '>' && c2 == '=') {
- shift(2);
- return GE;
- } else if (c1 == '!' && c2 == '=') {
- shift(2);
- return NE;
- } else if (c1 == '+' && c2 == '+') {
- shift(2);
- if (terminator)
- return AUTOPLUSPLUS;
- else
- return PLUSPLUS;
- } else if (c1 == '-' && c2 == '-') {
- shift(2);
- if (terminator)
- return AUTOMINUSMINUS;
- else
- return MINUSMINUS;
- } else if (c1 == '=' && c2 == '=') {
- shift(2);
- return EQEQ;
- } else if (c1 == '+' && c2 == '=') {
- shift(2);
- return PLUSEQUAL;
- } else if (c1 == '-' && c2 == '=') {
- shift(2);
- return MINUSEQUAL;
- } else if (c1 == '*' && c2 == '=') {
- shift(2);
- return MULTEQUAL;
- } else if (c1 == '/' && c2 == '=') {
- shift(2);
- return DIVEQUAL;
- } else if (c1 == '&' && c2 == '=') {
- shift(2);
- return ANDEQUAL;
- } else if (c1 == '^' && c2 == '=') {
- shift(2);
- return XOREQUAL;
- } else if (c1 == '%' && c2 == '=') {
- shift(2);
- return MODEQUAL;
- } else if (c1 == '|' && c2 == '=') {
- shift(2);
- return OREQUAL;
- } else if (c1 == '<' && c2 == '<') {
- shift(2);
- return LSHIFT;
- } else if (c1 == '>' && c2 == '>') {
- shift(2);
- return RSHIFT;
- } else if (c1 == '&' && c2 == '&') {
- shift(2);
- return AND;
- } else if (c1 == '|' && c2 == '|') {
- shift(2);
- return OR;
- }
-
- switch(c1) {
- case '=':
- case '>':
- case '<':
- case ',':
- case '!':
- case '~':
- case '?':
- case ':':
- case '.':
- case '+':
- case '-':
- case '*':
- case '/':
- case '&':
- case '|':
- case '^':
- case '%':
- case '(':
- case ')':
- case '[':
- case ']':
- case ';':
- shift(1);
- return static_cast<int>(c1);
- case '{':
- charPos = pos - 4;
- shift(1);
- return OPENBRACE;
- case '}':
- charPos = pos - 4;
- shift(1);
- return CLOSEBRACE;
- default:
- return -1;
- }
-}
-
-unsigned short Lexer::singleEscape(unsigned short c)
-{
- switch(c) {
- case 'b':
- return 0x08;
- case 't':
- return 0x09;
- case 'n':
- return 0x0A;
- case 'v':
- return 0x0B;
- case 'f':
- return 0x0C;
- case 'r':
- return 0x0D;
- case '"':
- return 0x22;
- case '\'':
- return 0x27;
- case '\\':
- return 0x5C;
- default:
- return c;
- }
-}
-
-unsigned short Lexer::convertOctal(int c1, int c2, int c3)
-{
- return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
-}
-
-unsigned char Lexer::convertHex(int c)
-{
- if (c >= '0' && c <= '9')
- return static_cast<unsigned char>(c - '0');
- if (c >= 'a' && c <= 'f')
- return static_cast<unsigned char>(c - 'a' + 10);
- return static_cast<unsigned char>(c - 'A' + 10);
-}
-
-unsigned char Lexer::convertHex(int c1, int c2)
-{
- return ((convertHex(c1) << 4) + convertHex(c2));
-}
-
-KJS::UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
-{
- return KJS::UChar((convertHex(c1) << 4) + convertHex(c2),
- (convertHex(c3) << 4) + convertHex(c4));
-}
-
-void Lexer::record8(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= 0xff);
- m_buffer8.append(static_cast<char>(c));
-}
-
-void Lexer::record16(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= USHRT_MAX);
- record16(UChar(static_cast<unsigned short>(c)));
-}
-
-void Lexer::record16(KJS::UChar c)
-{
- m_buffer16.append(c);
-}
-
-bool Lexer::scanRegExp()
-{
- m_buffer16.clear();
- bool lastWasEscape = false;
- bool inBrackets = false;
-
- while (1) {
- if (isLineTerminator() || current == -1)
- return false;
- else if (current != '/' || lastWasEscape == true || inBrackets == true)
- {
- // keep track of '[' and ']'
- if (!lastWasEscape) {
- if ( current == '[' && !inBrackets )
- inBrackets = true;
- if ( current == ']' && inBrackets )
- inBrackets = false;
- }
- record16(current);
- lastWasEscape =
- !lastWasEscape && (current == '\\');
- } else { // end of regexp
- m_pattern = UString(m_buffer16);
- m_buffer16.clear();
- shift(1);
- break;
- }
- shift(1);
- }
-
- while (isIdentPart(current)) {
- record16(current);
- shift(1);
- }
- m_flags = UString(m_buffer16);
-
- return true;
-}
-
-void Lexer::clear()
-{
- deleteAllValues(m_strings);
- Vector<UString*> newStrings;
- newStrings.reserveCapacity(initialStringTableCapacity);
- m_strings.swap(newStrings);
-
- deleteAllValues(m_identifiers);
- Vector<KJS::Identifier*> newIdentifiers;
- newIdentifiers.reserveCapacity(initialStringTableCapacity);
- m_identifiers.swap(newIdentifiers);
-
- Vector<char> newBuffer8;
- newBuffer8.reserveCapacity(initialReadBufferCapacity);
- m_buffer8.swap(newBuffer8);
-
- Vector<UChar> newBuffer16;
- newBuffer16.reserveCapacity(initialReadBufferCapacity);
- m_buffer16.swap(newBuffer16);
-
- m_pattern = 0;
- m_flags = 0;
-}
-
-Identifier* Lexer::makeIdentifier(const Vector<KJS::UChar>& buffer)
-{
- KJS::Identifier* identifier = new KJS::Identifier(buffer.data(), buffer.size());
- m_identifiers.append(identifier);
- return identifier;
-}
-
-UString* Lexer::makeUString(const Vector<KJS::UChar>& buffer)
-{
- UString* string = new UString(buffer);
- m_strings.append(string);
- return string;
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Lexer_h
-#define Lexer_h
-
-#include "SourceCode.h"
-#include "ustring.h"
-#include <wtf/Vector.h>
-
-namespace KJS {
-
- class Identifier;
- class RegExp;
-
- class Lexer : Noncopyable {
- public:
- void setCode(const SourceCode&);
- int lex();
-
- int lineNo() const { return yylineno; }
-
- bool prevTerminator() const { return terminator; }
-
- enum State { Start,
- IdentifierOrKeyword,
- Identifier,
- InIdentifierOrKeyword,
- InIdentifier,
- InIdentifierStartUnicodeEscapeStart,
- InIdentifierStartUnicodeEscape,
- InIdentifierPartUnicodeEscapeStart,
- InIdentifierPartUnicodeEscape,
- InSingleLineComment,
- InMultiLineComment,
- InNum,
- InNum0,
- InHex,
- InOctal,
- InDecimal,
- InExponentIndicator,
- InExponent,
- Hex,
- Octal,
- Number,
- String,
- Eof,
- InString,
- InEscapeSequence,
- InHexEscape,
- InUnicodeEscape,
- Other,
- Bad };
-
- bool scanRegExp();
- const UString& pattern() const { return m_pattern; }
- const UString& flags() const { return m_flags; }
-
- static unsigned char convertHex(int);
- static unsigned char convertHex(int c1, int c2);
- static UChar convertUnicode(int c1, int c2, int c3, int c4);
- static bool isIdentStart(int);
- static bool isIdentPart(int);
- static bool isHexDigit(int);
-
- bool sawError() const { return error; }
-
- void clear();
- SourceCode sourceCode(int openBrace, int closeBrace, int firstLine)
- {
- // The SourceCode constructor adds 1 to the line number to account for
- // all of the callers in WebCore that use zero-based line numbers, so
- // we regrettably subtract 1 here to deal with that.
- return SourceCode(m_source->provider(), m_source->startOffset() + openBrace + 1, m_source->startOffset() + closeBrace, firstLine - 1);
- }
-
- private:
- friend Lexer& lexer();
- Lexer();
-
- int yylineno;
- bool done;
- Vector<char> m_buffer8;
- Vector<UChar> m_buffer16;
- bool terminator;
- bool restrKeyword;
- // encountered delimiter like "'" and "}" on last run
- bool delimited;
- bool skipLF;
- bool skipCR;
- bool eatNextIdentifier;
- int stackToken;
- int lastToken;
-
- State state;
- void setDone(State);
- unsigned int pos;
- void shift(unsigned int p);
- void nextLine();
- int lookupKeyword(const char *);
-
- bool isWhiteSpace() const;
- bool isLineTerminator();
- static bool isOctalDigit(int);
-
- int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);
- static unsigned short singleEscape(unsigned short);
- static unsigned short convertOctal(int c1, int c2, int c3);
-
- void record8(int);
- void record16(int);
- void record16(UChar);
-
- KJS::Identifier* makeIdentifier(const Vector<UChar>& buffer);
- UString* makeUString(const Vector<UChar>& buffer);
-
- const SourceCode* m_source;
- const UChar* code;
- unsigned int length;
- int yycolumn;
- int atLineStart;
- bool error;
-
- // current and following unicode characters (int to allow for -1 for end-of-file marker)
- int current, next1, next2, next3;
-
- int m_currentOffset;
- int m_nextOffset1;
- int m_nextOffset2;
- int m_nextOffset3;
-
- Vector<UString*> m_strings;
- Vector<KJS::Identifier*> m_identifiers;
-
- UString m_pattern;
- UString m_flags;
- };
-
- Lexer& lexer(); // Returns the singletone JavaScript lexer.
-
-} // namespace KJS
-
-#endif // Lexer_h
+++ /dev/null
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "list.h"
-
-using std::min;
-
-namespace KJS {
-
-void List::getSlice(int startIndex, List& result) const
-{
- const_iterator start = min(begin() + startIndex, end());
- result.m_vector.appendRange(start, end());
-}
-
-List::ListSet& List::markSet()
-{
- static ListSet staticMarkSet;
- return staticMarkSet;
-}
-
-void List::markProtectedListsSlowCase()
-{
- ListSet::iterator end = markSet().end();
- for (ListSet::iterator it = markSet().begin(); it != end; ++it) {
- List* list = *it;
-
- iterator end2 = list->end();
- for (iterator it2 = list->begin(); it2 != end2; ++it2) {
- JSValue* v = *it2;
- if (!v->marked())
- v->mark();
- }
- }
-}
-
-void List::expandAndAppend(JSValue* v)
-{
- ASSERT(m_vector.size() == m_vector.capacity());
-
- // 4x growth would be excessive for a normal vector, but it's OK for Lists
- // because they're short-lived.
- m_vector.reserveCapacity(m_vector.capacity() * 4);
-
- // As long as our size stays within our Vector's inline
- // capacity, all our values are allocated on the stack, and
- // therefore don't need explicit marking. Once our size exceeds
- // our Vector's inline capacity, though, our values move to the
- // heap, where they do need explicit marking.
- if (!m_isInMarkSet) {
- markSet().add(this);
- m_isInMarkSet = true;
- }
-
- m_vector.uncheckedAppend(v);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_LIST_H
-#define KJS_LIST_H
-
-#include <kjs/value.h>
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-
- class JSValue;
- class List;
-
- class List : Noncopyable {
- private:
- typedef Vector<JSValue*, 8> VectorType;
- typedef HashSet<List*> ListSet;
-
- public:
- typedef VectorType::iterator iterator;
- typedef VectorType::const_iterator const_iterator;
-
- List()
- : m_isInMarkSet(false)
- {
- }
-
- ~List()
- {
- if (m_isInMarkSet)
- markSet().remove(this);
- }
-
- size_t size() const { return m_vector.size(); }
- bool isEmpty() const { return m_vector.isEmpty(); }
-
- JSValue* at(size_t i) const
- {
- if (i < m_vector.size())
- return m_vector.at(i);
- return jsUndefined();
- }
-
- JSValue* operator[](int i) const { return at(i); }
-
- void clear() { m_vector.clear(); }
-
- void append(JSValue* v)
- {
- if (m_vector.size() < m_vector.capacity())
- m_vector.uncheckedAppend(v);
- else
- // Putting the slow "expand and append" case all in one
- // function measurably improves the performance of the fast
- // "just append" case.
- expandAndAppend(v);
- }
-
- void getSlice(int startIndex, List& result) const;
-
- iterator begin() { return m_vector.begin(); }
- iterator end() { return m_vector.end(); }
-
- const_iterator begin() const { return m_vector.begin(); }
- const_iterator end() const { return m_vector.end(); }
-
- static void markProtectedLists()
- {
- if (!markSet().size())
- return;
- markProtectedListsSlowCase();
- }
-
- private:
- static ListSet& markSet();
- static void markProtectedListsSlowCase();
-
- void expandAndAppend(JSValue*);
-
- VectorType m_vector;
- bool m_isInMarkSet;
-
- private:
- // Prohibits new / delete, which would break GC.
- void* operator new(size_t);
- void operator delete(void*);
-
- void* operator new[](size_t);
- void operator delete[](void*);
-
- void* operator new(size_t, void*);
- void operator delete(void*, size_t);
- };
-
-} // namespace KJS
-
-#endif // KJS_LIST_H
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "lookup.h"
-
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-static inline bool keysMatch(const UChar* c, unsigned len, const char* s)
-{
- // FIXME: This can run off the end of |s| if |c| has a U+0000 character in it.
- const char* end = s + len;
- for (; s != end; c++, s++)
- if (c->uc != *s)
- return false;
- return *s == 0;
-}
-
-static inline const HashEntry* findEntry(const struct HashTable* table, unsigned int hash,
- const UChar* c, unsigned int len)
-{
- ASSERT(table->type == 3);
-
- const HashEntry* e = &table->entries[hash & table->hashSizeMask];
-
- if (!e->s)
- return 0;
-
- do {
- // compare strings
- if (keysMatch(c, len, e->s))
- return e;
-
- // try next bucket
- e = e->next;
- } while (e);
- return 0;
-}
-
-const HashEntry* Lookup::findEntry(const struct HashTable* table, const Identifier& s)
-{
- return KJS::findEntry(table, s.ustring().rep()->computedHash(), s.data(), s.size());
-}
-
-int Lookup::find(const struct HashTable *table, const UChar *c, unsigned int len)
-{
- const HashEntry *entry = KJS::findEntry(table, UString::Rep::computeHash(c, len), c, len);
- if (entry)
- return entry->value.intValue;
- return -1;
-}
-
-int Lookup::find(const struct HashTable* table, const Identifier& s)
-{
- const HashEntry* entry = KJS::findEntry(table, s.ustring().rep()->computedHash(), s.data(), s.size());
- if (entry)
- return entry->value.intValue;
- return -1;
-}
-
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJS_lookup_h
-#define KJS_lookup_h
-
-#include "ExecState.h"
-#include "function.h"
-#include "identifier.h"
-#include "JSGlobalObject.h"
-#include "object.h"
-#include <stdio.h>
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
- /**
- * An entry in a hash table.
- */
- struct HashEntry {
- /**
- * s is the key (e.g. a property name)
- */
- const char* s;
-
- /**
- * value is the result value (enum value for properties and a function pointer to a constructor factory for functions)
- */
- union {
- intptr_t intValue;
- PrototypeFunction::JSMemberFunction functionValue;
- } value;
-
- /**
- * attr is a set for flags (e.g. the property flags, see object.h)
- */
- unsigned char attr;
- /**
- * params is another number. For property hashtables, it is used to
- * denote the number of argument of the function
- */
- short int params;
- /**
- * next is the pointer to the next entry for the same hash value
- */
- const HashEntry* next;
- };
-
- /**
- * A hash table
- * Usually the hashtable is generated by the create_hash_table script, from a .table file.
- *
- * The implementation uses an array of entries, "size" is the total size of that array.
- * The entries between 0 and hashSize-1 are the entry points
- * for each hash value, and the entries between hashSize and size-1
- * are the overflow entries for the hash values that need one.
- * The "next" pointer of the entry links entry points to overflow entries,
- * and links overflow entries between them.
- */
- struct HashTable {
- /**
- * type is a version number. Currently always 2
- */
- int type;
- /**
- * size is the total number of entries in the hashtable, including the null entries,
- * i.e. the size of the "entries" array.
- * Used to iterate over all entries in the table
- */
- int size;
- /**
- * pointer to the array of entries
- * Mind that some entries in the array are null (0,0,0,0).
- */
- const HashEntry* entries;
- /**
- * the maximum value for the hash minus 1. Always smaller than size.
- */
- int hashSizeMask;
- };
-
- /**
- * @short Fast keyword lookup.
- */
- class Lookup {
- public:
- /**
- * Find an entry in the table, and return its value (i.e. the value field of HashEntry)
- */
- static int find(const struct HashTable*, const Identifier&);
- static int find(const struct HashTable*, const UChar*, unsigned int len);
-
- /**
- * Find an entry in the table, and return the entry
- * This variant gives access to the other attributes of the entry,
- * especially the attr field.
- */
- static const HashEntry* findEntry(const struct HashTable*, const Identifier&);
-
- };
-
- class ExecState;
- class UString;
- /**
- * @internal
- * Helper for getStaticFunctionSlot and getStaticPropertySlot
- */
- inline JSValue* staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
- {
- // Look for cached value in dynamic map of properties (in JSObject)
- JSObject* thisObj = slot.slotBase();
- JSValue* cachedVal = thisObj->getDirect(propertyName);
- if (cachedVal)
- return cachedVal;
-
- const HashEntry* entry = slot.staticEntry();
- JSValue* val = new PrototypeFunction(exec, entry->params, propertyName, entry->value.functionValue);
- thisObj->putDirect(propertyName, val, entry->attr);
- return val;
- }
-
- /**
- * @internal
- * Helper for getStaticValueSlot and getStaticPropertySlot
- */
- template <class ThisImp>
- inline JSValue* staticValueGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
- {
- ThisImp* thisObj = static_cast<ThisImp*>(slot.slotBase());
- const HashEntry* entry = slot.staticEntry();
- return thisObj->getValueProperty(exec, entry->value.intValue);
- }
-
- /**
- * Helper method for property lookups
- *
- * This method does it all (looking in the hashtable, checking for function
- * overrides, creating the function or retrieving from cache, calling
- * getValueProperty in case of a non-function property, forwarding to parent if
- * unknown property).
- *
- * Template arguments:
- * @param FuncImp the class which implements this object's functions
- * @param ThisImp the class of "this". It must implement the getValueProperty(exec,token) method,
- * for non-function properties.
- * @param ParentImp the class of the parent, to propagate the lookup.
- *
- * Method arguments:
- * @param exec execution state, as usual
- * @param propertyName the property we're looking for
- * @param table the static hashtable for this class
- * @param thisObj "this"
- */
- template <class ThisImp, class ParentImp>
- inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table,
- ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
-
- if (entry->attr & Function)
- slot.setStaticEntry(thisObj, entry, staticFunctionGetter);
- else
- slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
-
- return true;
- }
-
- /**
- * Simplified version of getStaticPropertySlot in case there are only functions.
- * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
- * a dummy getValueProperty.
- */
- template <class ParentImp>
- inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table,
- JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
-
- ASSERT(entry->attr & Function);
-
- slot.setStaticEntry(thisObj, entry, staticFunctionGetter);
- return true;
- }
-
- /**
- * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
- * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
- */
- template <class ThisImp, class ParentImp>
- inline bool getStaticValueSlot(ExecState* exec, const HashTable* table,
- ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
-
- ASSERT(!(entry->attr & Function));
-
- slot.setStaticEntry(thisObj, entry, staticValueGetter<ThisImp>);
- return true;
- }
-
- /**
- * This one is for "put".
- * It looks up a hash entry for the property to be set. If an entry
- * is found it sets the value and returns true, else it returns false.
- */
- template <class ThisImp>
- inline bool lookupPut(ExecState* exec, const Identifier& propertyName,
- JSValue* value, int attr,
- const HashTable* table, ThisImp* thisObj)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry)
- return false;
-
- if (entry->attr & Function) // function: put as override property
- thisObj->JSObject::put(exec, propertyName, value, attr);
- else if (!(entry->attr & ReadOnly))
- thisObj->putValueProperty(exec, entry->value.intValue, value, attr);
-
- return true;
- }
-
- /**
- * This one is for "put".
- * It calls lookupPut<ThisImp>() to set the value. If that call
- * returns false (meaning no entry in the hash table was found),
- * then it calls put() on the ParentImp class.
- */
- template <class ThisImp, class ParentImp>
- inline void lookupPut(ExecState* exec, const Identifier& propertyName,
- JSValue* value, int attr,
- const HashTable* table, ThisImp* thisObj)
- {
- if (!lookupPut<ThisImp>(exec, propertyName, value, attr, table, thisObj))
- thisObj->ParentImp::put(exec, propertyName, value, attr); // not found: forward to parent
- }
-
- /**
- * This template method retrieves or create an object that is unique
- * (for a given global object) The first time this is called (for a given
- * property name), the Object will be constructed, and set as a property
- * of the global object. Later calls will simply retrieve that cached object.
- * Note that the object constructor must take 1 argument, exec.
- */
- template <class ClassCtor>
- inline JSObject* cacheGlobalObject(ExecState* exec, const Identifier& propertyName)
- {
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
- JSValue* obj = globalObject->getDirect(propertyName);
- if (obj) {
- ASSERT(obj->isObject());
- return static_cast<JSObject* >(obj);
- }
- JSObject* newObject = new ClassCtor(exec);
- globalObject->putDirect(propertyName, newObject, Internal | DontEnum);
- return newObject;
- }
-
-} // namespace
-
-/**
- * Helpers to define prototype objects (each of which simply implements
- * the functions for a type of objects).
- * Sorry for this not being very readable, but it actually saves much copy-n-paste.
- * ParentPrototype is not our base class, it's the object we use as fallback.
- * The reason for this is that there should only be ONE DOMNode.hasAttributes (e.g.),
- * not one in each derived class. So we link the (unique) prototypes between them.
- *
- * Using those macros is very simple: define the hashtable (e.g. "DOMNodePrototypeTable"), then
- * KJS_DEFINE_PROTOTYPE(DOMNodePrototype)
- * KJS_IMPLEMENT_PROTOTYPE("DOMNode", DOMNodePrototype, DOMNodePrototypeFunction)
- * and use DOMNodePrototype::self(exec) as prototype in the DOMNode constructor.
- * If the prototype has a "parent prototype", e.g. DOMElementPrototype falls back on DOMNodePrototype,
- * then the first line will use KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE, with DOMNodePrototype as the second argument.
- */
-
-// These macros assume that a prototype's only properties are functions
-#define KJS_DEFINE_PROTOTYPE(ClassPrototype) \
- class ClassPrototype : public KJS::JSObject { \
- public: \
- static KJS::JSObject* self(KJS::ExecState* exec); \
- virtual const KJS::ClassInfo* classInfo() const { return &info; } \
- static const KJS::ClassInfo info; \
- bool getOwnPropertySlot(KJS::ExecState* , const KJS::Identifier&, KJS::PropertySlot&); \
- ClassPrototype(KJS::ExecState* exec) \
- : KJS::JSObject(exec->lexicalGlobalObject()->objectPrototype()) { } \
- \
- };
-
-#define KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(ClassPrototype, ClassPrototypePrototype) \
- class ClassPrototype : public KJS::JSObject { \
- public: \
- static KJS::JSObject* self(KJS::ExecState* exec); \
- virtual const KJS::ClassInfo* classInfo() const { return &info; } \
- static const KJS::ClassInfo info; \
- bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&); \
- ClassPrototype(KJS::ExecState* exec) \
- : KJS::JSObject(ClassPrototypePrototype::self(exec)) { } \
- \
- };
-
-#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassPrototype) \
- const ClassInfo ClassPrototype::info = { ClassName"Prototype", 0, &ClassPrototype##Table }; \
- JSObject* ClassPrototype::self(ExecState* exec) \
- { \
- static Identifier* prototypeIdentifier = new Identifier("[[" ClassName ".prototype]]"); \
- return KJS::cacheGlobalObject<ClassPrototype>(exec, *prototypeIdentifier); \
- } \
- bool ClassPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) \
- { \
- return getStaticFunctionSlot<JSObject>(exec, &ClassPrototype##Table, this, propertyName, slot); \
- }
-
-#endif // KJS_lookup_h
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "math_object.h"
-#include "math_object.lut.h"
-
-#include "operations.h"
-#include <time.h>
-#include <wtf/Assertions.h>
-#include <wtf/MathExtras.h>
-
-namespace KJS {
-
-// ------------------------------ MathObjectImp --------------------------------
-
-const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable };
-
-/* Source for math_object.lut.h
-@begin mathTable 21
- E MathObjectImp::Euler DontEnum|DontDelete|ReadOnly
- LN2 MathObjectImp::Ln2 DontEnum|DontDelete|ReadOnly
- LN10 MathObjectImp::Ln10 DontEnum|DontDelete|ReadOnly
- LOG2E MathObjectImp::Log2E DontEnum|DontDelete|ReadOnly
- LOG10E MathObjectImp::Log10E DontEnum|DontDelete|ReadOnly
- PI MathObjectImp::Pi DontEnum|DontDelete|ReadOnly
- SQRT1_2 MathObjectImp::Sqrt1_2 DontEnum|DontDelete|ReadOnly
- SQRT2 MathObjectImp::Sqrt2 DontEnum|DontDelete|ReadOnly
- abs mathProtoFuncAbs DontEnum|Function 1
- acos mathProtoFuncACos DontEnum|Function 1
- asin mathProtoFuncASin DontEnum|Function 1
- atan mathProtoFuncATan DontEnum|Function 1
- atan2 mathProtoFuncATan2 DontEnum|Function 2
- ceil mathProtoFuncCeil DontEnum|Function 1
- cos mathProtoFuncCos DontEnum|Function 1
- exp mathProtoFuncExp DontEnum|Function 1
- floor mathProtoFuncFloor DontEnum|Function 1
- log mathProtoFuncLog DontEnum|Function 1
- max mathProtoFuncMax DontEnum|Function 2
- min mathProtoFuncMin DontEnum|Function 2
- pow mathProtoFuncPow DontEnum|Function 2
- random mathProtoFuncRandom DontEnum|Function 0
- round mathProtoFuncRound DontEnum|Function 1
- sin mathProtoFuncSin DontEnum|Function 1
- sqrt mathProtoFuncSqrt DontEnum|Function 1
- tan mathProtoFuncTan DontEnum|Function 1
-@end
-*/
-
-MathObjectImp::MathObjectImp(ExecState*, ObjectPrototype* objectPrototype)
- : JSObject(objectPrototype)
-{
-}
-
-// ECMA 15.8
-
-bool MathObjectImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
-{
- return getStaticPropertySlot<MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
-}
-
-JSValue* MathObjectImp::getValueProperty(ExecState*, int token) const
-{
- switch (token) {
- case Euler:
- return jsNumber(exp(1.0));
- case Ln2:
- return jsNumber(log(2.0));
- case Ln10:
- return jsNumber(log(10.0));
- case Log2E:
- return jsNumber(1.0 / log(2.0));
- case Log10E:
- return jsNumber(1.0 / log(10.0));
- case Pi:
- return jsNumber(piDouble);
- case Sqrt1_2:
- return jsNumber(sqrt(0.5));
- case Sqrt2:
- return jsNumber(sqrt(2.0));
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-// ------------------------------ Functions --------------------------------
-
-JSValue* mathProtoFuncAbs(ExecState* exec, JSObject*, const List& args)
-{
- double arg = args[0]->toNumber(exec);
- return signbit(arg) ? jsNumber(-arg) : jsNumber(arg);
-}
-
-JSValue* mathProtoFuncACos(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(acos(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncASin(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(asin(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncATan(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(atan(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncATan2(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(atan2(args[0]->toNumber(exec), args[1]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncCeil(ExecState* exec, JSObject*, const List& args)
-{
- double arg = args[0]->toNumber(exec);
- if (signbit(arg) && arg > -1.0)
- return jsNumber(-0.0);
- return jsNumber(ceil(arg));
-}
-
-JSValue* mathProtoFuncCos(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(cos(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncExp(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(exp(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncFloor(ExecState* exec, JSObject*, const List& args)
-{
- double arg = args[0]->toNumber(exec);
- if (signbit(arg) && arg == 0.0)
- return jsNumber(-0.0);
- return jsNumber(floor(arg));
-}
-
-JSValue* mathProtoFuncLog(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(log(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncMax(ExecState* exec, JSObject*, const List& args)
-{
- unsigned argsCount = args.size();
- double result = -Inf;
- for (unsigned k = 0; k < argsCount; ++k) {
- double val = args[k]->toNumber(exec);
- if (isnan(val)) {
- result = NaN;
- break;
- }
- if (val > result || (val == 0 && result == 0 && !signbit(val)))
- result = val;
- }
- return jsNumber(result);
-}
-
-JSValue* mathProtoFuncMin(ExecState* exec, JSObject*, const List& args)
-{
- unsigned argsCount = args.size();
- double result = +Inf;
- for (unsigned k = 0; k < argsCount; ++k) {
- double val = args[k]->toNumber(exec);
- if (isnan(val)) {
- result = NaN;
- break;
- }
- if (val < result || (val == 0 && result == 0 && signbit(val)))
- result = val;
- }
- return jsNumber(result);
-}
-
-JSValue* mathProtoFuncPow(ExecState* exec, JSObject*, const List& args)
-{
- // ECMA 15.8.2.1.13
-
- double arg = args[0]->toNumber(exec);
- double arg2 = args[1]->toNumber(exec);
-
- if (isnan(arg2))
- return jsNumber(NaN);
- if (isinf(arg2) && fabs(arg) == 1)
- return jsNumber(NaN);
- return jsNumber(pow(arg, arg2));
-}
-
-static bool didInitRandom;
-
-JSValue* mathProtoFuncRandom(ExecState*, JSObject*, const List&)
-{
- if (!didInitRandom) {
- wtf_random_init();
- didInitRandom = true;
- }
- return jsNumber(wtf_random());
-}
-
-JSValue* mathProtoFuncRound(ExecState* exec, JSObject*, const List& args)
-{
- double arg = args[0]->toNumber(exec);
- if (signbit(arg) && arg >= -0.5)
- return jsNumber(-0.0);
- return jsNumber(floor(arg + 0.5));
-}
-
-JSValue* mathProtoFuncSin(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(sin(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncSqrt(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(sqrt(args[0]->toNumber(exec)));
-}
-
-JSValue* mathProtoFuncTan(ExecState* exec, JSObject*, const List& args)
-{
- return jsNumber(tan(args[0]->toNumber(exec)));
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef MATH_OBJECT_H_
-#define MATH_OBJECT_H_
-
-#include "function_object.h"
-#include "lookup.h"
-
-namespace KJS {
-
- class MathObjectImp : public JSObject {
- public:
- MathObjectImp(ExecState*, ObjectPrototype*);
-
- bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- JSValue* getValueProperty(ExecState*, int token) const;
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2 };
- };
-
- // Functions
- JSValue* mathProtoFuncAbs(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncACos(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncASin(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncATan(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncATan2(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncCeil(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncCos(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncExp(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncFloor(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncLog(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncMax(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncMin(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncPow(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncRandom(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncRound(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncSin(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncSqrt(ExecState*, JSObject*, const List&);
- JSValue* mathProtoFuncTan(ExecState*, JSObject*, const List&);
-
-} // namespace KJS
-
-#endif // MATH_OBJECT_H_
+++ /dev/null
-/*
-* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
-* Copyright (C) 2001 Peter Kelly (pmk@post.com)
-* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
-* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
-* Copyright (C) 2007 Maks Orlovich
-* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Library General Public
-* License as published by the Free Software Foundation; either
-* version 2 of the License, or (at your option) any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Library General Public License for more details.
-*
-* You should have received a copy of the GNU Library General Public License
-* along with this library; see the file COPYING.LIB. If not, write to
-* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-* Boston, MA 02110-1301, USA.
-*
-*/
-
-#include "config.h"
-#include "nodes.h"
-
-#include "ExecState.h"
-#include "JSGlobalObject.h"
-#include "Parser.h"
-#include "PropertyNameArray.h"
-#include "array_object.h"
-#include "debugger.h"
-#include "function_object.h"
-#include "lexer.h"
-#include "operations.h"
-#include "regexp_object.h"
-#include <math.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashSet.h>
-#include <wtf/MathExtras.h>
-
-namespace KJS {
-
-class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
-public:
- FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
-};
-
-#define KJS_CHECKEXCEPTION \
-if (exec->hadException()) \
- return rethrowException(exec);
-
-#define KJS_CHECKEXCEPTIONVALUE \
-if (exec->hadException()) { \
- handleException(exec); \
- return jsUndefined(); \
-}
-
-#define KJS_CHECKEXCEPTIONNUMBER \
-if (exec->hadException()) { \
- handleException(exec); \
- return 0; \
-}
-
-#define KJS_CHECKEXCEPTIONBOOLEAN \
-if (exec->hadException()) { \
- handleException(exec); \
- return false; \
-}
-
-#define KJS_CHECKEXCEPTIONVOID \
-if (exec->hadException()) { \
- handleException(exec); \
- return; \
-}
-
-#if !ASSERT_DISABLED
-static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
-{
- // Static lookup in EvalCode is impossible because variables aren't DontDelete.
- // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
- if (exec->codeType() != FunctionCode)
- return false;
-
- // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
- if (exec->variableObject() != exec->scopeChain().top())
- return false;
-
- // Static lookup is impossible if the symbol isn't statically declared.
- if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
- return false;
-
- return true;
-}
-#endif
-
-static inline bool isConstant(const LocalStorage& localStorage, size_t index)
-{
- ASSERT(index < localStorage.size());
- return localStorage[index].attributes & ReadOnly;
-}
-
-// ------------------------------ Node -----------------------------------------
-
-#ifndef NDEBUG
-#ifndef LOG_CHANNEL_PREFIX
-#define LOG_CHANNEL_PREFIX Log
-#endif
-static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
-
-struct ParserRefCountedCounter {
- static unsigned count;
- ParserRefCountedCounter()
- {
- if (count)
- LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
- }
-};
-unsigned ParserRefCountedCounter::count = 0;
-static ParserRefCountedCounter parserRefCountedCounter;
-#endif
-
-static HashSet<ParserRefCounted*>* newTrackedObjects;
-static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
-
-ParserRefCounted::ParserRefCounted()
-{
-#ifndef NDEBUG
- ++ParserRefCountedCounter::count;
-#endif
- if (!newTrackedObjects)
- newTrackedObjects = new HashSet<ParserRefCounted*>;
- newTrackedObjects->add(this);
- ASSERT(newTrackedObjects->contains(this));
-}
-
-ParserRefCounted::~ParserRefCounted()
-{
-#ifndef NDEBUG
- --ParserRefCountedCounter::count;
-#endif
-}
-
-void ParserRefCounted::ref()
-{
- // bumping from 0 to 1 is just removing from the new nodes set
- if (newTrackedObjects) {
- HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
- if (it != newTrackedObjects->end()) {
- newTrackedObjects->remove(it);
- ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
- return;
- }
- }
-
- ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
-
- if (!trackedObjectExtraRefCounts)
- trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
- trackedObjectExtraRefCounts->add(this);
-}
-
-void ParserRefCounted::deref()
-{
- ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
-
- if (!trackedObjectExtraRefCounts) {
- delete this;
- return;
- }
-
- HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
- if (it == trackedObjectExtraRefCounts->end())
- delete this;
- else
- trackedObjectExtraRefCounts->remove(it);
-}
-
-unsigned ParserRefCounted::refcount()
-{
- if (newTrackedObjects && newTrackedObjects->contains(this)) {
- ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
- return 0;
- }
-
- ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
-
- if (!trackedObjectExtraRefCounts)
- return 1;
-
- return 1 + trackedObjectExtraRefCounts->count(this);
-}
-
-void ParserRefCounted::deleteNewObjects()
-{
- if (!newTrackedObjects)
- return;
-
-#ifndef NDEBUG
- HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
- for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
- ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
-#endif
- deleteAllValues(*newTrackedObjects);
- delete newTrackedObjects;
- newTrackedObjects = 0;
-}
-
-Node::Node()
- : m_expectedReturnType(ObjectType)
-{
- m_line = lexer().lineNo();
-}
-
-Node::Node(JSType expectedReturn)
- : m_expectedReturnType(expectedReturn)
-{
- m_line = lexer().lineNo();
-}
-
-double ExpressionNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* value = evaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return value->toNumber(exec);
-}
-
-bool ExpressionNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* value = evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return value->toBoolean(exec);
-}
-
-int32_t ExpressionNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* value = evaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return value->toInt32(exec);
-}
-
-uint32_t ExpressionNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* value = evaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return value->toUInt32(exec);
-}
-
-static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
-static void substitute(UString& string, const UString& substring)
-{
- int position = string.find("%s");
- ASSERT(position != -1);
- UString newString = string.substr(0, position);
- newString.append(substring);
- newString.append(string.substr(position + 2));
- string = newString;
-}
-
-static inline int currentSourceID(ExecState* exec) KJS_FAST_CALL;
-static inline int currentSourceID(ExecState* exec)
-{
- return exec->scopeNode()->sourceID();
-}
-
-static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
-static inline const UString& currentSourceURL(ExecState* exec)
-{
- return exec->scopeNode()->sourceURL();
-}
-
-JSValue* Node::setInterruptedCompletion(ExecState* exec)
-{
- return exec->setInterruptedCompletion(Error::create(exec, TimeoutError, "JavaScript execution exceeded timeout.", lineNo(), currentSourceID(exec), currentSourceURL(exec)));
-}
-
-JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg)
-{
- return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceID(exec), currentSourceURL(exec)));
-}
-
-JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
-{
- UString message = msg;
- substitute(message, ident.ustring());
- return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec)));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg)
-{
- return KJS::throwError(exec, e, msg, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
-{
- UString message = msg;
- substitute(message, string);
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
-{
- UString message = msg;
- substitute(message, v->toString(exec));
- substitute(message, expr->toString());
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label)
-{
- UString message = msg;
- substitute(message, label.ustring());
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
-{
- UString message = msg;
- substitute(message, v->toString(exec));
- substitute(message, e1->toString());
- substitute(message, e2->toString());
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
-{
- UString message = msg;
- substitute(message, v->toString(exec));
- substitute(message, expr->toString());
- substitute(message, label.ustring());
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
-{
- UString message = msg;
- substitute(message, v->toString(exec));
- substitute(message, label.ustring());
- return KJS::throwError(exec, e, message, lineNo(), currentSourceID(exec), currentSourceURL(exec));
-}
-
-JSValue* Node::throwUndefinedVariableError(ExecState* exec, const Identifier& ident)
-{
- return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
-}
-
-void Node::handleException(ExecState* exec)
-{
- handleException(exec, exec->exception());
-}
-
-void Node::handleException(ExecState* exec, JSValue* exceptionValue)
-{
- if (exceptionValue->isObject()) {
- JSObject* exception = static_cast<JSObject*>(exceptionValue);
- if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
- exception->put(exec, "line", jsNumber(m_line));
- exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
- }
- }
- Debugger* dbg = exec->dynamicGlobalObject()->debugger();
- if (dbg && !dbg->hasHandledException(exec, exceptionValue)) {
- bool cont = dbg->exception(exec, currentSourceID(exec), m_line, exceptionValue);
- if (!cont)
- dbg->imp()->abort();
- }
-}
-
-NEVER_INLINE JSValue* Node::rethrowException(ExecState* exec)
-{
- JSValue* exception = exec->exception();
- exec->clearException();
- handleException(exec, exception);
- return exec->setThrowCompletion(exception);
-}
-
-// ------------------------------ StatementNode --------------------------------
-
-StatementNode::StatementNode()
- : m_lastLine(-1)
-{
- m_line = -1;
-}
-
-void StatementNode::setLoc(int firstLine, int lastLine)
-{
- m_line = firstLine;
- m_lastLine = lastLine;
-}
-
-// ------------------------------ SourceElements --------------------------------
-
-void SourceElements::append(PassRefPtr<StatementNode> statement)
-{
- if (statement->isEmptyStatement())
- return;
-
- if (Debugger::debuggersPresent)
- m_statements.append(new BreakpointCheckStatement(statement));
- else
- m_statements.append(statement);
-}
-
-// ------------------------------ BreakpointCheckStatement --------------------------------
-
-BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
- : m_statement(statement)
-{
- ASSERT(m_statement);
-}
-
-JSValue* BreakpointCheckStatement::execute(ExecState* exec)
-{
- if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
- if (!debugger->atStatement(exec, currentSourceID(exec), m_statement->firstLine(), m_statement->lastLine()))
- return exec->setNormalCompletion();
- return m_statement->execute(exec);
-}
-
-void BreakpointCheckStatement::streamTo(SourceStream& stream)
-{
- m_statement->streamTo(stream);
-}
-
-void BreakpointCheckStatement::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
-}
-
-// ------------------------------ NullNode -------------------------------------
-
-JSValue* NullNode::evaluate(ExecState* )
-{
- return jsNull();
-}
-
-// ------------------------------ FalseNode ----------------------------------
-
-JSValue* FalseNode::evaluate(ExecState*)
-{
- return jsBoolean(false);
-}
-
-// ------------------------------ TrueNode ----------------------------------
-
-JSValue* TrueNode::evaluate(ExecState*)
-{
- return jsBoolean(true);
-}
-
-// ------------------------------ NumberNode -----------------------------------
-
-JSValue* NumberNode::evaluate(ExecState*)
-{
- // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
- return jsNumberCell(m_double);
-}
-
-double NumberNode::evaluateToNumber(ExecState*)
-{
- return m_double;
-}
-
-bool NumberNode::evaluateToBoolean(ExecState*)
-{
- return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
-}
-
-int32_t NumberNode::evaluateToInt32(ExecState*)
-{
- return JSValue::toInt32(m_double);
-}
-
-uint32_t NumberNode::evaluateToUInt32(ExecState*)
-{
- return JSValue::toUInt32(m_double);
-}
-
-// ------------------------------ ImmediateNumberNode -----------------------------------
-
-JSValue* ImmediateNumberNode::evaluate(ExecState*)
-{
- return m_value;
-}
-
-int32_t ImmediateNumberNode::evaluateToInt32(ExecState*)
-{
- return JSImmediate::getTruncatedInt32(m_value);
-}
-
-uint32_t ImmediateNumberNode::evaluateToUInt32(ExecState*)
-{
- uint32_t i;
- if (JSImmediate::getTruncatedUInt32(m_value, i))
- return i;
- bool ok;
- return JSValue::toUInt32SlowCase(m_double, ok);
-}
-
-// ------------------------------ StringNode -----------------------------------
-
-JSValue* StringNode::evaluate(ExecState*)
-{
- return jsOwnedString(m_value);
-}
-
-double StringNode::evaluateToNumber(ExecState*)
-{
- return m_value.toDouble();
-}
-
-bool StringNode::evaluateToBoolean(ExecState*)
-{
- return !m_value.isEmpty();
-}
-
-// ------------------------------ RegExpNode -----------------------------------
-
-JSValue* RegExpNode::evaluate(ExecState* exec)
-{
- return exec->lexicalGlobalObject()->regExpConstructor()->createRegExpImp(exec, m_regExp);
-}
-
-// ------------------------------ ThisNode -------------------------------------
-
-// ECMA 11.1.1
-JSValue* ThisNode::evaluate(ExecState* exec)
-{
- return exec->thisValue();
-}
-
-// ------------------------------ ResolveNode ----------------------------------
-
-// ECMA 11.1.2 & 10.1.4
-JSValue* ResolveNode::inlineEvaluate(ExecState* exec)
-{
- // Check for missed optimization opportunity.
- ASSERT(!canSkipLookup(exec, m_ident));
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- do {
- JSObject* o = *iter;
-
- if (o->getPropertySlot(exec, m_ident, slot))
- return slot.getValue(exec, o, m_ident);
-
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-JSValue* ResolveNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double ResolveNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool ResolveNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t ResolveNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t ResolveNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-void ResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker())
- new (this) LocalVarAccessNode(index);
-}
-
-JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- return exec->localStorage()[m_index].value;
-}
-
-JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluate(exec)->toNumber(exec);
-}
-
-bool LocalVarAccessNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluate(exec)->toBoolean(exec);
-}
-
-int32_t LocalVarAccessNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluate(exec)->toInt32(exec);
-}
-
-uint32_t LocalVarAccessNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluate(exec)->toUInt32(exec);
-}
-
-// ------------------------------ ElementNode ----------------------------------
-
-void ElementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_next)
- nodeStack.append(m_next.get());
- ASSERT(m_node);
- nodeStack.append(m_node.get());
-}
-
-// ECMA 11.1.4
-JSValue* ElementNode::evaluate(ExecState* exec)
-{
- JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
- int length = 0;
- for (ElementNode* n = this; n; n = n->m_next.get()) {
- JSValue* val = n->m_node->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- length += n->m_elision;
- array->put(exec, length++, val);
- }
- return array;
-}
-
-// ------------------------------ ArrayNode ------------------------------------
-
-void ArrayNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_element)
- nodeStack.append(m_element.get());
-}
-
-// ECMA 11.1.4
-JSValue* ArrayNode::evaluate(ExecState* exec)
-{
- JSObject* array;
- int length;
-
- if (m_element) {
- array = static_cast<JSObject*>(m_element->evaluate(exec));
- KJS_CHECKEXCEPTIONVALUE
- length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
- } else {
- JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
- array = static_cast<JSObject*>(newArr);
- length = 0;
- }
-
- if (m_optional)
- array->put(exec, exec->propertyNames().length, jsNumber(m_elision + length));
-
- return array;
-}
-
-// ------------------------------ ObjectLiteralNode ----------------------------
-
-void ObjectLiteralNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_list)
- nodeStack.append(m_list.get());
-}
-
-// ECMA 11.1.5
-JSValue* ObjectLiteralNode::evaluate(ExecState* exec)
-{
- if (m_list)
- return m_list->evaluate(exec);
-
- return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
-}
-
-// ------------------------------ PropertyListNode -----------------------------
-
-void PropertyListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_next)
- nodeStack.append(m_next.get());
- nodeStack.append(m_node.get());
-}
-
-// ECMA 11.1.5
-JSValue* PropertyListNode::evaluate(ExecState* exec)
-{
- JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
-
- for (PropertyListNode* p = this; p; p = p->m_next.get()) {
- JSValue* v = p->m_node->m_assign->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- switch (p->m_node->m_type) {
- case PropertyNode::Getter:
- ASSERT(v->isObject());
- obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
- break;
- case PropertyNode::Setter:
- ASSERT(v->isObject());
- obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
- break;
- case PropertyNode::Constant:
- obj->put(exec, p->m_node->name(), v);
- break;
- }
- }
-
- return obj;
-}
-
-// ------------------------------ PropertyNode -----------------------------
-
-void PropertyNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_assign.get());
-}
-
-// ECMA 11.1.5
-JSValue* PropertyNode::evaluate(ExecState*)
-{
- ASSERT(false);
- return jsNull();
-}
-
-// ------------------------------ BracketAccessorNode --------------------------------
-
-void BracketAccessorNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-// ECMA 11.2.1a
-JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
-{
- JSValue* v1 = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* v2 = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* o = v1->toObject(exec);
- uint32_t i;
- if (v2->getUInt32(i))
- return o->get(exec, i);
- return o->get(exec, Identifier(v2->toString(exec)));
-}
-
-JSValue* BracketAccessorNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double BracketAccessorNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool BracketAccessorNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t BracketAccessorNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t BracketAccessorNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-// ------------------------------ DotAccessorNode --------------------------------
-
-void DotAccessorNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_base.get());
-}
-
-// ECMA 11.2.1b
-JSValue* DotAccessorNode::inlineEvaluate(ExecState* exec)
-{
- JSValue* v = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- return v->toObject(exec)->get(exec, m_ident);
-}
-
-JSValue* DotAccessorNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double DotAccessorNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool DotAccessorNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t DotAccessorNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t DotAccessorNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-// ------------------------------ ArgumentListNode -----------------------------
-
-void ArgumentListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_next)
- nodeStack.append(m_next.get());
- ASSERT(m_expr);
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.2.4
-void ArgumentListNode::evaluateList(ExecState* exec, List& list)
-{
- for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
- JSValue* v = n->m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVOID
- list.append(v);
- }
-}
-
-// ------------------------------ ArgumentsNode --------------------------------
-
-void ArgumentsNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_listNode)
- nodeStack.append(m_listNode.get());
-}
-
-// ------------------------------ NewExprNode ----------------------------------
-
-void NewExprNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_args)
- nodeStack.append(m_args.get());
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.2.2
-
-JSValue* NewExprNode::inlineEvaluate(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- List argList;
- if (m_args) {
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
- }
-
- if (!v->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
-
- JSObject* constr = static_cast<JSObject*>(v);
- if (!constr->implementsConstruct())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
-
- return constr->construct(exec, argList);
-}
-
-JSValue* NewExprNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double NewExprNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool NewExprNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t NewExprNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t NewExprNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-void FunctionCallValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_args.get());
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.2.3
-JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- if (!v->isObject()) {
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
- }
-
- JSObject* func = static_cast<JSObject*>(v);
-
- if (!func->implementsCall()) {
- return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
- }
-
- List argList;
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* thisObj = exec->dynamicGlobalObject();
-
- return func->call(exec, thisObj, argList);
-}
-
-void FunctionCallResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_args.get());
-
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker())
- new (this) LocalVarFunctionCallNode(index);
-}
-
-// ECMA 11.2.3
-JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
-{
- // Check for missed optimization opportunity.
- ASSERT(!canSkipLookup(exec, m_ident));
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot)) {
- JSValue* v = slot.getValue(exec, base, m_ident);
- KJS_CHECKEXCEPTIONVALUE
-
- if (!v->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
-
- JSObject* func = static_cast<JSObject*>(v);
-
- if (!func->implementsCall())
- return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
-
- List argList;
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* thisObj = base;
- // ECMA 11.2.3 says that in this situation the this value should be null.
- // However, section 10.2.3 says that in the case where the value provided
- // by the caller is null, the global object should be used. It also says
- // that the section does not apply to internal functions, but for simplicity
- // of implementation we use the global object anyway here. This guarantees
- // that in host objects you always get a valid object for this.
- if (thisObj->isActivationObject())
- thisObj = exec->dynamicGlobalObject();
-
- return func->call(exec, thisObj, argList);
- }
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-JSValue* FunctionCallResolveNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double FunctionCallResolveNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool FunctionCallResolveNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t FunctionCallResolveNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t FunctionCallResolveNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- JSValue* v = exec->localStorage()[m_index].value;
-
- if (!v->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
-
- JSObject* func = static_cast<JSObject*>(v);
- if (!func->implementsCall())
- return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
-
- List argList;
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
-
- return func->call(exec, exec->dynamicGlobalObject(), argList);
-}
-
-JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double LocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool LocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t LocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-void FunctionCallBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_args.get());
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-// ECMA 11.2.3
-JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseVal = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* subscriptVal = m_subscript->evaluate(exec);
-
- JSObject* baseObj = baseVal->toObject(exec);
- uint32_t i;
- PropertySlot slot;
-
- JSValue* funcVal;
- if (subscriptVal->getUInt32(i)) {
- if (baseObj->getPropertySlot(exec, i, slot))
- funcVal = slot.getValue(exec, baseObj, i);
- else
- funcVal = jsUndefined();
- } else {
- Identifier ident(subscriptVal->toString(exec));
- if (baseObj->getPropertySlot(exec, ident, slot))
- funcVal = baseObj->get(exec, ident);
- else
- funcVal = jsUndefined();
- }
-
- KJS_CHECKEXCEPTIONVALUE
-
- if (!funcVal->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());
-
- JSObject* func = static_cast<JSObject*>(funcVal);
-
- if (!func->implementsCall())
- return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());
-
- List argList;
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* thisObj = baseObj;
- ASSERT(thisObj);
- ASSERT(thisObj->isObject());
- ASSERT(!thisObj->isActivationObject());
-
- return func->call(exec, thisObj, argList);
-}
-
-static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
-static const char* dotExprNotAnObjectString()
-{
- return "Value %s (result of expression %s.%s) is not object.";
-}
-
-static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
-static const char* dotExprDoesNotAllowCallsString()
-{
- return "Object %s (result of expression %s.%s) does not allow calls.";
-}
-
-void FunctionCallDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_args.get());
- nodeStack.append(m_base.get());
-}
-
-// ECMA 11.2.3
-JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
-{
- JSValue* baseVal = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* baseObj = baseVal->toObject(exec);
- PropertySlot slot;
- JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- if (!funcVal->isObject())
- return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);
-
- JSObject* func = static_cast<JSObject*>(funcVal);
-
- if (!func->implementsCall())
- return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);
-
- List argList;
- m_args->evaluateList(exec, argList);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* thisObj = baseObj;
- ASSERT(thisObj);
- ASSERT(thisObj->isObject());
- ASSERT(!thisObj->isActivationObject());
-
- return func->call(exec, thisObj, argList);
-}
-
-JSValue* FunctionCallDotNode::evaluate(ExecState* exec)
-{
- return inlineEvaluate(exec);
-}
-
-double FunctionCallDotNode::evaluateToNumber(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toNumber(exec);
-}
-
-bool FunctionCallDotNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return v->toBoolean(exec);
-}
-
-int32_t FunctionCallDotNode::evaluateToInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toInt32(exec);
-}
-
-uint32_t FunctionCallDotNode::evaluateToUInt32(ExecState* exec)
-{
- JSValue* v = inlineEvaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return v->toUInt32(exec);
-}
-
-// ECMA 11.3
-
-// ------------------------------ PostfixResolveNode ----------------------------------
-
-// Increment
-void PostIncResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) PostIncConstNode(index);
- else
- new (this) PostIncLocalVarNode(index);
- }
-}
-
-JSValue* PostIncResolveNode::evaluate(ExecState* exec)
-{
- // Check for missed optimization opportunity.
- ASSERT(!canSkipLookup(exec, m_ident));
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- do {
- if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
- // If m_ident is 'arguments', the base->getPropertySlot() may cause
- // base (which must be an ActivationImp in such this case) to be torn
- // off from the activation stack, in which case we need to get it again
- // from the ScopeChainIterator.
-
- JSObject* base = *iter;
- JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
- base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
- return v;
- }
-
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-void PostIncResolveNode::optimizeForUnnecessaryResult()
-{
- new (this) PreIncResolveNode(PlacementNewAdopt);
-}
-
-JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- JSValue** slot = &exec->localStorage()[m_index].value;
- JSValue* v = (*slot)->toJSNumber(exec);
- *slot = jsNumber(v->toNumber(exec) + 1);
- return v;
-}
-
-void PostIncLocalVarNode::optimizeForUnnecessaryResult()
-{
- new (this) PreIncLocalVarNode(m_index);
-}
-
-// Decrement
-void PostDecResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) PostDecConstNode(index);
- else
- new (this) PostDecLocalVarNode(index);
- }
-}
-
-JSValue* PostDecResolveNode::evaluate(ExecState* exec)
-{
- // Check for missed optimization opportunity.
- ASSERT(!canSkipLookup(exec, m_ident));
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- do {
- if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
- // See the comment in PostIncResolveNode::evaluate().
-
- JSObject* base = *iter;
- JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
- base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
- return v;
- }
-
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-void PostDecResolveNode::optimizeForUnnecessaryResult()
-{
- new (this) PreDecResolveNode(PlacementNewAdopt);
-}
-
-JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- JSValue** slot = &exec->localStorage()[m_index].value;
- JSValue* v = (*slot)->toJSNumber(exec);
- *slot = jsNumber(v->toNumber(exec) - 1);
- return v;
-}
-
-double PostDecLocalVarNode::inlineEvaluateToNumber(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- JSValue** slot = &exec->localStorage()[m_index].value;
- double n = (*slot)->toNumber(exec);
- *slot = jsNumber(n - 1);
- return n;
-}
-
-double PostDecLocalVarNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-bool PostDecLocalVarNode::evaluateToBoolean(ExecState* exec)
-{
- double result = inlineEvaluateToNumber(exec);
- return result > 0.0 || 0.0 > result; // NaN produces false as well
-}
-
-int32_t PostDecLocalVarNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t PostDecLocalVarNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-void PostDecLocalVarNode::optimizeForUnnecessaryResult()
-{
- new (this) PreDecLocalVarNode(m_index);
-}
-
-// ------------------------------ PostfixBracketNode ----------------------------------
-
-void PostfixBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* PostIncBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));
-
- return v2;
- }
-
- Identifier propertyName(subscript->toString(exec));
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
- return v2;
-}
-
-JSValue* PostDecBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
- return v2;
- }
-
- Identifier propertyName(subscript->toString(exec));
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
- return v2;
-}
-
-// ------------------------------ PostfixDotNode ----------------------------------
-
-void PostfixDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_base.get());
-}
-
-JSValue* PostIncDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
- return v2;
-}
-
-JSValue* PostDecDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = v->toJSNumber(exec);
- base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
- return v2;
-}
-
-// ------------------------------ PostfixErrorNode -----------------------------------
-
-JSValue* PostfixErrorNode::evaluate(ExecState* exec)
-{
- throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
- m_operator == OpPlusPlus ? "++" : "--");
- handleException(exec);
- return jsUndefined();
-}
-
-// ------------------------------ DeleteResolveNode -----------------------------------
-
-void DeleteResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker())
- new (this) LocalVarDeleteNode();
-}
-
-// ECMA 11.4.1
-
-JSValue* DeleteResolveNode::evaluate(ExecState* exec)
-{
- // Check for missed optimization opportunity.
- ASSERT(!canSkipLookup(exec, m_ident));
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // We must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot))
- return jsBoolean(base->deleteProperty(exec, m_ident));
-
- ++iter;
- } while (iter != end);
-
- return jsBoolean(true);
-}
-
-JSValue* LocalVarDeleteNode::evaluate(ExecState*)
-{
- return jsBoolean(false);
-}
-
-// ------------------------------ DeleteBracketNode -----------------------------------
-
-void DeleteBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* DeleteBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex))
- return jsBoolean(base->deleteProperty(exec, propertyIndex));
-
- Identifier propertyName(subscript->toString(exec));
- return jsBoolean(base->deleteProperty(exec, propertyName));
-}
-
-// ------------------------------ DeleteDotNode -----------------------------------
-
-void DeleteDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_base.get());
-}
-
-JSValue* DeleteDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- JSObject* base = baseValue->toObject(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return jsBoolean(base->deleteProperty(exec, m_ident));
-}
-
-// ------------------------------ DeleteValueNode -----------------------------------
-
-void DeleteValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-JSValue* DeleteValueNode::evaluate(ExecState* exec)
-{
- m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- // delete on a non-location expression ignores the value and returns true
- return jsBoolean(true);
-}
-
-// ------------------------------ VoidNode -------------------------------------
-
-void VoidNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.4.2
-JSValue* VoidNode::evaluate(ExecState* exec)
-{
- m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return jsUndefined();
-}
-
-// ECMA 11.4.3
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-void TypeOfValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-static JSValue* typeStringForValue(JSValue* v) KJS_FAST_CALL;
-static JSValue* typeStringForValue(JSValue* v)
-{
- switch (v->type()) {
- case UndefinedType:
- return jsString("undefined");
- case NullType:
- return jsString("object");
- case BooleanType:
- return jsString("boolean");
- case NumberType:
- return jsString("number");
- case StringType:
- return jsString("string");
- default:
- if (v->isObject()) {
- // Return "undefined" for objects that should be treated
- // as null when doing comparisons.
- if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
- return jsString("undefined");
- else if (static_cast<JSObject*>(v)->implementsCall())
- return jsString("function");
- }
-
- return jsString("object");
- }
-}
-
-void TypeOfResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker())
- new (this) LocalVarTypeOfNode(index);
-}
-
-JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- return typeStringForValue(exec->localStorage()[m_index].value);
-}
-
-JSValue* TypeOfResolveNode::evaluate(ExecState* exec)
-{
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // We must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot)) {
- JSValue* v = slot.getValue(exec, base, m_ident);
- return typeStringForValue(v);
- }
-
- ++iter;
- } while (iter != end);
-
- return jsString("undefined");
-}
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-JSValue* TypeOfValueNode::evaluate(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return typeStringForValue(v);
-}
-
-// ECMA 11.4.4 and 11.4.5
-
-// ------------------------------ PrefixResolveNode ----------------------------------
-
-void PreIncResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) PreIncConstNode(index);
- else
- new (this) PreIncLocalVarNode(index);
- }
-}
-
-JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- JSValue** slot = &exec->localStorage()[m_index].value;
-
- double n = (*slot)->toNumber(exec);
- JSValue* n2 = jsNumber(n + 1);
- *slot = n2;
- return n2;
-}
-
-JSValue* PreIncResolveNode::evaluate(ExecState* exec)
-{
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- do {
- if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
- // See the comment in PostIncResolveNode::evaluate().
-
- JSObject* base = *iter;
- JSValue* v = slot.getValue(exec, base, m_ident);
-
- double n = v->toNumber(exec);
- JSValue* n2 = jsNumber(n + 1);
- base->put(exec, m_ident, n2);
-
- return n2;
- }
-
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-void PreDecResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
-{
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) PreDecConstNode(index);
- else
- new (this) PreDecLocalVarNode(index);
- }
-}
-
-JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- JSValue** slot = &exec->localStorage()[m_index].value;
-
- double n = (*slot)->toNumber(exec);
- JSValue* n2 = jsNumber(n - 1);
- *slot = n2;
- return n2;
-}
-
-JSValue* PreDecResolveNode::evaluate(ExecState* exec)
-{
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- do {
- if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
- // See the comment in PostIncResolveNode::evaluate().
-
- JSObject* base = *iter;
- JSValue* v = slot.getValue(exec, base, m_ident);
-
- double n = v->toNumber(exec);
- JSValue* n2 = jsNumber(n - 1);
- base->put(exec, m_ident, n2);
-
- return n2;
- }
-
- ++iter;
- } while (iter != end);
-
- return throwUndefinedVariableError(exec, m_ident);
-}
-
-// ------------------------------ PreIncConstNode ----------------------------------
-
-JSValue* PreIncConstNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
-}
-
-// ------------------------------ PreDecConstNode ----------------------------------
-
-JSValue* PreDecConstNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
-}
-
-// ------------------------------ PostIncConstNode ----------------------------------
-
-JSValue* PostIncConstNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
-}
-
-// ------------------------------ PostDecConstNode ----------------------------------
-
-JSValue* PostDecConstNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
-}
-
-// ------------------------------ PrefixBracketNode ----------------------------------
-
-void PrefixBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* PreIncBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
- base->put(exec, propertyIndex, n2);
-
- return n2;
- }
-
- Identifier propertyName(subscript->toString(exec));
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
- base->put(exec, propertyName, n2);
-
- return n2;
-}
-
-JSValue* PreDecBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
- base->put(exec, propertyIndex, n2);
-
- return n2;
- }
-
- Identifier propertyName(subscript->toString(exec));
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
- base->put(exec, propertyName, n2);
-
- return n2;
-}
-
-// ------------------------------ PrefixDotNode ----------------------------------
-
-void PrefixDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_base.get());
-}
-
-JSValue* PreIncDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- double n = v->toNumber(exec);
- JSValue* n2 = jsNumber(n + 1);
- base->put(exec, m_ident, n2);
-
- return n2;
-}
-
-JSValue* PreDecDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- PropertySlot slot;
- JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
-
- double n = v->toNumber(exec);
- JSValue* n2 = jsNumber(n - 1);
- base->put(exec, m_ident, n2);
-
- return n2;
-}
-
-// ------------------------------ PrefixErrorNode -----------------------------------
-
-JSValue* PrefixErrorNode::evaluate(ExecState* exec)
-{
- throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
- m_operator == OpPlusPlus ? "++" : "--");
- handleException(exec);
- return jsUndefined();
-}
-
-// ------------------------------ UnaryPlusNode --------------------------------
-
-void UnaryPlusNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.4.6
-JSValue* UnaryPlusNode::evaluate(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- return v->toJSNumber(exec);
-}
-
-bool UnaryPlusNode::evaluateToBoolean(ExecState* exec)
-{
- return m_expr->evaluateToBoolean(exec);
-}
-
-double UnaryPlusNode::evaluateToNumber(ExecState* exec)
-{
- return m_expr->evaluateToNumber(exec);
-}
-
-int32_t UnaryPlusNode::evaluateToInt32(ExecState* exec)
-{
- return m_expr->evaluateToInt32(exec);
-}
-
-uint32_t UnaryPlusNode::evaluateToUInt32(ExecState* exec)
-{
- return m_expr->evaluateToInt32(exec);
-}
-
-// ------------------------------ NegateNode -----------------------------------
-
-void NegateNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.4.7
-JSValue* NegateNode::evaluate(ExecState* exec)
-{
- // No need to check exception, caller will do so right after evaluate()
- return jsNumber(-m_expr->evaluateToNumber(exec));
-}
-
-double NegateNode::evaluateToNumber(ExecState* exec)
-{
- // No need to check exception, caller will do so right after evaluateToNumber()
- return -m_expr->evaluateToNumber(exec);
-}
-
-// ------------------------------ BitwiseNotNode -------------------------------
-
-void BitwiseNotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.4.8
-int32_t BitwiseNotNode::inlineEvaluateToInt32(ExecState* exec)
-{
- return ~m_expr->evaluateToInt32(exec);
-}
-
-JSValue* BitwiseNotNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToInt32(exec));
-}
-
-double BitwiseNotNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-bool BitwiseNotNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t BitwiseNotNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t BitwiseNotNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-// ------------------------------ LogicalNotNode -------------------------------
-
-void LogicalNotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 11.4.9
-JSValue* LogicalNotNode::evaluate(ExecState* exec)
-{
- return jsBoolean(!m_expr->evaluateToBoolean(exec));
-}
-
-bool LogicalNotNode::evaluateToBoolean(ExecState* exec)
-{
- return !m_expr->evaluateToBoolean(exec);
-}
-
-// ------------------------------ Multiplicative Nodes -----------------------------------
-
-void MultNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.5.1
-double MultNode::inlineEvaluateToNumber(ExecState* exec)
-{
- double n1 = m_term1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONNUMBER
- double n2 = m_term2->evaluateToNumber(exec);
- return n1 * n2;
-}
-
-JSValue* MultNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToNumber(exec));
-}
-
-double MultNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-bool MultNode::evaluateToBoolean(ExecState* exec)
-{
- double result = inlineEvaluateToNumber(exec);
- return result > 0.0 || 0.0 > result; // NaN produces false as well
-}
-
-int32_t MultNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t MultNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-void DivNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.5.2
-double DivNode::inlineEvaluateToNumber(ExecState* exec)
-{
- double n1 = m_term1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONNUMBER
- double n2 = m_term2->evaluateToNumber(exec);
- return n1 / n2;
-}
-
-JSValue* DivNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToNumber(exec));
-}
-
-double DivNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-int32_t DivNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t DivNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-void ModNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.5.3
-double ModNode::inlineEvaluateToNumber(ExecState* exec)
-{
- double n1 = m_term1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONNUMBER
- double n2 = m_term2->evaluateToNumber(exec);
- return fmod(n1, n2);
-}
-
-JSValue* ModNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToNumber(exec));
-}
-
-double ModNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-bool ModNode::evaluateToBoolean(ExecState* exec)
-{
- double result = inlineEvaluateToNumber(exec);
- return result > 0.0 || 0.0 > result; // NaN produces false as well
-}
-
-int32_t ModNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t ModNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-// ------------------------------ Additive Nodes --------------------------------------
-
-static JSValue* throwOutOfMemoryError(ExecState* exec)
-{
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- return error;
-}
-
-static double throwOutOfMemoryErrorToNumber(ExecState* exec)
-{
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- return 0.0;
-}
-
-// ECMA 11.6
-static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- // exception for the Date exception in defaultValue()
- JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
- JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
-
- if (p1->isString() || p2->isString()) {
- UString value = p1->toString(exec) + p2->toString(exec);
- if (value.isNull())
- return throwOutOfMemoryError(exec);
- return jsString(value);
- }
-
- return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
-}
-
-static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- // exception for the Date exception in defaultValue()
- JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
- JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
-
- if (p1->isString() || p2->isString()) {
- UString value = p1->toString(exec) + p2->toString(exec);
- if (value.isNull())
- return throwOutOfMemoryErrorToNumber(exec);
- return value.toDouble();
- }
-
- return p1->toNumber(exec) + p2->toNumber(exec);
-}
-
-// Fast-path choices here are based on frequency data from SunSpider:
-// <times> Add case: <t1> <t2>
-// ---------------------------
-// 5627160 Add case: 1 1
-// 247427 Add case: 5 5
-// 20901 Add case: 5 6
-// 13978 Add case: 5 1
-// 4000 Add case: 1 5
-// 1 Add case: 3 5
-
-static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
- const unsigned bothTypes = (t1 << 3) | t2;
-
- if (bothTypes == ((NumberType << 3) | NumberType))
- return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
- if (bothTypes == ((StringType << 3) | StringType)) {
- UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
- if (value.isNull())
- return throwOutOfMemoryError(exec);
- return jsString(value);
- }
-
- // All other cases are pretty uncommon
- return addSlowCase(exec, v1, v2);
-}
-
-static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
- const unsigned bothTypes = (t1 << 3) | t2;
-
- if (bothTypes == ((NumberType << 3) | NumberType))
- return v1->toNumber(exec) + v2->toNumber(exec);
- if (bothTypes == ((StringType << 3) | StringType)) {
- UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
- if (value.isNull())
- return throwOutOfMemoryErrorToNumber(exec);
- return value.toDouble();
- }
-
- // All other cases are pretty uncommon
- return addSlowCaseToNumber(exec, v1, v2);
-}
-
-void AddNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.6.1
-JSValue* AddNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = m_term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return add(exec, v1, v2);
-}
-
-double AddNode::inlineEvaluateToNumber(ExecState* exec)
-{
- JSValue* v1 = m_term1->evaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
-
- JSValue* v2 = m_term2->evaluate(exec);
- KJS_CHECKEXCEPTIONNUMBER
-
- return addToNumber(exec, v1, v2);
-}
-
-double AddNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-int32_t AddNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t AddNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
-{
- double n1 = m_term1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONNUMBER
- double n2 = m_term2->evaluateToNumber(exec);
- return n1 + n2;
-}
-
-JSValue* AddNumbersNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToNumber(exec));
-}
-
-double AddNumbersNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-int32_t AddNumbersNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t AddNumbersNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-JSValue* AddStringsNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = m_term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
-}
-
-JSValue* AddStringLeftNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = m_term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
- return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
-}
-
-JSValue* AddStringRightNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* v2 = m_term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
- return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
-}
-
-void SubNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.6.2
-double SubNode::inlineEvaluateToNumber(ExecState* exec)
-{
- double n1 = m_term1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONNUMBER
- double n2 = m_term2->evaluateToNumber(exec);
- return n1 - n2;
-}
-
-JSValue* SubNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToNumber(exec));
-}
-
-double SubNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToNumber(exec);
-}
-
-int32_t SubNode::evaluateToInt32(ExecState* exec)
-{
- return JSValue::toInt32(inlineEvaluateToNumber(exec));
-}
-
-uint32_t SubNode::evaluateToUInt32(ExecState* exec)
-{
- return JSValue::toUInt32(inlineEvaluateToNumber(exec));
-}
-
-// ------------------------------ Shift Nodes ------------------------------------
-
-void LeftShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.7.1
-int32_t LeftShiftNode::inlineEvaluateToInt32(ExecState* exec)
-{
- int i1 = m_term1->evaluateToInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
- return (i1 << i2);
-}
-
-JSValue* LeftShiftNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToInt32(exec));
-}
-
-double LeftShiftNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t LeftShiftNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t LeftShiftNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-void RightShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.7.2
-int32_t RightShiftNode::inlineEvaluateToInt32(ExecState* exec)
-{
- int i1 = m_term1->evaluateToInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
- return (i1 >> i2);
-}
-
-JSValue* RightShiftNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToInt32(exec));
-}
-
-double RightShiftNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t RightShiftNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t RightShiftNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-void UnsignedRightShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_term1.get());
- nodeStack.append(m_term2.get());
-}
-
-// ECMA 11.7.3
-uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(ExecState* exec)
-{
- unsigned int i1 = m_term1->evaluateToUInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
- return (i1 >> i2);
-}
-
-JSValue* UnsignedRightShiftNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToUInt32(exec));
-}
-
-double UnsignedRightShiftNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToUInt32(exec);
-}
-
-int32_t UnsignedRightShiftNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToUInt32(exec);
-}
-
-uint32_t UnsignedRightShiftNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToUInt32(exec);
-}
-
-// ------------------------------ Relational Nodes -------------------------------
-
-static inline bool lessThan(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- double n1;
- double n2;
- JSValue* p1;
- JSValue* p2;
- bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
- bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
-
- if (wasNotString1 | wasNotString2)
- return n1 < n2;
-
- return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
-}
-
-static inline bool lessThanEq(ExecState* exec, JSValue* v1, JSValue* v2)
-{
- double n1;
- double n2;
- JSValue* p1;
- JSValue* p2;
- bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
- bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
-
- if (wasNotString1 | wasNotString2)
- return n1 <= n2;
-
- return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
-}
-
-void LessNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.1
-bool LessNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return lessThan(exec, v1, v2);
-}
-
-JSValue* LessNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool LessNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-bool LessNumbersNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- double n1 = m_expr1->evaluateToNumber(exec);
- KJS_CHECKEXCEPTIONVALUE
- double n2 = m_expr2->evaluateToNumber(exec);
- return n1 < n2;
-}
-
-JSValue* LessNumbersNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool LessNumbersNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-bool LessStringsNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* v2 = m_expr2->evaluate(exec);
- return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
-}
-
-JSValue* LessStringsNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool LessStringsNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void GreaterNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.2
-bool GreaterNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return lessThan(exec, v2, v1);
-}
-
-JSValue* GreaterNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool GreaterNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void LessEqNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.3
-bool LessEqNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return lessThanEq(exec, v1, v2);
-}
-
-JSValue* LessEqNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool LessEqNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void GreaterEqNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.4
-bool GreaterEqNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return lessThanEq(exec, v2, v1);
-}
-
-JSValue* GreaterEqNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool GreaterEqNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void InstanceOfNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.6
-JSValue* InstanceOfNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- if (!v2->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());
-
- JSObject* o2 = static_cast<JSObject*>(v2);
-
- // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
- // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
- // property. It seems that all objects have the property, but not all implement it, so in this
- // case we return false (consistent with Mozilla).
- if (!o2->implementsHasInstance())
- return jsBoolean(false);
-
- return jsBoolean(o2->hasInstance(exec, v1));
-}
-
-bool InstanceOfNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- if (!v2->isObject()) {
- throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
- return false;
- }
-
- JSObject* o2 = static_cast<JSObject*>(v2);
-
- // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
- // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
- // property. It seems that all objects have the property, but not all implement it, so in this
- // case we return false (consistent with Mozilla).
- if (!o2->implementsHasInstance())
- return false;
-
- return o2->hasInstance(exec, v1);
-}
-
-void InNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.8.7
-JSValue* InNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- if (!v2->isObject())
- return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
-
- return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
-}
-
-bool InNode::evaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- if (!v2->isObject()) {
- throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
- return false;
- }
-
- return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
-}
-
-// ------------------------------ Equality Nodes ------------------------------------
-
-void EqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.9.1
-bool EqualNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- return equal(exec, v1, v2);
-}
-
-JSValue* EqualNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool EqualNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void NotEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.9.2
-bool NotEqualNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- return !equal(exec,v1, v2);
-}
-
-JSValue* NotEqualNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool NotEqualNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void StrictEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.9.4
-bool StrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- return strictEqual(exec,v1, v2);
-}
-
-JSValue* StrictEqualNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool StrictEqualNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-void NotStrictEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.9.5
-bool NotStrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
-
- return !strictEqual(exec,v1, v2);
-}
-
-JSValue* NotStrictEqualNode::evaluate(ExecState* exec)
-{
- return jsBoolean(inlineEvaluateToBoolean(exec));
-}
-
-bool NotStrictEqualNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToBoolean(exec);
-}
-
-// ------------------------------ Bit Operation Nodes ----------------------------------
-
-void BitAndNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.10
-JSValue* BitAndNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return jsNumberFromAnd(exec, v1, v2);
-}
-
-int32_t BitAndNode::inlineEvaluateToInt32(ExecState* exec)
-{
- int32_t i1 = m_expr1->evaluateToInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- int32_t i2 = m_expr2->evaluateToInt32(exec);
- return (i1 & i2);
-}
-
-double BitAndNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-bool BitAndNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t BitAndNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t BitAndNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-void BitXOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-int32_t BitXOrNode::inlineEvaluateToInt32(ExecState* exec)
-{
- int i1 = m_expr1->evaluateToInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- int i2 = m_expr2->evaluateToInt32(exec);
- return (i1 ^ i2);
-}
-
-JSValue* BitXOrNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToInt32(exec));
-}
-
-double BitXOrNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-bool BitXOrNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t BitXOrNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t BitXOrNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-void BitOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-int32_t BitOrNode::inlineEvaluateToInt32(ExecState* exec)
-{
- int i1 = m_expr1->evaluateToInt32(exec);
- KJS_CHECKEXCEPTIONNUMBER
- int i2 = m_expr2->evaluateToInt32(exec);
- return (i1 | i2);
-}
-
-JSValue* BitOrNode::evaluate(ExecState* exec)
-{
- return jsNumber(inlineEvaluateToInt32(exec));
-}
-
-double BitOrNode::evaluateToNumber(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-bool BitOrNode::evaluateToBoolean(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-int32_t BitOrNode::evaluateToInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-uint32_t BitOrNode::evaluateToUInt32(ExecState* exec)
-{
- return inlineEvaluateToInt32(exec);
-}
-
-// ------------------------------ Binary Logical Nodes ----------------------------
-
-void LogicalAndNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.11
-JSValue* LogicalAndNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- bool b1 = v1->toBoolean(exec);
- KJS_CHECKEXCEPTIONVALUE
- if (!b1)
- return v1;
- JSValue* v2 = m_expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- return v2;
-}
-
-bool LogicalAndNode::evaluateToBoolean(ExecState* exec)
-{
- bool b = m_expr1->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return b && m_expr2->evaluateToBoolean(exec);
-}
-
-void LogicalOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-JSValue* LogicalOrNode::evaluate(ExecState* exec)
-{
- JSValue* v1 = m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- if (v1->toBoolean(exec))
- return v1;
- return m_expr2->evaluate(exec);
-}
-
-bool LogicalOrNode::evaluateToBoolean(ExecState* exec)
-{
- bool b = m_expr1->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return b || m_expr2->evaluateToBoolean(exec);
-}
-
-// ------------------------------ ConditionalNode ------------------------------
-
-void ConditionalNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
- nodeStack.append(m_logical.get());
-}
-
-// ECMA 11.12
-JSValue* ConditionalNode::evaluate(ExecState* exec)
-{
- bool b = m_logical->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONVALUE
- return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
-}
-
-bool ConditionalNode::evaluateToBoolean(ExecState* exec)
-{
- bool b = m_logical->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONBOOLEAN
- return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
-}
-
-double ConditionalNode::evaluateToNumber(ExecState* exec)
-{
- bool b = m_logical->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
-}
-
-int32_t ConditionalNode::evaluateToInt32(ExecState* exec)
-{
- bool b = m_logical->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
-}
-
-uint32_t ConditionalNode::evaluateToUInt32(ExecState* exec)
-{
- bool b = m_logical->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTIONNUMBER
- return b ? m_expr1->evaluateToUInt32(exec) : m_expr2->evaluateToUInt32(exec);
-}
-
-// ECMA 11.13
-
-static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
-static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
-{
- JSValue* v;
- int i1;
- int i2;
- unsigned int ui;
- switch (oper) {
- case OpMultEq:
- v = jsNumber(current->toNumber(exec) * right->evaluateToNumber(exec));
- break;
- case OpDivEq:
- v = jsNumber(current->toNumber(exec) / right->evaluateToNumber(exec));
- break;
- case OpPlusEq:
- v = add(exec, current, right->evaluate(exec));
- break;
- case OpMinusEq:
- v = jsNumber(current->toNumber(exec) - right->evaluateToNumber(exec));
- break;
- case OpLShift:
- i1 = current->toInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(i1 << i2);
- break;
- case OpRShift:
- i1 = current->toInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(i1 >> i2);
- break;
- case OpURShift:
- ui = current->toUInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(ui >> i2);
- break;
- case OpAndEq:
- i1 = current->toInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(i1 & i2);
- break;
- case OpXOrEq:
- i1 = current->toInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(i1 ^ i2);
- break;
- case OpOrEq:
- i1 = current->toInt32(exec);
- i2 = right->evaluateToInt32(exec);
- v = jsNumber(i1 | i2);
- break;
- case OpModEq: {
- double d1 = current->toNumber(exec);
- double d2 = right->evaluateToNumber(exec);
- v = jsNumber(fmod(d1, d2));
- }
- break;
- default:
- ASSERT_NOT_REACHED();
- v = jsUndefined();
- }
-
- return v;
-}
-
-// ------------------------------ ReadModifyResolveNode -----------------------------------
-
-void ReadModifyResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) ReadModifyConstNode(index);
- else
- new (this) ReadModifyLocalVarNode(index);
- }
-}
-
-// ------------------------------ AssignResolveNode -----------------------------------
-
-void AssignResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- size_t index = symbolTable.get(m_ident.ustring().rep());
- if (index != missingSymbolMarker()) {
- if (isConstant(localStorage, index))
- new (this) AssignConstNode;
- else
- new (this) AssignLocalVarNode(index);
- }
-}
-
-// ------------------------------ ReadModifyLocalVarNode -----------------------------------
-
-JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
-
- ASSERT(m_operator != OpEqual);
- JSValue* v = valueForReadModifyAssignment(exec, exec->localStorage()[m_index].value, m_right.get(), m_operator);
-
- KJS_CHECKEXCEPTIONVALUE
-
- // We can't store a pointer into localStorage() and use it throughout the function
- // body, because valueForReadModifyAssignment() might cause an ActivationImp tear-off,
- // changing the value of localStorage().
-
- exec->localStorage()[m_index].value = v;
- return v;
-}
-
-// ------------------------------ AssignLocalVarNode -----------------------------------
-
-JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- JSValue* v = m_right->evaluate(exec);
-
- KJS_CHECKEXCEPTIONVALUE
-
- exec->localStorage()[m_index].value = v;
-
- return v;
-}
-
-// ------------------------------ ReadModifyConstNode -----------------------------------
-
-JSValue* ReadModifyConstNode::evaluate(ExecState* exec)
-{
- ASSERT(exec->variableObject() == exec->scopeChain().top());
- JSValue* left = exec->localStorage()[m_index].value;
- ASSERT(m_operator != OpEqual);
- JSValue* result = valueForReadModifyAssignment(exec, left, m_right.get(), m_operator);
- KJS_CHECKEXCEPTIONVALUE
- return result;
-}
-
-// ------------------------------ AssignConstNode -----------------------------------
-
-JSValue* AssignConstNode::evaluate(ExecState* exec)
-{
- return m_right->evaluate(exec);
-}
-
-JSValue* ReadModifyResolveNode::evaluate(ExecState* exec)
-{
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // We must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot)) {
- // See the comment in PostIncResolveNode::evaluate().
-
- base = *iter;
- goto found;
- }
-
- ++iter;
- } while (iter != end);
-
- ASSERT(m_operator != OpEqual);
- return throwUndefinedVariableError(exec, m_ident);
-
-found:
- JSValue* v;
-
- ASSERT(m_operator != OpEqual);
- JSValue* v1 = slot.getValue(exec, base, m_ident);
- KJS_CHECKEXCEPTIONVALUE
- v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
-
- KJS_CHECKEXCEPTIONVALUE
-
- // Since valueForReadModifyAssignment() might cause an ActivationImp tear-off,
- // we need to get the base from the ScopeChainIterator again.
-
- (*iter)->put(exec, m_ident, v);
- return v;
-}
-
-JSValue* AssignResolveNode::evaluate(ExecState* exec)
-{
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot)) {
- // See the comment in PostIncResolveNode::evaluate().
-
- base = *iter;
- goto found;
- }
-
- ++iter;
- } while (iter != end);
-
-found:
- JSValue* v = m_right->evaluate(exec);
-
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, m_ident, v);
- return v;
-}
-
-// ------------------------------ ReadModifyDotNode -----------------------------------
-
-void AssignDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* AssignDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- JSValue* v = m_right->evaluate(exec);
-
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, m_ident, v);
- return v;
-}
-
-void ReadModifyDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* ReadModifyDotNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSObject* base = baseValue->toObject(exec);
-
- JSValue* v;
-
- ASSERT(m_operator != OpEqual);
- PropertySlot slot;
- JSValue* v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
- v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
-
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, m_ident, v);
- return v;
-}
-
-// ------------------------------ AssignErrorNode -----------------------------------
-
-JSValue* AssignErrorNode::evaluate(ExecState* exec)
-{
- throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
- handleException(exec);
- return jsUndefined();
-}
-
-// ------------------------------ AssignBracketNode -----------------------------------
-
-void AssignBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* AssignBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- JSValue* v = m_right->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, propertyIndex, v);
- return v;
- }
-
- Identifier propertyName(subscript->toString(exec));
- JSValue* v = m_right->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, propertyName, v);
- return v;
-}
-void ReadModifyBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_right.get());
- nodeStack.append(m_subscript.get());
- nodeStack.append(m_base.get());
-}
-
-JSValue* ReadModifyBracketNode::evaluate(ExecState* exec)
-{
- JSValue* baseValue = m_base->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- JSValue* subscript = m_subscript->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- JSObject* base = baseValue->toObject(exec);
-
- uint32_t propertyIndex;
- if (subscript->getUInt32(propertyIndex)) {
- JSValue* v;
- ASSERT(m_operator != OpEqual);
- PropertySlot slot;
- JSValue* v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
- v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
-
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, propertyIndex, v);
- return v;
- }
-
- Identifier propertyName(subscript->toString(exec));
- JSValue* v;
-
- ASSERT(m_operator != OpEqual);
- PropertySlot slot;
- JSValue* v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
- KJS_CHECKEXCEPTIONVALUE
- v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
-
- KJS_CHECKEXCEPTIONVALUE
-
- base->put(exec, propertyName, v);
- return v;
-}
-
-// ------------------------------ CommaNode ------------------------------------
-
-void CommaNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 11.14
-JSValue* CommaNode::evaluate(ExecState* exec)
-{
- m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- return m_expr2->evaluate(exec);
-}
-
-// ------------------------------ ConstDeclNode ----------------------------------
-
-ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
- : m_ident(ident)
- , m_init(init)
-{
-}
-
-void ConstDeclNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_next)
- nodeStack.append(m_next.get());
- if (m_init)
- nodeStack.append(m_init.get());
-}
-
-void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
-{
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // We must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* base;
-
- do {
- base = *iter;
- if (base->getPropertySlot(exec, m_ident, slot))
- break;
-
- ++iter;
- } while (iter != end);
-
- unsigned flags = 0;
- base->getPropertyAttributes(m_ident, flags);
- flags |= ReadOnly;
-
- base->put(exec, m_ident, val, flags);
-}
-
-// ECMA 12.2
-inline void ConstDeclNode::evaluateSingle(ExecState* exec)
-{
- ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
- const ScopeChain& chain = exec->scopeChain();
- JSObject* variableObject = exec->variableObject();
-
- ASSERT(!chain.isEmpty());
-
- bool inGlobalScope = ++chain.begin() == chain.end();
-
- if (m_init) {
- if (inGlobalScope) {
- JSValue* val = m_init->evaluate(exec);
- int flags = Internal;
- if (exec->codeType() != EvalCode)
- flags |= DontDelete;
- flags |= ReadOnly;
- variableObject->put(exec, m_ident, val, flags);
- } else {
- JSValue* val = m_init->evaluate(exec);
- KJS_CHECKEXCEPTIONVOID
-
- // if the variable object is the top of the scope chain, then that must
- // be where this variable is declared, processVarDecls would have put
- // it there. Don't search the scope chain, to optimize this very common case.
- if (chain.top() != variableObject)
- return handleSlowCase(exec, chain, val);
-
- unsigned flags = 0;
- variableObject->getPropertyAttributes(m_ident, flags);
- flags |= ReadOnly;
-
- variableObject->put(exec, m_ident, val, flags);
- }
- }
-}
-
-JSValue* ConstDeclNode::evaluate(ExecState* exec)
-{
- evaluateSingle(exec);
-
- if (ConstDeclNode* n = m_next.get()) {
- do {
- n->evaluateSingle(exec);
- KJS_CHECKEXCEPTIONVALUE
- n = n->m_next.get();
- } while (n);
- }
- return jsUndefined();
-}
-
-// ------------------------------ ConstStatementNode -----------------------------
-
-void ConstStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- ASSERT(m_next);
- nodeStack.append(m_next.get());
-}
-
-// ECMA 12.2
-JSValue* ConstStatementNode::execute(ExecState* exec)
-{
- m_next->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- return exec->setNormalCompletion();
-}
-
-// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
-
-static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
-{
- StatementVector::iterator it = statements.end();
- StatementVector::iterator begin = statements.begin();
- while (it != begin) {
- --it;
- stack.append((*it).get());
- }
-}
-
-static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
-{
- if (statements.isEmpty())
- return 0;
-
- StatementVector::iterator it = statements.end();
- StatementVector::iterator begin = statements.begin();
- StatementVector::iterator beginPlusOne = begin + 1;
-
- while (it != beginPlusOne) {
- --it;
- stack.append((*it).get());
- }
-
- return (*begin).get();
-}
-
-static inline JSValue* statementListExecute(StatementVector& statements, ExecState* exec)
-{
- JSValue* value = 0;
- size_t size = statements.size();
- for (size_t i = 0; i != size; ++i) {
- JSValue* statementValue = statements[i]->execute(exec);
- if (statementValue)
- value = statementValue;
- if (exec->completionType() != Normal)
- return value;
- }
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ BlockNode ------------------------------------
-
-BlockNode::BlockNode()
-{
-}
-
-BlockNode::BlockNode(SourceElements* children)
-{
- if (children)
- children->releaseContentsIntoVector(m_children);
-}
-
-void BlockNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- statementListPushFIFO(m_children, nodeStack);
-}
-
-// ECMA 12.1
-JSValue* BlockNode::execute(ExecState* exec)
-{
- return statementListExecute(m_children, exec);
-}
-
-// ------------------------------ EmptyStatementNode ---------------------------
-
-// ECMA 12.3
-JSValue* EmptyStatementNode::execute(ExecState* exec)
-{
- return exec->setNormalCompletion();
-}
-
-// ------------------------------ ExprStatementNode ----------------------------
-
-void ExprStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- ASSERT(m_expr);
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.4
-JSValue* ExprStatementNode::execute(ExecState* exec)
-{
- JSValue* value = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ VarStatementNode ----------------------------
-
-void VarStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- ASSERT(m_expr);
- nodeStack.append(m_expr.get());
-}
-
-JSValue* VarStatementNode::execute(ExecState* exec)
-{
- m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- return exec->setNormalCompletion();
-}
-
-// ------------------------------ IfNode ---------------------------------------
-
-void IfNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_ifBlock.get());
- nodeStack.append(m_condition.get());
-}
-
-// ECMA 12.5
-JSValue* IfNode::execute(ExecState* exec)
-{
- bool b = m_condition->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTION
-
- if (b)
- return m_ifBlock->execute(exec);
- return exec->setNormalCompletion();
-}
-
-void IfElseNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
-{
- nodeStack.append(m_elseBlock.get());
- IfNode::optimizeVariableAccess(symbolTable, localStorage, nodeStack);
-}
-
-// ECMA 12.5
-JSValue* IfElseNode::execute(ExecState* exec)
-{
- bool b = m_condition->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTION
-
- if (b)
- return m_ifBlock->execute(exec);
- return m_elseBlock->execute(exec);
-}
-
-// ------------------------------ DoWhileNode ----------------------------------
-
-void DoWhileNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.6.1
-JSValue* DoWhileNode::execute(ExecState* exec)
-{
- JSValue* value = 0;
-
- while (1) {
- exec->pushIteration();
- JSValue* statementValue = m_statement->execute(exec);
- exec->popIteration();
-
- if (exec->dynamicGlobalObject()->timedOut())
- return setInterruptedCompletion(exec);
-
- if (statementValue)
- value = statementValue;
-
- if (exec->completionType() != Normal) {
- if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
- goto continueDoWhileLoop;
- if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
- break;
- return statementValue;
- }
-
- continueDoWhileLoop:
- bool b = m_expr->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTION
- if (!b)
- break;
- }
-
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ WhileNode ------------------------------------
-
-void WhileNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.6.2
-JSValue* WhileNode::execute(ExecState* exec)
-{
- JSValue* value = 0;
-
- while (1) {
- bool b = m_expr->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTION
- if (!b)
- break;
-
- exec->pushIteration();
- JSValue* statementValue = m_statement->execute(exec);
- exec->popIteration();
-
- if (exec->dynamicGlobalObject()->timedOut())
- return setInterruptedCompletion(exec);
-
- if (statementValue)
- value = statementValue;
-
- if (exec->completionType() != Normal) {
- if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
- continue;
- if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
- break;
- return statementValue;
- }
- }
-
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ ForNode --------------------------------------
-
-void ForNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
- nodeStack.append(m_expr3.get());
- nodeStack.append(m_expr2.get());
- nodeStack.append(m_expr1.get());
-}
-
-// ECMA 12.6.3
-JSValue* ForNode::execute(ExecState* exec)
-{
- JSValue* value = 0;
-
- m_expr1->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- while (1) {
- bool b = m_expr2->evaluateToBoolean(exec);
- KJS_CHECKEXCEPTION
- if (!b)
- break;
-
- exec->pushIteration();
- JSValue* statementValue = m_statement->execute(exec);
- exec->popIteration();
- if (statementValue)
- value = statementValue;
-
- if (exec->dynamicGlobalObject()->timedOut())
- return setInterruptedCompletion(exec);
-
- if (exec->completionType() != Normal) {
- if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
- goto continueForLoop;
- if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
- break;
- return statementValue;
- }
-
- continueForLoop:
- m_expr3->evaluate(exec);
- KJS_CHECKEXCEPTION
- }
-
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ ForInNode ------------------------------------
-
-ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
- : m_init(0L)
- , m_lexpr(l)
- , m_expr(expr)
- , m_statement(statement)
- , m_identIsVarDecl(false)
-{
-}
-
-ForInNode::ForInNode(const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
- : m_ident(ident)
- , m_lexpr(new ResolveNode(ident))
- , m_expr(expr)
- , m_statement(statement)
- , m_identIsVarDecl(true)
-{
- if (in)
- m_init = new AssignResolveNode(ident, in);
- // for( var foo = bar in baz )
-}
-
-void ForInNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
- nodeStack.append(m_expr.get());
- nodeStack.append(m_lexpr.get());
- if (m_init)
- nodeStack.append(m_init.get());
-}
-
-// ECMA 12.6.4
-JSValue* ForInNode::execute(ExecState* exec)
-{
- JSValue* value = 0;
-
- if (m_init) {
- m_init->evaluate(exec);
- KJS_CHECKEXCEPTION
- }
-
- JSValue* e = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- // For Null and Undefined, we want to make sure not to go through
- // the loop at all, because toObject will throw an exception.
- if (e->isUndefinedOrNull())
- return exec->setNormalCompletion();
-
- JSObject* v = e->toObject(exec);
- PropertyNameArray propertyNames;
- v->getPropertyNames(exec, propertyNames);
-
- PropertyNameArray::const_iterator end = propertyNames.end();
- for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != end; ++it) {
- const Identifier& name = *it;
- if (!v->hasProperty(exec, name))
- continue;
-
- JSValue* str = jsOwnedString(name.ustring());
-
- if (m_lexpr->isResolveNode()) {
- const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
-
- const ScopeChain& chain = exec->scopeChain();
- ScopeChainIterator iter = chain.begin();
- ScopeChainIterator end = chain.end();
-
- // we must always have something in the scope chain
- ASSERT(iter != end);
-
- PropertySlot slot;
- JSObject* o;
- do {
- o = *iter;
- if (o->getPropertySlot(exec, ident, slot)) {
- o->put(exec, ident, str);
- break;
- }
- ++iter;
- } while (iter != end);
-
- if (iter == end)
- o->put(exec, ident, str);
- } else if (m_lexpr->isDotAccessorNode()) {
- const Identifier& ident = static_cast<DotAccessorNode*>(m_lexpr.get())->identifier();
- JSValue* v = static_cast<DotAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
- KJS_CHECKEXCEPTION
- JSObject* o = v->toObject(exec);
-
- o->put(exec, ident, str);
- } else {
- ASSERT(m_lexpr->isBracketAccessorNode());
- JSValue* v = static_cast<BracketAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
- KJS_CHECKEXCEPTION
- JSValue* v2 = static_cast<BracketAccessorNode*>(m_lexpr.get())->subscript()->evaluate(exec);
- KJS_CHECKEXCEPTION
- JSObject* o = v->toObject(exec);
-
- uint32_t i;
- if (v2->getUInt32(i))
- o->put(exec, i, str);
- o->put(exec, Identifier(v2->toString(exec)), str);
- }
-
- KJS_CHECKEXCEPTION
-
- exec->pushIteration();
- JSValue* statementValue = m_statement->execute(exec);
- exec->popIteration();
- if (statementValue)
- value = statementValue;
-
- if (exec->completionType() != Normal) {
- if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
- continue;
- if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
- break;
- return statementValue;
- }
- }
-
- return exec->setNormalCompletion(value);
-}
-
-// ------------------------------ ContinueNode ---------------------------------
-
-// ECMA 12.7
-JSValue* ContinueNode::execute(ExecState* exec)
-{
- if (m_ident.isEmpty() && !exec->inIteration())
- return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
- if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
- return setErrorCompletion(exec, SyntaxError, "Label %s not found.", m_ident);
- return exec->setContinueCompletion(&m_ident);
-}
-
-// ------------------------------ BreakNode ------------------------------------
-
-// ECMA 12.8
-JSValue* BreakNode::execute(ExecState* exec)
-{
- if (m_ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
- return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
- if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
- return setErrorCompletion(exec, SyntaxError, "Label %s not found.");
- return exec->setBreakCompletion(&m_ident);
-}
-
-// ------------------------------ ReturnNode -----------------------------------
-
-void ReturnNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_value)
- nodeStack.append(m_value.get());
-}
-
-// ECMA 12.9
-JSValue* ReturnNode::execute(ExecState* exec)
-{
- CodeType codeType = exec->codeType();
- if (codeType != FunctionCode)
- return setErrorCompletion(exec, SyntaxError, "Invalid return statement.");
-
- if (!m_value)
- return exec->setReturnValueCompletion(jsUndefined());
-
- JSValue* v = m_value->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- return exec->setReturnValueCompletion(v);
-}
-
-// ------------------------------ WithNode -------------------------------------
-
-void WithNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- // Can't optimize within statement because "with" introduces a dynamic scope.
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.10
-JSValue* WithNode::execute(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
- JSObject* o = v->toObject(exec);
- KJS_CHECKEXCEPTION
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- exec->pushScope(o);
- JSValue* value = m_statement->execute(exec);
- exec->popScope();
-
- return value;
-}
-
-// ------------------------------ CaseClauseNode -------------------------------
-
-void CaseClauseNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_expr)
- nodeStack.append(m_expr.get());
- statementListPushFIFO(m_children, nodeStack);
-}
-
-// ECMA 12.11
-JSValue* CaseClauseNode::evaluate(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return v;
-}
-
-// ECMA 12.11
-JSValue* CaseClauseNode::executeStatements(ExecState* exec)
-{
- return statementListExecute(m_children, exec);
-}
-
-// ------------------------------ ClauseListNode -------------------------------
-
-void ClauseListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_next)
- nodeStack.append(m_next.get());
- nodeStack.append(m_clause.get());
-}
-
-// ------------------------------ CaseBlockNode --------------------------------
-
-CaseBlockNode::CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
- : m_list1(list1)
- , m_defaultClause(defaultClause)
- , m_list2(list2)
-{
-}
-
-void CaseBlockNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- if (m_list2)
- nodeStack.append(m_list2.get());
- if (m_defaultClause)
- nodeStack.append(m_defaultClause.get());
- if (m_list1)
- nodeStack.append(m_list1.get());
-}
-
-// ECMA 12.11
-JSValue* CaseBlockNode::executeBlock(ExecState* exec, JSValue* input)
-{
- ClauseListNode* a = m_list1.get();
- while (a) {
- CaseClauseNode* clause = a->getClause();
- a = a->getNext();
- JSValue* v = clause->evaluate(exec);
- KJS_CHECKEXCEPTION
- if (strictEqual(exec, input, v)) {
- JSValue* res = clause->executeStatements(exec);
- if (exec->completionType() != Normal)
- return res;
- for (; a; a = a->getNext()) {
- JSValue* res = a->getClause()->executeStatements(exec);
- if (exec->completionType() != Normal)
- return res;
- }
- break;
- }
- }
-
- ClauseListNode* b = m_list2.get();
- while (b) {
- CaseClauseNode* clause = b->getClause();
- b = b->getNext();
- JSValue* v = clause->evaluate(exec);
- KJS_CHECKEXCEPTION
- if (strictEqual(exec, input, v)) {
- JSValue* res = clause->executeStatements(exec);
- if (exec->completionType() != Normal)
- return res;
- goto step18;
- }
- }
-
- // default clause
- if (m_defaultClause) {
- JSValue* res = m_defaultClause->executeStatements(exec);
- if (exec->completionType() != Normal)
- return res;
- }
- b = m_list2.get();
-step18:
- while (b) {
- CaseClauseNode* clause = b->getClause();
- JSValue* res = clause->executeStatements(exec);
- if (exec->completionType() != Normal)
- return res;
- b = b->getNext();
- }
-
- // bail out on error
- KJS_CHECKEXCEPTION
-
- return exec->setNormalCompletion();
-}
-
-// ------------------------------ SwitchNode -----------------------------------
-
-void SwitchNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_block.get());
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.11
-JSValue* SwitchNode::execute(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- exec->pushSwitch();
- JSValue* result = m_block->executeBlock(exec, v);
- exec->popSwitch();
-
- if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
- exec->setCompletionType(Normal);
- return result;
-}
-
-// ------------------------------ LabelNode ------------------------------------
-
-void LabelNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_statement.get());
-}
-
-// ECMA 12.12
-JSValue* LabelNode::execute(ExecState* exec)
-{
- if (!exec->seenLabels().push(m_label))
- return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", m_label);
- JSValue* result = m_statement->execute(exec);
- exec->seenLabels().pop();
-
- if (exec->completionType() == Break && exec->breakOrContinueTarget() == m_label)
- exec->setCompletionType(Normal);
- return result;
-}
-
-// ------------------------------ ThrowNode ------------------------------------
-
-void ThrowNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- nodeStack.append(m_expr.get());
-}
-
-// ECMA 12.13
-JSValue* ThrowNode::execute(ExecState* exec)
-{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
-
- handleException(exec, v);
- return exec->setThrowCompletion(v);
-}
-
-// ------------------------------ TryNode --------------------------------------
-
-void TryNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
-{
- // Can't optimize within catchBlock because "catch" introduces a dynamic scope.
- if (m_finallyBlock)
- nodeStack.append(m_finallyBlock.get());
- nodeStack.append(m_tryBlock.get());
-}
-
-// ECMA 12.14
-JSValue* TryNode::execute(ExecState* exec)
-{
- JSValue* result = m_tryBlock->execute(exec);
-
- if (m_catchBlock && exec->completionType() == Throw) {
- JSObject* obj = new JSObject;
- obj->put(exec, m_exceptionIdent, result, DontDelete);
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- exec->pushScope(obj);
- result = m_catchBlock->execute(exec);
- exec->popScope();
- }
-
- if (m_finallyBlock) {
- ComplType savedCompletionType = exec->completionType();
- JSValue* finallyResult = m_finallyBlock->execute(exec);
- if (exec->completionType() != Normal)
- result = finallyResult;
- else
- exec->setCompletionType(savedCompletionType);
- }
-
- return result;
-}
-
-// ------------------------------ FunctionBodyNode -----------------------------
-
-ScopeNode::ScopeNode()
- : BlockNode()
-{
-}
-
-ScopeNode::ScopeNode(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
- : BlockNode(children)
- , m_source(source)
-{
- if (varStack)
- m_varStack = *varStack;
- if (funcStack)
- m_functionStack = *funcStack;
-}
-
-void ScopeNode::setData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
-{
- if (children)
- children->releaseContentsIntoVector(m_children);
- if (varStack)
- m_varStack = *varStack;
- if (funcStack)
- m_functionStack = *funcStack;
-}
-
-// ------------------------------ ProgramNode -----------------------------
-
-ProgramNode::ProgramNode(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
- : ScopeNode(source, children, varStack, funcStack)
-{
-}
-
-ProgramNode* ProgramNode::create(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
-{
- return new ProgramNode(source, children, varStack, funcStack);
-}
-
-// ------------------------------ EvalNode -----------------------------
-
-EvalNode::EvalNode(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
- : ScopeNode(source, children, varStack, funcStack)
-{
-}
-
-EvalNode* EvalNode::create(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
-{
- return new EvalNode(source, children, varStack, funcStack);
-}
-
-// ------------------------------ FunctionBodyNode -----------------------------
-
-FunctionBodyNode::FunctionBodyNode()
- : ScopeNode()
- , m_initialized(false)
-{
-}
-
-FunctionBodyNode::FunctionBodyNode(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
- : ScopeNode(source, children, varStack, funcStack)
- , m_initialized(false)
-{
-}
-
-FunctionBodyNode* FunctionBodyNode::create()
-{
- return new FunctionBodyNode();
-}
-
-FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
-{
- // debugger code removed
- return new FunctionBodyNode(SourceCode(), children, varStack, funcStack);
-}
-
-FunctionBodyNode* FunctionBodyNode::create(const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
-{
- // debugger code removed
- return new FunctionBodyNode(source, children, varStack, funcStack);
-}
-
-void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
-{
- SymbolTable& symbolTable = exec->variableObject()->symbolTable();
- ASSERT(symbolTable.isEmpty());
-
- size_t localStorageIndex = 0;
-
- // Order must match the order in processDeclarations.
-
- for (size_t i = 0, size = m_parameters.size(); i < size; ++i, ++localStorageIndex) {
- UString::Rep* rep = m_parameters[i].ustring().rep();
- symbolTable.set(rep, localStorageIndex);
- }
-
- for (size_t i = 0, size = m_functionStack.size(); i < size; ++i, ++localStorageIndex) {
- UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
- symbolTable.set(rep, localStorageIndex);
- }
-
- for (size_t i = 0, size = m_varStack.size(); i < size; ++i, ++localStorageIndex) {
- Identifier& ident = m_varStack[i].first;
- if (ident == exec->propertyNames().arguments)
- continue;
- symbolTable.add(ident.ustring().rep(), localStorageIndex);
- }
-}
-
-void ProgramNode::initializeSymbolTable(ExecState* exec)
-{
- // If a previous script defined a symbol with the same name as one of our
- // symbols, to avoid breaking previously optimized nodes, we need to reuse
- // the symbol's existing storage index. So, we can't be as efficient as
- // FunctionBodyNode::initializeSymbolTable, which knows that no bindings
- // have yet been made.
-
- JSVariableObject* variableObject = exec->variableObject();
- SymbolTable& symbolTable = variableObject->symbolTable();
-
- size_t localStorageIndex = symbolTable.size();
- size_t size;
-
- // Order must match the order in processDeclarations.
-
- size = m_functionStack.size();
- m_functionIndexes.resize(size);
- for (size_t i = 0; i < size; ++i) {
- UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
- pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
- m_functionIndexes[i] = result.first->second;
- if (result.second)
- ++localStorageIndex;
- }
-
- size = m_varStack.size();
- m_varIndexes.resize(size);
- for (size_t i = 0; i < size; ++i) {
- const Identifier& ident = m_varStack[i].first;
- if (variableObject->hasProperty(exec, ident)) {
- m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
- continue;
- }
-
- UString::Rep* rep = ident.ustring().rep();
- pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
- if (!result.second) {
- m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
- continue;
- }
-
- m_varIndexes[i] = result.first->second;
- ++localStorageIndex;
- }
-}
-
-void ScopeNode::optimizeVariableAccess(ExecState* exec)
-{
- NodeStack nodeStack;
- Node* node = statementListInitializeVariableAccessStack(m_children, nodeStack);
- if (!node)
- return;
-
- const SymbolTable& symbolTable = exec->variableObject()->symbolTable();
- const LocalStorage& localStorage = exec->variableObject()->localStorage();
- while (true) {
- node->optimizeVariableAccess(symbolTable, localStorage, nodeStack);
-
- size_t size = nodeStack.size();
- if (!size)
- break;
- --size;
- node = nodeStack[size];
- nodeStack.shrink(size);
- }
-}
-
-void FunctionBodyNode::processDeclarations(ExecState* exec)
-{
- if (!m_initialized)
- initializeSymbolTable(exec);
-
- if (!m_functionStack.isEmpty())
- exec->dynamicGlobalObject()->tearOffActivation(exec);
-
- LocalStorage& localStorage = exec->variableObject()->localStorage();
-
- // We can't just resize localStorage here because that would temporarily
- // leave uninitialized entries, which would crash GC during the mark phase.
- size_t totalSize = m_varStack.size() + m_parameters.size() + m_functionStack.size();
- if (totalSize > localStorage.capacity()) // Doing this check inline avoids function call overhead.
- localStorage.reserveCapacity(totalSize);
-
- int minAttributes = Internal | DontDelete;
-
- // In order for our localStorage indexes to be correct, we must match the
- // order of addition in initializeSymbolTable().
-
- const List& args = *exec->arguments();
- for (size_t i = 0, size = m_parameters.size(); i < size; ++i)
- localStorage.uncheckedAppend(LocalStorageEntry(args[i], DontDelete));
-
- for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
- FuncDeclNode* node = m_functionStack[i];
- localStorage.uncheckedAppend(LocalStorageEntry(node->makeFunction(exec), minAttributes));
- }
-
- for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
- int attributes = minAttributes;
- if (m_varStack[i].second & DeclarationStacks::IsConstant)
- attributes |= ReadOnly;
- localStorage.uncheckedAppend(LocalStorageEntry(jsUndefined(), attributes));
- }
-
- if (!m_initialized) {
- optimizeVariableAccess(exec);
- m_initialized = true;
- }
-}
-
-static void gccIsCrazy() KJS_FAST_CALL;
-static void gccIsCrazy()
-{
-}
-
-void ProgramNode::processDeclarations(ExecState* exec)
-{
- // If you remove this call, some SunSpider tests, including
- // bitops-nsieve-bits.js, will regress substantially on Mac, due to a ~40%
- // increase in L2 cache misses. FIXME: <rdar://problem/5657439> WTF?
- gccIsCrazy();
-
- initializeSymbolTable(exec);
-
- LocalStorage& localStorage = exec->variableObject()->localStorage();
-
- // We can't just resize localStorage here because that would temporarily
- // leave uninitialized entries, which would crash GC during the mark phase.
- localStorage.reserveCapacity(localStorage.size() + m_varStack.size() + m_functionStack.size());
-
- int minAttributes = Internal | DontDelete;
-
- // In order for our localStorage indexes to be correct, we must match the
- // order of addition in initializeSymbolTable().
-
- for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
- FuncDeclNode* node = m_functionStack[i];
- LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec), minAttributes);
- size_t index = m_functionIndexes[i];
-
- if (index == localStorage.size())
- localStorage.uncheckedAppend(entry);
- else {
- ASSERT(index < localStorage.size());
- localStorage[index] = entry;
- }
- }
-
- for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
- size_t index = m_varIndexes[i];
- if (index == missingSymbolMarker())
- continue;
-
- int attributes = minAttributes;
- if (m_varStack[i].second & DeclarationStacks::IsConstant)
- attributes |= ReadOnly;
- LocalStorageEntry entry = LocalStorageEntry(jsUndefined(), attributes);
-
- ASSERT(index == localStorage.size());
- localStorage.uncheckedAppend(entry);
- }
-
- optimizeVariableAccess(exec);
-}
-
-void EvalNode::processDeclarations(ExecState* exec)
-{
- // We could optimize access to pre-existing symbols here, but SunSpider
- // reports that to be a net loss.
-
- size_t i;
- size_t size;
-
- JSVariableObject* variableObject = exec->variableObject();
-
- int minAttributes = Internal;
-
- for (i = 0, size = m_varStack.size(); i < size; ++i) {
- Identifier& ident = m_varStack[i].first;
- if (variableObject->hasProperty(exec, ident))
- continue;
- int attributes = minAttributes;
- if (m_varStack[i].second & DeclarationStacks::IsConstant)
- attributes |= ReadOnly;
- variableObject->put(exec, ident, jsUndefined(), attributes);
- }
-
- for (i = 0, size = m_functionStack.size(); i < size; ++i) {
- FuncDeclNode* node = m_functionStack[i];
- variableObject->put(exec, node->m_ident, node->makeFunction(exec), minAttributes);
- }
-}
-
-UString FunctionBodyNode::paramString() const
-{
- UString s("");
- size_t count = m_parameters.size();
- for (size_t pos = 0; pos < count; ++pos) {
- if (!s.isEmpty())
- s += ", ";
- s += m_parameters[pos].ustring();
- }
-
- return s;
-}
-
-JSValue* ProgramNode::execute(ExecState* exec)
-{
- processDeclarations(exec);
- return ScopeNode::execute(exec);
-}
-
-JSValue* EvalNode::execute(ExecState* exec)
-{
- processDeclarations(exec);
- return ScopeNode::execute(exec);
-}
-
-JSValue* FunctionBodyNode::execute(ExecState* exec)
-{
- if (m_children.isEmpty())
- parser().reparse(this);
- processDeclarations(exec);
- return ScopeNode::execute(exec);
-}
-
-// ------------------------------ FunctionBodyNodeWithDebuggerHooks ---------------------------------
-
-FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
- : FunctionBodyNode(SourceCode(), children, varStack, funcStack)
-{
-}
-
-JSValue* FunctionBodyNodeWithDebuggerHooks::execute(ExecState* exec)
-{
- if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
- if (!dbg->callEvent(exec, sourceID(), lineNo(), exec->function(), *exec->arguments())) {
- dbg->imp()->abort();
- return exec->setInterruptedCompletion();
- }
- }
-
- JSValue* result = FunctionBodyNode::execute(exec);
-
- if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
- if (exec->completionType() == Throw)
- exec->setException(result);
- if (!dbg->returnEvent(exec, sourceID(), lineNo(), exec->function())) {
- dbg->imp()->abort();
- return exec->setInterruptedCompletion();
- }
- }
-
- return result;
-}
-
-// ------------------------------ FuncDeclNode ---------------------------------
-
-void FuncDeclNode::addParams()
-{
- for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
- m_body->parameters().append(p->ident());
-}
-
-FunctionImp* FuncDeclNode::makeFunction(ExecState* exec)
-{
- FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());
-
- JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
- proto->putDirect(exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
- func->putDirect(exec->propertyNames().prototype, proto, Internal | DontDelete);
- func->putDirect(exec->propertyNames().length, jsNumber(m_body->parameters().size()), ReadOnly | DontDelete | DontEnum);
- return func;
-}
-
-JSValue* FuncDeclNode::execute(ExecState* exec)
-{
- return exec->setNormalCompletion();
-}
-
-// ------------------------------ FuncExprNode ---------------------------------
-
-// ECMA 13
-void FuncExprNode::addParams()
-{
- for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
- m_body->parameters().append(p->ident());
-}
-
-JSValue* FuncExprNode::evaluate(ExecState* exec)
-{
- exec->dynamicGlobalObject()->tearOffActivation(exec);
-
- bool named = !m_ident.isNull();
- JSObject* functionScopeObject = 0;
-
- if (named) {
- // named FunctionExpressions can recursively call themselves,
- // but they won't register with the current scope chain and should
- // be contained as single property in an anonymous object.
- functionScopeObject = new JSObject;
- exec->pushScope(functionScopeObject);
- }
-
- FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());
- JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
- proto->putDirect(exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
- func->putDirect(exec->propertyNames().prototype, proto, Internal | DontDelete);
-
- if (named) {
- functionScopeObject->putDirect(m_ident, func, Internal | ReadOnly | (exec->codeType() == EvalCode ? 0 : DontDelete));
- exec->popScope();
- }
-
- return func;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef NODES_H_
-#define NODES_H_
-
-#include "internal.h"
-#include "regexp.h"
-#include "SourceCode.h"
-#include "SymbolTable.h"
-#include <wtf/ListRefPtr.h>
-#include <wtf/MathExtras.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/Vector.h>
-
-#if PLATFORM(X86) && COMPILER(GCC)
-#define KJS_FAST_CALL __attribute__((regparm(3)))
-#else
-#define KJS_FAST_CALL
-#endif
-
-namespace KJS {
-
- class ConstDeclNode;
- class FuncDeclNode;
- class Node;
- class PropertyListNode;
- class SourceStream;
-
- enum Operator {
- OpEqual,
- OpPlusEq,
- OpMinusEq,
- OpMultEq,
- OpDivEq,
- OpPlusPlus,
- OpMinusMinus,
- OpAndEq,
- OpXOrEq,
- OpOrEq,
- OpModEq,
- OpLShift,
- OpRShift,
- OpURShift,
- };
-
- enum Precedence {
- PrecPrimary,
- PrecMember,
- PrecCall,
- PrecLeftHandSide,
- PrecPostfix,
- PrecUnary,
- PrecMultiplicitave,
- PrecAdditive,
- PrecShift,
- PrecRelational,
- PrecEquality,
- PrecBitwiseAnd,
- PrecBitwiseXor,
- PrecBitwiseOr,
- PrecLogicalAnd,
- PrecLogicalOr,
- PrecConditional,
- PrecAssignment,
- PrecExpression
- };
-
- struct DeclarationStacks {
- typedef Vector<Node*, 16> NodeStack;
- enum { IsConstant = 1, HasInitializer = 2 } VarAttrs;
- typedef Vector<std::pair<Identifier, unsigned>, 16> VarStack;
- typedef Vector<FuncDeclNode*, 16> FunctionStack;
-
- DeclarationStacks(ExecState* e, NodeStack& n, VarStack& v, FunctionStack& f)
- : exec(e)
- , nodeStack(n)
- , varStack(v)
- , functionStack(f)
- {
- }
-
- ExecState* exec;
- NodeStack& nodeStack;
- VarStack& varStack;
- FunctionStack& functionStack;
- };
-
- class ParserRefCounted : Noncopyable {
- protected:
- ParserRefCounted() KJS_FAST_CALL;
- ParserRefCounted(PlacementNewAdoptType) KJS_FAST_CALL
- {
- }
-
- public:
- void ref() KJS_FAST_CALL;
- void deref() KJS_FAST_CALL;
- unsigned refcount() KJS_FAST_CALL;
-
- static void deleteNewObjects() KJS_FAST_CALL;
-
- virtual ~ParserRefCounted();
- };
-
- class Node : public ParserRefCounted {
- public:
- typedef DeclarationStacks::NodeStack NodeStack;
- typedef DeclarationStacks::VarStack VarStack;
- typedef DeclarationStacks::FunctionStack FunctionStack;
-
- Node() KJS_FAST_CALL;
- Node(PlacementNewAdoptType placementAdopt) KJS_FAST_CALL
- : ParserRefCounted(placementAdopt)
- {
- }
-
- UString toString() KJS_FAST_CALL;
- int lineNo() const KJS_FAST_CALL { return m_line; }
-
- // Serialization.
- virtual void streamTo(SourceStream&) KJS_FAST_CALL = 0;
- virtual Precedence precedence() const = 0;
- virtual bool needsParensIfLeftmost() const { return false; }
-
- // Used for iterative, depth-first traversal of the node tree. Does not cross function call boundaries.
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL { }
-
- protected:
- JSValue* setInterruptedCompletion(ExecState*);
- Node(JSType) KJS_FAST_CALL; // used by ExpressionNode
-
- // for use in execute()
- JSValue* setErrorCompletion(ExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
- JSValue* setErrorCompletion(ExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
-
- // for use in evaluate()
- JSValue* throwError(ExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, const char*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, const Identifier&) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*, Node*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*, const Identifier&) KJS_FAST_CALL;
-
- JSValue* throwUndefinedVariableError(ExecState*, const Identifier&) KJS_FAST_CALL;
-
- void handleException(ExecState*) KJS_FAST_CALL;
- void handleException(ExecState*, JSValue*) KJS_FAST_CALL;
-
- // for use in execute()
- JSValue* rethrowException(ExecState*) KJS_FAST_CALL;
-
- int m_line : 28;
- unsigned m_expectedReturnType : 3; // JSType
- };
-
- class ExpressionNode : public Node {
- public:
- ExpressionNode() KJS_FAST_CALL : Node() {}
- ExpressionNode(JSType expectedReturn) KJS_FAST_CALL
- : Node(expectedReturn)
- {
- }
-
- // Special constructor for cases where we overwrite an object in place.
- ExpressionNode(PlacementNewAdoptType) KJS_FAST_CALL
- : Node(PlacementNewAdopt)
- {
- }
-
- virtual bool isNumber() const KJS_FAST_CALL { return false; }
- virtual bool isLocation() const KJS_FAST_CALL { return false; }
- virtual bool isResolveNode() const KJS_FAST_CALL { return false; }
- virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return false; }
- virtual bool isDotAccessorNode() const KJS_FAST_CALL { return false; }
- virtual bool isFuncExprNode() const KJS_FAST_CALL { return false; }
-
- JSType expectedReturnType() const KJS_FAST_CALL { return static_cast<JSType>(m_expectedReturnType); }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL = 0;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
-
- // Used to optimize those nodes that do extra work when returning a result, even if the result has no semantic relevance
- virtual void optimizeForUnnecessaryResult() { }
- };
-
- class StatementNode : public Node {
- public:
- StatementNode() KJS_FAST_CALL;
- void setLoc(int line0, int line1) KJS_FAST_CALL;
- int firstLine() const KJS_FAST_CALL { return lineNo(); }
- int lastLine() const KJS_FAST_CALL { return m_lastLine; }
- virtual JSValue* execute(ExecState *exec) KJS_FAST_CALL = 0;
- void pushLabel(const Identifier& ident) KJS_FAST_CALL { m_labelStack.push(ident); }
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- virtual bool isEmptyStatement() const KJS_FAST_CALL { return false; }
- virtual bool isExprStatement() const KJS_FAST_CALL { return false; }
-
- protected:
- LabelStack m_labelStack;
-
- private:
- int m_lastLine;
- };
-
- class NullNode : public ExpressionNode {
- public:
- NullNode() KJS_FAST_CALL : ExpressionNode(NullType) {}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class FalseNode : public ExpressionNode {
- public:
- FalseNode() KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return false; }
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class TrueNode : public ExpressionNode {
- public:
- TrueNode() KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return true; }
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class PlaceholderTrueNode : public TrueNode {
- public:
- // Like TrueNode, but does not serialize as "true".
- PlaceholderTrueNode() KJS_FAST_CALL
- : TrueNode()
- {
- }
-
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class NumberNode : public ExpressionNode {
- public:
- NumberNode(double v) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_double(v)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; }
-
- virtual bool isNumber() const KJS_FAST_CALL { return true; }
- double value() const KJS_FAST_CALL { return m_double; }
- virtual void setValue(double d) KJS_FAST_CALL { m_double = d; }
-
- protected:
- double m_double;
- };
-
- class ImmediateNumberNode : public NumberNode {
- public:
- ImmediateNumberNode(JSValue* v, double d) KJS_FAST_CALL
- : NumberNode(d)
- , m_value(v)
- {
- ASSERT(v == JSImmediate::from(d));
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
-
- virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
-
- private:
- JSValue* m_value; // This is never a JSCell, only JSImmediate, thus no ProtectedPtr
- };
-
- class StringNode : public ExpressionNode {
- public:
- StringNode(const UString* v) KJS_FAST_CALL
- : ExpressionNode(StringType)
- , m_value(*v)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- UString m_value;
- };
-
- class RegExpNode : public ExpressionNode {
- public:
- RegExpNode(const UString& pattern, const UString& flags) KJS_FAST_CALL
- : m_regExp(new RegExp(pattern, flags))
- {
- }
-
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- RefPtr<RegExp> m_regExp;
- };
-
- class ThisNode : public ExpressionNode {
- public:
- ThisNode() KJS_FAST_CALL
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- };
-
- class ResolveNode : public ExpressionNode {
- public:
- ResolveNode(const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- }
-
- // Special constructor for cases where we overwrite an object in place.
- ResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- virtual bool isLocation() const KJS_FAST_CALL { return true; }
- virtual bool isResolveNode() const KJS_FAST_CALL { return true; }
- const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
-
- protected:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
- Identifier m_ident;
- size_t m_index; // Used by LocalVarAccessNode.
- };
-
- class LocalVarAccessNode : public ResolveNode {
- public:
- // Overwrites a ResolveNode in place.
- LocalVarAccessNode(size_t i) KJS_FAST_CALL
- : ResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
- };
-
- class ElementNode : public Node {
- public:
- ElementNode(int elision, ExpressionNode* node) KJS_FAST_CALL
- : m_elision(elision)
- , m_node(node)
- {
- }
-
- ElementNode(ElementNode* l, int elision, ExpressionNode* node) KJS_FAST_CALL
- : m_elision(elision)
- , m_node(node)
- {
- l->m_next = this;
- }
-
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- PassRefPtr<ElementNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
-
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
-
- private:
- friend class ArrayNode;
- ListRefPtr<ElementNode> m_next;
- int m_elision;
- RefPtr<ExpressionNode> m_node;
- };
-
- class ArrayNode : public ExpressionNode {
- public:
- ArrayNode(int elision) KJS_FAST_CALL
- : m_elision(elision)
- , m_optional(true)
- {
- }
-
- ArrayNode(ElementNode* element) KJS_FAST_CALL
- : m_element(element)
- , m_elision(0)
- , m_optional(false)
- {
- }
-
- ArrayNode(int elision, ElementNode* element) KJS_FAST_CALL
- : m_element(element)
- , m_elision(elision)
- , m_optional(true)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
-
- private:
- RefPtr<ElementNode> m_element;
- int m_elision;
- bool m_optional;
- };
-
- class PropertyNode : public Node {
- public:
- enum Type { Constant, Getter, Setter };
-
- PropertyNode(const Identifier& name, ExpressionNode* assign, Type type) KJS_FAST_CALL
- : m_name(name)
- , m_assign(assign)
- , m_type(type)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- const Identifier& name() const { return m_name; }
-
- private:
- friend class PropertyListNode;
- Identifier m_name;
- RefPtr<ExpressionNode> m_assign;
- Type m_type;
- };
-
- class PropertyListNode : public Node {
- public:
- PropertyListNode(PropertyNode* node) KJS_FAST_CALL
- : m_node(node)
- {
- }
-
- PropertyListNode(PropertyNode* node, PropertyListNode* list) KJS_FAST_CALL
- : m_node(node)
- {
- list->m_next = this;
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- PassRefPtr<PropertyListNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
-
- private:
- friend class ObjectLiteralNode;
- RefPtr<PropertyNode> m_node;
- ListRefPtr<PropertyListNode> m_next;
- };
-
- class ObjectLiteralNode : public ExpressionNode {
- public:
- ObjectLiteralNode() KJS_FAST_CALL
- {
- }
-
- ObjectLiteralNode(PropertyListNode* list) KJS_FAST_CALL
- : m_list(list)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPrimary; }
- virtual bool needsParensIfLeftmost() const { return true; }
-
- private:
- RefPtr<PropertyListNode> m_list;
- };
-
- class BracketAccessorNode : public ExpressionNode {
- public:
- BracketAccessorNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
-
- virtual bool isLocation() const KJS_FAST_CALL { return true; }
- virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return true; }
- ExpressionNode* base() KJS_FAST_CALL { return m_base.get(); }
- ExpressionNode* subscript() KJS_FAST_CALL { return m_subscript.get(); }
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
-
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- };
-
- class DotAccessorNode : public ExpressionNode {
- public:
- DotAccessorNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
-
- virtual bool isLocation() const KJS_FAST_CALL { return true; }
- virtual bool isDotAccessorNode() const KJS_FAST_CALL { return true; }
- ExpressionNode* base() const KJS_FAST_CALL { return m_base.get(); }
- const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
-
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class ArgumentListNode : public Node {
- public:
- ArgumentListNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- ArgumentListNode(ArgumentListNode* listNode, ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- listNode->m_next = this;
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- void evaluateList(ExecState*, List&) KJS_FAST_CALL;
- PassRefPtr<ArgumentListNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
-
- private:
- friend class ArgumentsNode;
- ListRefPtr<ArgumentListNode> m_next;
- RefPtr<ExpressionNode> m_expr;
- };
-
- class ArgumentsNode : public Node {
- public:
- ArgumentsNode() KJS_FAST_CALL
- {
- }
-
- ArgumentsNode(ArgumentListNode* listNode) KJS_FAST_CALL
- : m_listNode(listNode)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- void evaluateList(ExecState* exec, List& list) KJS_FAST_CALL { if (m_listNode) m_listNode->evaluateList(exec, list); }
-
- private:
- RefPtr<ArgumentListNode> m_listNode;
- };
-
- class NewExprNode : public ExpressionNode {
- public:
- NewExprNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- NewExprNode(ExpressionNode* expr, ArgumentsNode* args) KJS_FAST_CALL
- : m_expr(expr)
- , m_args(args)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecLeftHandSide; }
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
-
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallValueNode : public ExpressionNode {
- public:
- FunctionCallValueNode(ExpressionNode* expr, ArgumentsNode* args) KJS_FAST_CALL
- : m_expr(expr)
- , m_args(args)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallResolveNode : public ExpressionNode {
- public:
- FunctionCallResolveNode(const Identifier& ident, ArgumentsNode* args) KJS_FAST_CALL
- : m_ident(ident)
- , m_args(args)
- {
- }
-
- FunctionCallResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- , m_args(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- protected:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
-
- Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
- size_t m_index; // Used by LocalVarFunctionCallNode.
- };
-
- class LocalVarFunctionCallNode : public FunctionCallResolveNode {
- public:
- LocalVarFunctionCallNode(size_t i) KJS_FAST_CALL
- : FunctionCallResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
- };
-
- class FunctionCallBracketNode : public ExpressionNode {
- public:
- FunctionCallBracketNode(ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- , m_args(args)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class FunctionCallDotNode : public ExpressionNode {
- public:
- FunctionCallDotNode(ExpressionNode* base, const Identifier& ident, ArgumentsNode* args) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- , m_args(args)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecCall; }
-
- private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
-
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
- };
-
- class PrePostResolveNode : public ExpressionNode {
- public:
- PrePostResolveNode(const Identifier& ident) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_ident(ident)
- {
- }
-
- PrePostResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- {
- }
-
- protected:
- Identifier m_ident;
- size_t m_index; // Used by LocalVarPostfixNode.
- };
-
- class PostIncResolveNode : public PrePostResolveNode {
- public:
- PostIncResolveNode(const Identifier& ident) KJS_FAST_CALL
- : PrePostResolveNode(ident)
- {
- }
-
- PostIncResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : PrePostResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
- virtual void optimizeForUnnecessaryResult();
- };
-
- class PostIncLocalVarNode : public PostIncResolveNode {
- public:
- PostIncLocalVarNode(size_t i) KJS_FAST_CALL
- : PostIncResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void optimizeForUnnecessaryResult();
- };
-
- class PostIncConstNode : public PostIncResolveNode {
- public:
- PostIncConstNode(size_t i) KJS_FAST_CALL
- : PostIncResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PostDecResolveNode : public PrePostResolveNode {
- public:
- PostDecResolveNode(const Identifier& ident) KJS_FAST_CALL
- : PrePostResolveNode(ident)
- {
- }
-
- PostDecResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : PrePostResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
- virtual void optimizeForUnnecessaryResult();
- };
-
- class PostDecLocalVarNode : public PostDecResolveNode {
- public:
- PostDecLocalVarNode(size_t i) KJS_FAST_CALL
- : PostDecResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void optimizeForUnnecessaryResult();
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
- };
-
- class PostDecConstNode : public PostDecResolveNode {
- public:
- PostDecConstNode(size_t i) KJS_FAST_CALL
- : PostDecResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PostfixBracketNode : public ExpressionNode {
- public:
- PostfixBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- };
-
- class PostIncBracketNode : public PostfixBracketNode {
- public:
- PostIncBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : PostfixBracketNode(base, subscript)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PostDecBracketNode : public PostfixBracketNode {
- public:
- PostDecBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : PostfixBracketNode(base, subscript)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PostfixDotNode : public ExpressionNode {
- public:
- PostfixDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class PostIncDotNode : public PostfixDotNode {
- public:
- PostIncDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : PostfixDotNode(base, ident)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PostDecDotNode : public PostfixDotNode {
- public:
- PostDecDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : PostfixDotNode(base, ident)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PostfixErrorNode : public ExpressionNode {
- public:
- PostfixErrorNode(ExpressionNode* expr, Operator oper) KJS_FAST_CALL
- : m_expr(expr)
- , m_operator(oper)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- Operator m_operator;
- };
-
- class DeleteResolveNode : public ExpressionNode {
- public:
- DeleteResolveNode(const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- }
-
- DeleteResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- Identifier m_ident;
- };
-
- class LocalVarDeleteNode : public DeleteResolveNode {
- public:
- LocalVarDeleteNode() KJS_FAST_CALL
- : DeleteResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class DeleteBracketNode : public ExpressionNode {
- public:
- DeleteBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- };
-
- class DeleteDotNode : public ExpressionNode {
- public:
- DeleteDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class DeleteValueNode : public ExpressionNode {
- public:
- DeleteValueNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class VoidNode : public ExpressionNode {
- public:
- VoidNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class TypeOfResolveNode : public ExpressionNode {
- public:
- TypeOfResolveNode(const Identifier& ident) KJS_FAST_CALL
- : ExpressionNode(StringType)
- , m_ident(ident)
- {
- }
-
- TypeOfResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- {
- m_expectedReturnType = StringType;
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
-
- protected:
- Identifier m_ident;
- size_t m_index; // Used by LocalTypeOfNode.
- };
-
- class LocalVarTypeOfNode : public TypeOfResolveNode {
- public:
- LocalVarTypeOfNode(size_t i) KJS_FAST_CALL
- : TypeOfResolveNode(PlacementNewAdopt)
- {
- m_expectedReturnType = StringType;
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class TypeOfValueNode : public ExpressionNode {
- public:
- TypeOfValueNode(ExpressionNode* expr) KJS_FAST_CALL
- : ExpressionNode(StringType)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class PreIncResolveNode : public PrePostResolveNode {
- public:
- PreIncResolveNode(const Identifier& ident) KJS_FAST_CALL
- : PrePostResolveNode(ident)
- {
- }
-
- PreIncResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : PrePostResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class PreIncLocalVarNode : public PreIncResolveNode {
- public:
- PreIncLocalVarNode(size_t i) KJS_FAST_CALL
- : PreIncResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PreIncConstNode : public PreIncResolveNode {
- public:
- PreIncConstNode(size_t i) KJS_FAST_CALL
- : PreIncResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PreDecResolveNode : public PrePostResolveNode {
- public:
- PreDecResolveNode(const Identifier& ident) KJS_FAST_CALL
- : PrePostResolveNode(ident)
- {
- }
-
- PreDecResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : PrePostResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
- };
-
- class PreDecLocalVarNode : public PreDecResolveNode {
- public:
- PreDecLocalVarNode(size_t i) KJS_FAST_CALL
- : PreDecResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PreDecConstNode : public PreDecResolveNode {
- public:
- PreDecConstNode(size_t i) KJS_FAST_CALL
- : PreDecResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class PrefixBracketNode : public ExpressionNode {
- public:
- PrefixBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- };
-
- class PreIncBracketNode : public PrefixBracketNode {
- public:
- PreIncBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : PrefixBracketNode(base, subscript)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PreDecBracketNode : public PrefixBracketNode {
- public:
- PreDecBracketNode(ExpressionNode* base, ExpressionNode* subscript) KJS_FAST_CALL
- : PrefixBracketNode(base, subscript)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PrefixDotNode : public ExpressionNode {
- public:
- PrefixDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecPostfix; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- };
-
- class PreIncDotNode : public PrefixDotNode {
- public:
- PreIncDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : PrefixDotNode(base, ident)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PreDecDotNode : public PrefixDotNode {
- public:
- PreDecDotNode(ExpressionNode* base, const Identifier& ident) KJS_FAST_CALL
- : PrefixDotNode(base, ident)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- };
-
- class PrefixErrorNode : public ExpressionNode {
- public:
- PrefixErrorNode(ExpressionNode* expr, Operator oper) KJS_FAST_CALL
- : m_expr(expr)
- , m_operator(oper)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- Operator m_operator;
- };
-
- class UnaryPlusNode : public ExpressionNode {
- public:
- UnaryPlusNode(ExpressionNode* expr) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class NegateNode : public ExpressionNode {
- public:
- NegateNode(ExpressionNode* expr) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class BitwiseNotNode : public ExpressionNode {
- public:
- BitwiseNotNode(ExpressionNode* expr) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_expr;
- };
-
- class LogicalNotNode : public ExpressionNode {
- public:
- LogicalNotNode(ExpressionNode* expr) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecUnary; }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class MultNode : public ExpressionNode {
- public:
- MultNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicitave; }
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class DivNode : public ExpressionNode {
- public:
- DivNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicitave; }
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class ModNode : public ExpressionNode {
- public:
- ModNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMultiplicitave; }
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class AddNode : public ExpressionNode {
- public:
- AddNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAdditive; }
-
- protected:
- AddNode(ExpressionNode* term1, ExpressionNode* term2, JSType expectedReturn) KJS_FAST_CALL
- : ExpressionNode(expectedReturn)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
- };
-
- class AddNumbersNode : public AddNode {
- public:
- AddNumbersNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : AddNode(term1, term2, NumberType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*) KJS_FAST_CALL;
- };
-
- class AddStringLeftNode : public AddNode {
- public:
- AddStringLeftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : AddNode(term1, term2, StringType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class AddStringRightNode : public AddNode {
- public:
- AddStringRightNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : AddNode(term1, term2, StringType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class AddStringsNode : public AddNode {
- public:
- AddStringsNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : AddNode(term1, term2, StringType)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class SubNode : public ExpressionNode {
- public:
- SubNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAdditive; }
-
- private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class LeftShiftNode : public ExpressionNode {
- public:
- LeftShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class RightShiftNode : public ExpressionNode {
- public:
- RightShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class UnsignedRightShiftNode : public ExpressionNode {
- public:
- UnsignedRightShiftNode(ExpressionNode* term1, ExpressionNode* term2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_term1(term1)
- , m_term2(term2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecShift; }
- private:
- ALWAYS_INLINE uint32_t inlineEvaluateToUInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_term1;
- RefPtr<ExpressionNode> m_term2;
- };
-
- class LessNode : public ExpressionNode {
- public:
- LessNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- protected:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class LessNumbersNode : public LessNode {
- public:
- LessNumbersNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : LessNode(expr1, expr2)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
- };
-
- class LessStringsNode : public LessNode {
- public:
- LessStringsNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : LessNode(expr1, expr2)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
- };
-
- class GreaterNode : public ExpressionNode {
- public:
- GreaterNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class LessEqNode : public ExpressionNode {
- public:
- LessEqNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class GreaterEqNode : public ExpressionNode {
- public:
- GreaterEqNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class InstanceOfNode : public ExpressionNode {
- public:
- InstanceOfNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class InNode : public ExpressionNode {
- public:
- InNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecRelational; }
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class EqualNode : public ExpressionNode {
- public:
- EqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class NotEqualNode : public ExpressionNode {
- public:
- NotEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class StrictEqualNode : public ExpressionNode {
- public:
- StrictEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class NotStrictEqualNode : public ExpressionNode {
- public:
- NotStrictEqualNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecEquality; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class BitAndNode : public ExpressionNode {
- public:
- BitAndNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseAnd; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class BitOrNode : public ExpressionNode {
- public:
- BitOrNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseOr; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class BitXOrNode : public ExpressionNode {
- public:
- BitXOrNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(NumberType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecBitwiseXor; }
-
- private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- /**
- * m_expr1 && m_expr2, m_expr1 || m_expr2
- */
- class LogicalAndNode : public ExpressionNode {
- public:
- LogicalAndNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecLogicalAnd; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class LogicalOrNode : public ExpressionNode {
- public:
- LogicalOrNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : ExpressionNode(BooleanType)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecLogicalOr; }
-
- private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
-
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- /**
- * The ternary operator, "m_logical ? m_expr1 : m_expr2"
- */
- class ConditionalNode : public ExpressionNode {
- public:
- ConditionalNode(ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_logical(logical)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecConditional; }
-
- private:
- RefPtr<ExpressionNode> m_logical;
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class ReadModifyResolveNode : public ExpressionNode {
- public:
- ReadModifyResolveNode(const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL
- : m_ident(ident)
- , m_operator(oper)
- , m_right(right)
- {
- }
-
- ReadModifyResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- , m_right(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- Identifier m_ident;
- Operator m_operator;
- RefPtr<ExpressionNode> m_right;
- size_t m_index; // Used by ReadModifyLocalVarNode.
- };
-
- class ReadModifyLocalVarNode : public ReadModifyResolveNode {
- public:
- ReadModifyLocalVarNode(size_t i) KJS_FAST_CALL
- : ReadModifyResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class ReadModifyConstNode : public ReadModifyResolveNode {
- public:
- ReadModifyConstNode(size_t i) KJS_FAST_CALL
- : ReadModifyResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class AssignResolveNode : public ExpressionNode {
- public:
- AssignResolveNode(const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
- : m_ident(ident)
- , m_right(right)
- {
- }
-
- AssignResolveNode(PlacementNewAdoptType) KJS_FAST_CALL
- : ExpressionNode(PlacementNewAdopt)
- , m_ident(PlacementNewAdopt)
- , m_right(PlacementNewAdopt)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- size_t m_index; // Used by ReadModifyLocalVarNode.
- };
-
- class AssignLocalVarNode : public AssignResolveNode {
- public:
- AssignLocalVarNode(size_t i) KJS_FAST_CALL
- : AssignResolveNode(PlacementNewAdopt)
- {
- ASSERT(i != missingSymbolMarker());
- m_index = i;
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class AssignConstNode : public AssignResolveNode {
- public:
- AssignConstNode() KJS_FAST_CALL
- : AssignResolveNode(PlacementNewAdopt)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- };
-
- class ReadModifyBracketNode : public ExpressionNode {
- public:
- ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- , m_operator(oper)
- , m_right(right)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- Operator m_operator;
- RefPtr<ExpressionNode> m_right;
- };
-
- class AssignBracketNode : public ExpressionNode {
- public:
- AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right) KJS_FAST_CALL
- : m_base(base)
- , m_subscript(subscript)
- , m_right(right)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ExpressionNode> m_right;
- };
-
- class AssignDotNode : public ExpressionNode {
- public:
- AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- , m_right(right)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
- };
-
- class ReadModifyDotNode : public ExpressionNode {
- public:
- ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL
- : m_base(base)
- , m_ident(ident)
- , m_operator(oper)
- , m_right(right)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- Operator m_operator;
- RefPtr<ExpressionNode> m_right;
- };
-
- class AssignErrorNode : public ExpressionNode {
- public:
- AssignErrorNode(ExpressionNode* left, Operator oper, ExpressionNode* right) KJS_FAST_CALL
- : m_left(left)
- , m_operator(oper)
- , m_right(right)
- {
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecAssignment; }
-
- protected:
- RefPtr<ExpressionNode> m_left;
- Operator m_operator;
- RefPtr<ExpressionNode> m_right;
- };
-
- class CommaNode : public ExpressionNode {
- public:
- CommaNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : m_expr1(expr1)
- , m_expr2(expr2)
- {
- m_expr1->optimizeForUnnecessaryResult();
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecExpression; }
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- };
-
- class VarDeclCommaNode : public CommaNode {
- public:
- VarDeclCommaNode(ExpressionNode* expr1, ExpressionNode* expr2) KJS_FAST_CALL
- : CommaNode(expr1, expr2)
- {
- }
- virtual Precedence precedence() const { return PrecAssignment; }
- };
-
- class ConstDeclNode : public ExpressionNode {
- public:
- ConstDeclNode(const Identifier& ident, ExpressionNode* in) KJS_FAST_CALL;
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual KJS::JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- void evaluateSingle(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- PassRefPtr<ConstDeclNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
-
- Identifier m_ident;
- ListRefPtr<ConstDeclNode> m_next;
- RefPtr<ExpressionNode> m_init;
-
- private:
- void handleSlowCase(ExecState*, const ScopeChain&, JSValue*) KJS_FAST_CALL NEVER_INLINE;
- };
-
- class ConstStatementNode : public StatementNode {
- public:
- ConstStatementNode(ConstDeclNode* next) KJS_FAST_CALL
- : m_next(next)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ConstDeclNode> m_next;
- };
-
- typedef Vector<RefPtr<StatementNode> > StatementVector;
-
- class SourceElements : public ParserRefCounted {
- public:
- void append(PassRefPtr<StatementNode>);
- void releaseContentsIntoVector(StatementVector& destination)
- {
- ASSERT(destination.isEmpty());
- m_statements.swap(destination);
- }
-
- private:
- StatementVector m_statements;
- };
-
- class BlockNode : public StatementNode {
- public:
- BlockNode() KJS_FAST_CALL;
- BlockNode(SourceElements* children) KJS_FAST_CALL;
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- protected:
- StatementVector m_children;
- };
-
- class EmptyStatementNode : public StatementNode {
- public:
- EmptyStatementNode() KJS_FAST_CALL // debug
- {
- }
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual bool isEmptyStatement() const KJS_FAST_CALL { return true; }
- };
-
- class ExprStatementNode : public StatementNode {
- public:
- ExprStatementNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual bool isExprStatement() const KJS_FAST_CALL { return true; }
-
- ExpressionNode* expr() const { return m_expr.get(); }
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class VarStatementNode : public StatementNode {
- public:
- VarStatementNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class IfNode : public StatementNode {
- public:
- IfNode(ExpressionNode* condition, StatementNode* ifBlock) KJS_FAST_CALL
- : m_condition(condition)
- , m_ifBlock(ifBlock)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- protected:
- RefPtr<ExpressionNode> m_condition;
- RefPtr<StatementNode> m_ifBlock;
- };
-
- class IfElseNode : public IfNode {
- public:
- IfElseNode(ExpressionNode* condtion, StatementNode* ifBlock, StatementNode* elseBlock) KJS_FAST_CALL
- : IfNode(condtion, ifBlock)
- , m_elseBlock(elseBlock)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_elseBlock;
- };
-
- class DoWhileNode : public StatementNode {
- public:
- DoWhileNode(StatementNode* statement, ExpressionNode* expr) KJS_FAST_CALL
- : m_statement(statement)
- , m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_statement;
- RefPtr<ExpressionNode> m_expr;
- };
-
- class WhileNode : public StatementNode {
- public:
- WhileNode(ExpressionNode* expr, StatementNode* statement) KJS_FAST_CALL
- : m_expr(expr)
- , m_statement(statement)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- };
-
- class ForNode : public StatementNode {
- public:
- ForNode(ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) KJS_FAST_CALL
- : m_expr1(expr1 ? expr1 : new PlaceholderTrueNode)
- , m_expr2(expr2 ? expr2 : new PlaceholderTrueNode)
- , m_expr3(expr3 ? expr3 : new PlaceholderTrueNode)
- , m_statement(statement)
- , m_expr1WasVarDecl(expr1 && expr1WasVarDecl)
- {
- ASSERT(m_expr1);
- ASSERT(m_expr2);
- ASSERT(m_expr3);
- ASSERT(statement);
-
- m_expr1->optimizeForUnnecessaryResult();
- m_expr3->optimizeForUnnecessaryResult();
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- RefPtr<ExpressionNode> m_expr3;
- RefPtr<StatementNode> m_statement;
- bool m_expr1WasVarDecl;
- };
-
- class ForInNode : public StatementNode {
- public:
- ForInNode(ExpressionNode*, ExpressionNode*, StatementNode*) KJS_FAST_CALL;
- ForInNode(const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*) KJS_FAST_CALL;
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- Identifier m_ident;
- RefPtr<ExpressionNode> m_init;
- RefPtr<ExpressionNode> m_lexpr;
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- bool m_identIsVarDecl;
- };
-
- class ContinueNode : public StatementNode {
- public:
- ContinueNode() KJS_FAST_CALL
- {
- }
-
- ContinueNode(const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- }
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- Identifier m_ident;
- };
-
- class BreakNode : public StatementNode {
- public:
- BreakNode() KJS_FAST_CALL
- {
- }
-
- BreakNode(const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- }
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- Identifier m_ident;
- };
-
- class ReturnNode : public StatementNode {
- public:
- ReturnNode(ExpressionNode* value) KJS_FAST_CALL
- : m_value(value)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_value;
- };
-
- class WithNode : public StatementNode {
- public:
- WithNode(ExpressionNode* expr, StatementNode* statement) KJS_FAST_CALL
- : m_expr(expr)
- , m_statement(statement)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
- };
-
- class LabelNode : public StatementNode {
- public:
- LabelNode(const Identifier& label, StatementNode* statement) KJS_FAST_CALL
- : m_label(label)
- , m_statement(statement)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- Identifier m_label;
- RefPtr<StatementNode> m_statement;
- };
-
- class ThrowNode : public StatementNode {
- public:
- ThrowNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- };
-
- class TryNode : public StatementNode {
- public:
- TryNode(StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) KJS_FAST_CALL
- : m_tryBlock(tryBlock)
- , m_exceptionIdent(exceptionIdent)
- , m_catchBlock(catchBlock)
- , m_finallyBlock(finallyBlock)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_tryBlock;
- Identifier m_exceptionIdent;
- RefPtr<StatementNode> m_catchBlock;
- RefPtr<StatementNode> m_finallyBlock;
- };
-
- class ParameterNode : public Node {
- public:
- ParameterNode(const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- }
-
- ParameterNode(ParameterNode* l, const Identifier& ident) KJS_FAST_CALL
- : m_ident(ident)
- {
- l->m_next = this;
- }
-
- Identifier ident() KJS_FAST_CALL { return m_ident; }
- ParameterNode *nextParam() KJS_FAST_CALL { return m_next.get(); }
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- PassRefPtr<ParameterNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- friend class FuncDeclNode;
- friend class FuncExprNode;
- Identifier m_ident;
- ListRefPtr<ParameterNode> m_next;
- };
-
- class ScopeNode : public BlockNode {
- public:
- ScopeNode() KJS_FAST_CALL;
- ScopeNode(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- void setSource(const SourceCode& source) { m_source = source; }
- const SourceCode& source() const { return m_source; }
- const UString& sourceURL() const KJS_FAST_CALL { return m_source.provider()->url(); }
- intptr_t sourceID() const { return m_source.provider()->asID(); }
-
- void setData(SourceElements*, VarStack*, FunctionStack*);
-
- protected:
- void optimizeVariableAccess(ExecState*) KJS_FAST_CALL;
-
- VarStack m_varStack;
- FunctionStack m_functionStack;
-
- private:
- SourceCode m_source;
- };
-
- class ProgramNode : public ScopeNode {
- public:
- static ProgramNode* create(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
-
- private:
- ProgramNode(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
-
- Vector<size_t> m_varIndexes; // Storage indexes belonging to the nodes in m_varStack. (Recorded to avoid double lookup.)
- Vector<size_t> m_functionIndexes; // Storage indexes belonging to the nodes in m_functionStack. (Recorded to avoid double lookup.)
- };
-
- class EvalNode : public ScopeNode {
- public:
- static EvalNode* create(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
-
- private:
- EvalNode(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
- };
-
- class FunctionBodyNode : public ScopeNode {
- public:
- static FunctionBodyNode* create() KJS_FAST_CALL;
- static FunctionBodyNode* create(SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
- static FunctionBodyNode* create(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- SymbolTable& symbolTable() KJS_FAST_CALL { return m_symbolTable; }
-
- Vector<Identifier>& parameters() KJS_FAST_CALL { return m_parameters; }
- UString paramString() const KJS_FAST_CALL;
-
- protected:
- FunctionBodyNode() KJS_FAST_CALL;
- FunctionBodyNode(const SourceCode&, SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
-
- private:
- void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
-
- bool m_initialized;
- Vector<Identifier> m_parameters;
- SymbolTable m_symbolTable;
- };
-
- class FuncExprNode : public ExpressionNode {
- public:
- FuncExprNode(const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) KJS_FAST_CALL
- : m_ident(ident)
- , m_parameter(parameter)
- , m_body(body)
- {
- addParams();
- m_body->setSource(source);
- }
-
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { return PrecMember; }
- virtual bool needsParensIfLeftmost() const { return true; }
- virtual bool isFuncExprNode() const KJS_FAST_CALL { return true; }
-
- private:
- void addParams() KJS_FAST_CALL;
-
- // Used for streamTo
- friend class PropertyNode;
- Identifier m_ident;
- RefPtr<ParameterNode> m_parameter;
- RefPtr<FunctionBodyNode> m_body;
- };
-
- class FuncDeclNode : public StatementNode {
- public:
- FuncDeclNode(const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) KJS_FAST_CALL
- : m_ident(ident)
- , m_parameter(parameter)
- , m_body(body)
- {
- addParams();
- m_body->setSource(source);
- }
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- ALWAYS_INLINE FunctionImp* makeFunction(ExecState*) KJS_FAST_CALL;
-
- Identifier m_ident;
-
- private:
- void addParams() KJS_FAST_CALL;
-
- RefPtr<ParameterNode> m_parameter;
- RefPtr<FunctionBodyNode> m_body;
- };
-
- class CaseClauseNode : public Node {
- public:
- CaseClauseNode(ExpressionNode* expr) KJS_FAST_CALL
- : m_expr(expr)
- {
- }
-
- CaseClauseNode(ExpressionNode* expr, SourceElements* children) KJS_FAST_CALL
- : m_expr(expr)
- {
- if (children)
- children->releaseContentsIntoVector(m_children);
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- JSValue* executeStatements(ExecState*) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- StatementVector m_children;
- };
-
- class ClauseListNode : public Node {
- public:
- ClauseListNode(CaseClauseNode* clause) KJS_FAST_CALL
- : m_clause(clause)
- {
- }
-
- ClauseListNode(ClauseListNode* clauseList, CaseClauseNode* clause) KJS_FAST_CALL
- : m_clause(clause)
- {
- clauseList->m_next = this;
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- CaseClauseNode* getClause() const KJS_FAST_CALL { return m_clause.get(); }
- ClauseListNode* getNext() const KJS_FAST_CALL { return m_next.get(); }
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- PassRefPtr<ClauseListNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- friend class CaseBlockNode;
- RefPtr<CaseClauseNode> m_clause;
- ListRefPtr<ClauseListNode> m_next;
- };
-
- class CaseBlockNode : public Node {
- public:
- CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) KJS_FAST_CALL;
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- JSValue* executeBlock(ExecState*, JSValue *input) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
-
- private:
- RefPtr<ClauseListNode> m_list1;
- RefPtr<CaseClauseNode> m_defaultClause;
- RefPtr<ClauseListNode> m_list2;
- };
-
- class SwitchNode : public StatementNode {
- public:
- SwitchNode(ExpressionNode* expr, CaseBlockNode* block) KJS_FAST_CALL
- : m_expr(expr)
- , m_block(block)
- {
- }
-
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
-
- private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<CaseBlockNode> m_block;
- };
-
- class BreakpointCheckStatement : public StatementNode {
- public:
- BreakpointCheckStatement(PassRefPtr<StatementNode>) KJS_FAST_CALL;
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
- virtual void streamTo(SourceStream&) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
-
- private:
- RefPtr<StatementNode> m_statement;
- };
-
- struct ElementList {
- ElementNode* head;
- ElementNode* tail;
- };
-
- struct PropertyList {
- PropertyListNode* head;
- PropertyListNode* tail;
- };
-
- struct ArgumentList {
- ArgumentListNode* head;
- ArgumentListNode* tail;
- };
-
- struct ConstDeclList {
- ConstDeclNode* head;
- ConstDeclNode* tail;
- };
-
- struct ParameterList {
- ParameterNode* head;
- ParameterNode* tail;
- };
-
- struct ClauseList {
- ClauseListNode* head;
- ClauseListNode* tail;
- };
-
-} // namespace KJS
-
-#endif // NODES_H_
+++ /dev/null
-/*
- * Copyright (C) 2002 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "nodes.h"
-
-#include <wtf/MathExtras.h>
-#include <wtf/StringExtras.h>
-#include <wtf/unicode/Unicode.h>
-
-using namespace WTF;
-using namespace Unicode;
-
-namespace KJS {
-
-// A simple text streaming class that helps with code indentation.
-
-enum EndlType { Endl };
-enum IndentType { Indent };
-enum UnindentType { Unindent };
-enum DotExprType { DotExpr };
-
-class SourceStream {
-public:
- SourceStream()
- : m_numberNeedsParens(false)
- , m_atStartOfStatement(true)
- , m_precedence(PrecExpression)
- {
- }
-
- UString toString() const { return m_string; }
-
- SourceStream& operator<<(const Identifier&);
- SourceStream& operator<<(const UString&);
- SourceStream& operator<<(const char*);
- SourceStream& operator<<(double);
- SourceStream& operator<<(char);
- SourceStream& operator<<(EndlType);
- SourceStream& operator<<(IndentType);
- SourceStream& operator<<(UnindentType);
- SourceStream& operator<<(DotExprType);
- SourceStream& operator<<(Precedence);
- SourceStream& operator<<(Node*);
- template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); }
-
-private:
- UString m_string;
- UString m_spacesForIndentation;
- bool m_numberNeedsParens;
- bool m_atStartOfStatement;
- Precedence m_precedence;
-};
-
-// --------
-
-static UString escapeStringForPrettyPrinting(const UString& s)
-{
- UString escapedString;
-
- for (int i = 0; i < s.size(); i++) {
- unsigned short c = s.data()[i].unicode();
- switch (c) {
- case '\"':
- escapedString += "\\\"";
- break;
- case '\n':
- escapedString += "\\n";
- break;
- case '\r':
- escapedString += "\\r";
- break;
- case '\t':
- escapedString += "\\t";
- break;
- case '\\':
- escapedString += "\\\\";
- break;
- default:
- if (c < 128 && isPrintableChar(c))
- escapedString.append(c);
- else {
- char hexValue[7];
- snprintf(hexValue, 7, "\\u%04x", c);
- escapedString += hexValue;
- }
- }
- }
-
- return escapedString;
-}
-
-static const char* operatorString(Operator oper)
-{
- switch (oper) {
- case OpEqual:
- return "=";
- case OpMultEq:
- return "*=";
- case OpDivEq:
- return "/=";
- case OpPlusEq:
- return "+=";
- case OpMinusEq:
- return "-=";
- case OpLShift:
- return "<<=";
- case OpRShift:
- return ">>=";
- case OpURShift:
- return ">>>=";
- case OpAndEq:
- return "&=";
- case OpXOrEq:
- return "^=";
- case OpOrEq:
- return "|=";
- case OpModEq:
- return "%=";
- case OpPlusPlus:
- return "++";
- case OpMinusMinus:
- return "--";
- }
- ASSERT_NOT_REACHED();
- return "???";
-}
-
-static bool isParserRoundTripNumber(const UString& string)
-{
- double number = string.toDouble(false, false);
- if (isnan(number) || isinf(number))
- return false;
- return string == UString::from(number);
-}
-
-// --------
-
-SourceStream& SourceStream::operator<<(char c)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- UChar ch(c);
- m_string.append(ch);
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const char* s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s;
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(double value)
-{
- bool needParens = m_numberNeedsParens;
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
-
- if (needParens)
- m_string.append('(');
- m_string += UString::from(value);
- if (needParens)
- m_string.append(')');
-
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const UString& s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s;
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(const Identifier& s)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_string += s.ustring();
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(Node* n)
-{
- bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost());
- m_precedence = PrecExpression;
- if (!n)
- return *this;
- if (needParens) {
- m_numberNeedsParens = false;
- m_string.append('(');
- }
- n->streamTo(*this);
- if (needParens)
- m_string.append(')');
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(EndlType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = true;
- m_string.append('\n');
- m_string.append(m_spacesForIndentation);
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(IndentType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_spacesForIndentation += " ";
- return *this;
-}
-
-SourceStream& SourceStream::operator<<(UnindentType)
-{
- m_numberNeedsParens = false;
- m_atStartOfStatement = false;
- m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
- return *this;
-}
-
-inline SourceStream& SourceStream::operator<<(DotExprType)
-{
- m_numberNeedsParens = true;
- return *this;
-}
-
-inline SourceStream& SourceStream::operator<<(Precedence precedence)
-{
- m_precedence = precedence;
- return *this;
-}
-
-static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
- const char* operatorString, Node* left, Node* right)
-{
- s << precedence << left
- << ' ' << operatorString << ' '
- << static_cast<Precedence>(precedence - 1) << right;
-}
-
-template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
- Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
-{
- streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
-}
-
-static inline void bracketNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const RefPtr<ExpressionNode>& subscript)
-{
- s << PrecCall << base.get() << "[" << subscript.get() << "]";
-}
-
-static inline void dotNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const Identifier& ident)
-{
- s << DotExpr << PrecCall << base.get() << "." << ident;
-}
-
-// --------
-
-UString Node::toString()
-{
- SourceStream stream;
- streamTo(stream);
- return stream.toString();
-}
-
-// --------
-
-void NullNode::streamTo(SourceStream& s)
-{
- s << "null";
-}
-
-void FalseNode::streamTo(SourceStream& s)
-{
- s << "false";
-}
-
-void TrueNode::streamTo(SourceStream& s)
-{
- s << "true";
-}
-
-void PlaceholderTrueNode::streamTo(SourceStream&)
-{
-}
-
-void NumberNode::streamTo(SourceStream& s)
-{
- s << value();
-}
-
-void StringNode::streamTo(SourceStream& s)
-{
- s << '"' << escapeStringForPrettyPrinting(m_value) << '"';
-}
-
-void RegExpNode::streamTo(SourceStream& s)
-{
- s << '/' << m_regExp->pattern() << '/' << m_regExp->flags();
-}
-
-void ThisNode::streamTo(SourceStream& s)
-{
- s << "this";
-}
-
-void ResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident;
-}
-
-void ElementNode::streamTo(SourceStream& s)
-{
- for (const ElementNode* n = this; n; n = n->m_next.get()) {
- for (int i = 0; i < n->m_elision; i++)
- s << ',';
- s << PrecAssignment << n->m_node;
- if (n->m_next)
- s << ',';
- }
-}
-
-void ArrayNode::streamTo(SourceStream& s)
-{
- s << '[' << m_element;
- for (int i = 0; i < m_elision; i++)
- s << ',';
- // Parser consumes one elision comma if there's array elements
- // present in the expression.
- if (m_optional && m_element)
- s << ',';
- s << ']';
-}
-
-void ObjectLiteralNode::streamTo(SourceStream& s)
-{
- if (m_list)
- s << "{ " << m_list << " }";
- else
- s << "{ }";
-}
-
-void PropertyListNode::streamTo(SourceStream& s)
-{
- s << m_node;
- for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << n->m_node;
-}
-
-void PropertyNode::streamTo(SourceStream& s)
-{
- switch (m_type) {
- case Constant: {
- UString propertyName = name().ustring();
- if (isParserRoundTripNumber(propertyName))
- s << propertyName;
- else
- s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
- s << ": " << PrecAssignment << m_assign;
- break;
- }
- case Getter:
- case Setter: {
- const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get());
- if (m_type == Getter)
- s << "get ";
- else
- s << "set ";
- s << escapeStringForPrettyPrinting(name().ustring())
- << "(" << func->m_parameter << ')' << func->m_body;
- break;
- }
- }
-}
-
-void BracketAccessorNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void DotAccessorNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void ArgumentListNode::streamTo(SourceStream& s)
-{
- s << PrecAssignment << m_expr;
- for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << PrecAssignment << n->m_expr;
-}
-
-void ArgumentsNode::streamTo(SourceStream& s)
-{
- s << '(' << m_listNode << ')';
-}
-
-void NewExprNode::streamTo(SourceStream& s)
-{
- s << "new " << PrecMember << m_expr << m_args;
-}
-
-void FunctionCallValueNode::streamTo(SourceStream& s)
-{
- s << PrecCall << m_expr << m_args;
-}
-
-void FunctionCallResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident << m_args;
-}
-
-void FunctionCallBracketNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << m_args;
-}
-
-void FunctionCallDotNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << m_args;
-}
-
-void PostIncResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident << "++";
-}
-
-void PostDecResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident << "--";
-}
-
-void PostIncBracketNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << "++";
-}
-
-void PostDecBracketNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << "--";
-}
-
-void PostIncDotNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << "++";
-}
-
-void PostDecDotNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << "--";
-}
-
-void PostfixErrorNode::streamTo(SourceStream& s)
-{
- s << PrecLeftHandSide << m_expr;
- if (m_operator == OpPlusPlus)
- s << "++";
- else
- s << "--";
-}
-
-void DeleteResolveNode::streamTo(SourceStream& s)
-{
- s << "delete " << m_ident;
-}
-
-void DeleteBracketNode::streamTo(SourceStream& s)
-{
- s << "delete ";
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void DeleteDotNode::streamTo(SourceStream& s)
-{
- s << "delete ";
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void DeleteValueNode::streamTo(SourceStream& s)
-{
- s << "delete " << PrecUnary << m_expr;
-}
-
-void VoidNode::streamTo(SourceStream& s)
-{
- s << "void " << PrecUnary << m_expr;
-}
-
-void TypeOfValueNode::streamTo(SourceStream& s)
-{
- s << "typeof " << PrecUnary << m_expr;
-}
-
-void TypeOfResolveNode::streamTo(SourceStream& s)
-{
- s << "typeof " << m_ident;
-}
-
-void PreIncResolveNode::streamTo(SourceStream& s)
-{
- s << "++" << m_ident;
-}
-
-void PreDecResolveNode::streamTo(SourceStream& s)
-{
- s << "--" << m_ident;
-}
-
-void PreIncBracketNode::streamTo(SourceStream& s)
-{
- s << "++";
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void PreDecBracketNode::streamTo(SourceStream& s)
-{
- s << "--";
- bracketNodeStreamTo(s, m_base, m_subscript);
-}
-
-void PreIncDotNode::streamTo(SourceStream& s)
-{
- s << "++";
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void PreDecDotNode::streamTo(SourceStream& s)
-{
- s << "--";
- dotNodeStreamTo(s, m_base, m_ident);
-}
-
-void PrefixErrorNode::streamTo(SourceStream& s)
-{
- if (m_operator == OpPlusPlus)
- s << "++" << PrecUnary << m_expr;
- else
- s << "--" << PrecUnary << m_expr;
-}
-
-void UnaryPlusNode::streamTo(SourceStream& s)
-{
- s << "+ " << PrecUnary << m_expr;
-}
-
-void NegateNode::streamTo(SourceStream& s)
-{
- s << "- " << PrecUnary << m_expr;
-}
-
-void BitwiseNotNode::streamTo(SourceStream& s)
-{
- s << "~" << PrecUnary << m_expr;
-}
-
-void LogicalNotNode::streamTo(SourceStream& s)
-{
- s << "!" << PrecUnary << m_expr;
-}
-
-void MultNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_term1, m_term2);
-}
-
-void DivNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_term1, m_term2);
-}
-
-void ModNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_term1, m_term2);
-}
-
-void AddNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_term1, m_term2);
-}
-
-void SubNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_term1, m_term2);
-}
-
-void LeftShiftNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_term1, m_term2);
-}
-
-void RightShiftNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_term1, m_term2);
-}
-
-void UnsignedRightShiftNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_term1, m_term2);
-}
-
-void LessNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
-}
-
-void GreaterNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
-}
-
-void LessEqNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
-}
-
-void GreaterEqNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
-}
-
-void InstanceOfNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
-}
-
-void InNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
-}
-
-void EqualNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
-}
-
-void NotEqualNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
-}
-
-void StrictEqualNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
-}
-
-void NotStrictEqualNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
-}
-
-void BitAndNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
-}
-
-void BitXOrNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
-}
-
-void BitOrNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
-}
-
-void LogicalAndNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "&&", m_expr1, m_expr2);
-}
-
-void LogicalOrNode::streamTo(SourceStream& s)
-{
- streamLeftAssociativeBinaryOperator(s, precedence(), "||", m_expr1, m_expr2);
-}
-
-void ConditionalNode::streamTo(SourceStream& s)
-{
- s << PrecLogicalOr << m_logical
- << " ? " << PrecAssignment << m_expr1
- << " : " << PrecAssignment << m_expr2;
-}
-
-void ReadModifyResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignResolveNode::streamTo(SourceStream& s)
-{
- s << m_ident << " = " << PrecAssignment << m_right;
-}
-
-void ReadModifyBracketNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignBracketNode::streamTo(SourceStream& s)
-{
- bracketNodeStreamTo(s, m_base, m_subscript);
- s << " = " << PrecAssignment << m_right;
-}
-
-void ReadModifyDotNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void AssignDotNode::streamTo(SourceStream& s)
-{
- dotNodeStreamTo(s, m_base, m_ident);
- s << " = " << PrecAssignment << m_right;
-}
-
-void AssignErrorNode::streamTo(SourceStream& s)
-{
- s << PrecLeftHandSide << m_left << ' '
- << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
-}
-
-void CommaNode::streamTo(SourceStream& s)
-{
- s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
-}
-
-void ConstDeclNode::streamTo(SourceStream& s)
-{
- s << m_ident;
- if (m_init)
- s << " = " << m_init;
- for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
- s << ", " << m_ident;
- if (m_init)
- s << " = " << m_init;
- }
-}
-
-void ConstStatementNode::streamTo(SourceStream& s)
-{
- s << Endl << "const " << m_next << ';';
-}
-
-static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
-{
- for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
- s << *ptr;
-}
-
-void BlockNode::streamTo(SourceStream& s)
-{
- s << Endl << "{" << Indent;
- statementListStreamTo(m_children, s);
- s << Unindent << Endl << "}";
-}
-
-void ScopeNode::streamTo(SourceStream& s)
-{
- s << Endl << "{" << Indent;
-
- bool printedVar = false;
- for (size_t i = 0; i < m_varStack.size(); ++i) {
- if (m_varStack[i].second == 0) {
- if (!printedVar) {
- s << Endl << "var ";
- printedVar = true;
- } else
- s << ", ";
- s << m_varStack[i].first;
- }
- }
- if (printedVar)
- s << ';';
-
- statementListStreamTo(m_children, s);
- s << Unindent << Endl << "}";
-}
-
-void FunctionBodyNode::streamTo(SourceStream& s)
-{
- if (m_children.isEmpty())
- parser().reparse(this);
- ScopeNode::streamTo(s);
-}
-
-void EmptyStatementNode::streamTo(SourceStream& s)
-{
- s << Endl << ';';
-}
-
-void ExprStatementNode::streamTo(SourceStream& s)
-{
- s << Endl << m_expr << ';';
-}
-
-void VarStatementNode::streamTo(SourceStream& s)
-{
- s << Endl << "var " << m_expr << ';';
-}
-
-void IfNode::streamTo(SourceStream& s)
-{
- s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
-}
-
-void IfElseNode::streamTo(SourceStream& s)
-{
- IfNode::streamTo(s);
- s << Endl << "else" << Indent << m_elseBlock << Unindent;
-}
-
-void DoWhileNode::streamTo(SourceStream& s)
-{
- s << Endl << "do " << Indent << m_statement << Unindent << Endl
- << "while (" << m_expr << ");";
-}
-
-void WhileNode::streamTo(SourceStream& s)
-{
- s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
-}
-
-void ForNode::streamTo(SourceStream& s)
-{
- s << Endl << "for ("
- << (m_expr1WasVarDecl ? "var " : "")
- << m_expr1
- << "; " << m_expr2
- << "; " << m_expr3
- << ')' << Indent << m_statement << Unindent;
-}
-
-void ForInNode::streamTo(SourceStream& s)
-{
- s << Endl << "for (";
- if (m_identIsVarDecl) {
- s << "var ";
- if (m_init)
- s << m_init;
- else
- s << PrecLeftHandSide << m_lexpr;
- } else
- s << PrecLeftHandSide << m_lexpr;
-
- s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
-}
-
-void ContinueNode::streamTo(SourceStream& s)
-{
- s << Endl << "continue";
- if (!m_ident.isNull())
- s << ' ' << m_ident;
- s << ';';
-}
-
-void BreakNode::streamTo(SourceStream& s)
-{
- s << Endl << "break";
- if (!m_ident.isNull())
- s << ' ' << m_ident;
- s << ';';
-}
-
-void ReturnNode::streamTo(SourceStream& s)
-{
- s << Endl << "return";
- if (m_value)
- s << ' ' << m_value;
- s << ';';
-}
-
-void WithNode::streamTo(SourceStream& s)
-{
- s << Endl << "with (" << m_expr << ") " << m_statement;
-}
-
-void CaseClauseNode::streamTo(SourceStream& s)
-{
- s << Endl;
- if (m_expr)
- s << "case " << m_expr;
- else
- s << "default";
- s << ":" << Indent;
- statementListStreamTo(m_children, s);
- s << Unindent;
-}
-
-void ClauseListNode::streamTo(SourceStream& s)
-{
- for (const ClauseListNode* n = this; n; n = n->getNext())
- s << n->getClause();
-}
-
-void CaseBlockNode::streamTo(SourceStream& s)
-{
- for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
- s << n->getClause();
- s << m_defaultClause;
- for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
- s << n->getClause();
-}
-
-void SwitchNode::streamTo(SourceStream& s)
-{
- s << Endl << "switch (" << m_expr << ") {"
- << Indent << m_block << Unindent
- << Endl << "}";
-}
-
-void LabelNode::streamTo(SourceStream& s)
-{
- s << Endl << m_label << ":" << Indent << m_statement << Unindent;
-}
-
-void ThrowNode::streamTo(SourceStream& s)
-{
- s << Endl << "throw " << m_expr << ';';
-}
-
-void TryNode::streamTo(SourceStream& s)
-{
- s << Endl << "try " << m_tryBlock;
- if (m_catchBlock)
- s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
- if (m_finallyBlock)
- s << Endl << "finally " << m_finallyBlock;
-}
-
-void ParameterNode::streamTo(SourceStream& s)
-{
- s << m_ident;
- for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
- s << ", " << n->m_ident;
-}
-
-void FuncDeclNode::streamTo(SourceStream& s)
-{
- s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
-}
-
-void FuncExprNode::streamTo(SourceStream& s)
-{
- s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
- * Copyright (C) 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- *
- */
-
-#include "config.h"
-#include "number_object.h"
-#include "number_object.lut.h"
-
-#include "dtoa.h"
-#include "error_object.h"
-#include "operations.h"
-#include <wtf/Assertions.h>
-#include <wtf/MathExtras.h>
-#include <wtf/Vector.h>
-
-namespace KJS {
-
-// ------------------------------ NumberInstance ----------------------------
-
-const ClassInfo NumberInstance::info = { "Number", 0, 0 };
-
-NumberInstance::NumberInstance(JSObject* proto)
- : JSWrapperObject(proto)
-{
-}
-
-// ------------------------------ NumberPrototype ---------------------------
-
-static JSValue* numberProtoFuncToString(ExecState*, JSObject*, const List&);
-static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
-static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, const List&);
-static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, const List&);
-static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, const List&);
-static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, const List&);
-
-// ECMA 15.7.4
-
-NumberPrototype::NumberPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
- : NumberInstance(objectPrototype)
-{
- setInternalValue(jsNumber(0));
-
- // The constructor will be added later, after NumberObjectImp has been constructed
-
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
-}
-
-// ------------------------------ Functions ---------------------------
-
-// ECMA 15.7.4.2 - 15.7.4.7
-
-static UString integer_part_noexp(double d)
-{
- int decimalPoint;
- int sign;
- char* result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL);
- bool resultIsInfOrNan = (decimalPoint == 9999);
- size_t length = strlen(result);
-
- UString str = sign ? "-" : "";
- if (resultIsInfOrNan)
- str += result;
- else if (decimalPoint <= 0)
- str += "0";
- else {
- Vector<char, 1024> buf(decimalPoint + 1);
-
- // FIXME: Remove use of strcpy() and strncpy()
- if (static_cast<int>(length) <= decimalPoint) {
- strcpy(buf.data(), result);
- memset(buf.data() + length, '0', decimalPoint - length);
- } else
- strncpy(buf.data(), result, decimalPoint);
-
- buf[decimalPoint] = '\0';
- str += UString(buf.data());
- }
-
- kjs_freedtoa(result);
-
- return str;
-}
-
-static UString char_sequence(char c, int count)
-{
- Vector<char, 2048> buf(count + 1, c);
- buf[count] = '\0';
-
- return UString(buf.data());
-}
-
-static double intPow10(int e)
-{
- // This function uses the "exponentiation by squaring" algorithm and
- // long double to quickly and precisely calculate integer powers of 10.0.
-
- // This is a handy workaround for <rdar://problem/4494756>
-
- if (e == 0)
- return 1.0;
-
- bool negative = e < 0;
- unsigned exp = negative ? -e : e;
-
- long double result = 10.0;
- bool foundOne = false;
- for (int bit = 31; bit >= 0; bit--) {
- if (!foundOne) {
- if ((exp >> bit) & 1)
- foundOne = true;
- } else {
- result = result * result;
- if ((exp >> bit) & 1)
- result = result * 10.0;
- }
- }
-
- if (negative)
- return static_cast<double>(1.0 / result);
- return static_cast<double>(result);
-}
-
-
-JSValue* numberProtoFuncToString(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
-
- double radixAsDouble = args[0]->toInteger(exec); // nan -> 0
- if (radixAsDouble == 10 || args[0]->isUndefined())
- return jsString(v->toString(exec));
-
- if (radixAsDouble < 2 || radixAsDouble > 36)
- return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");
-
- int radix = static_cast<int>(radixAsDouble);
- const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- // INT_MAX results in 1024 characters left of the dot with radix 2
- // give the same space on the right side. safety checks are in place
- // unless someone finds a precise rule.
- char s[2048 + 3];
- const char* lastCharInString = s + sizeof(s) - 1;
- double x = v->toNumber(exec);
- if (isnan(x) || isinf(x))
- return jsString(UString::from(x));
-
- bool isNegative = x < 0.0;
- if (isNegative)
- x = -x;
-
- double integerPart = floor(x);
- char* decimalPoint = s + sizeof(s) / 2;
-
- // convert integer portion
- char* p = decimalPoint;
- double d = integerPart;
- do {
- int remainderDigit = static_cast<int>(fmod(d, radix));
- *--p = digits[remainderDigit];
- d /= radix;
- } while ((d <= -1.0 || d >= 1.0) && s < p);
-
- if (isNegative)
- *--p = '-';
- char* startOfResultString = p;
- ASSERT(s <= startOfResultString);
-
- d = x - integerPart;
- p = decimalPoint;
- const double epsilon = 0.001; // TODO: guessed. base on radix ?
- bool hasFractionalPart = (d < -epsilon || d > epsilon);
- if (hasFractionalPart) {
- *p++ = '.';
- do {
- d *= radix;
- const int digit = static_cast<int>(d);
- *p++ = digits[digit];
- d -= digit;
- } while ((d < -epsilon || d > epsilon) && p < lastCharInString);
- }
- *p = '\0';
- ASSERT(p < s + sizeof(s));
-
- return jsString(startOfResultString);
-}
-
-JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- // TODO
- return jsString(static_cast<NumberInstance*>(thisObj)->internalValue()->toString(exec));
-}
-
-JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- return static_cast<NumberInstance*>(thisObj)->internalValue()->toJSNumber(exec);
-}
-
-JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
-
- JSValue* fractionDigits = args[0];
- double df = fractionDigits->toInteger(exec);
- if (!(df >= 0 && df <= 20))
- return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");
- int f = (int)df;
-
- double x = v->toNumber(exec);
- if (isnan(x))
- return jsString("NaN");
-
- UString s;
- if (x < 0) {
- s.append('-');
- x = -x;
- } else if (x == -0.0)
- x = 0;
-
- if (x >= pow(10.0, 21.0))
- return jsString(s + UString::from(x));
-
- const double tenToTheF = pow(10.0, f);
- double n = floor(x * tenToTheF);
- if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))
- n++;
-
- UString m = integer_part_noexp(n);
-
- int k = m.size();
- if (k <= f) {
- UString z;
- for (int i = 0; i < f + 1 - k; i++)
- z.append('0');
- m = z + m;
- k = f + 1;
- ASSERT(k == m.size());
- }
- int kMinusf = k - f;
- if (kMinusf < m.size())
- return jsString(s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));
- return jsString(s + m.substr(0, kMinusf));
-}
-
-static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
-{
- if (fractionalDigits <= 0)
- return;
-
- int fDigitsInResult = static_cast<int>(resultLength) - 1;
- buf[i++] = '.';
- if (fDigitsInResult > 0) {
- if (fractionalDigits < fDigitsInResult) {
- strncpy(buf + i, result + 1, fractionalDigits);
- i += fractionalDigits;
- } else {
- // FIXME: Remove use of strcpy()
- strcpy(buf + i, result + 1);
- i += static_cast<int>(resultLength) - 1;
- }
- }
-
- for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)
- buf[i++] = '0';
-}
-
-static void exponentialPartToString(char* buf, int& i, int decimalPoint)
-{
- buf[i++] = 'e';
- buf[i++] = (decimalPoint >= 0) ? '+' : '-';
- // decimalPoint can't be more than 3 digits decimal given the
- // nature of float representation
- int exponential = decimalPoint - 1;
- if (exponential < 0)
- exponential *= -1;
- if (exponential >= 100)
- buf[i++] = static_cast<char>('0' + exponential / 100);
- if (exponential >= 10)
- buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
- buf[i++] = static_cast<char>('0' + exponential % 10);
-}
-
-JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
-
- double x = v->toNumber(exec);
-
- if (isnan(x) || isinf(x))
- return jsString(UString::from(x));
-
- JSValue* fractionalDigitsValue = args[0];
- double df = fractionalDigitsValue->toInteger(exec);
- if (!(df >= 0 && df <= 20))
- return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");
- int fractionalDigits = (int)df;
- bool includeAllDigits = fractionalDigitsValue->isUndefined();
-
- int decimalAdjust = 0;
- if (x && !includeAllDigits) {
- double logx = floor(log10(fabs(x)));
- x /= pow(10.0, logx);
- const double tenToTheF = pow(10.0, fractionalDigits);
- double fx = floor(x * tenToTheF) / tenToTheF;
- double cx = ceil(x * tenToTheF) / tenToTheF;
-
- if (fabs(fx - x) < fabs(cx - x))
- x = fx;
- else
- x = cx;
-
- decimalAdjust = static_cast<int>(logx);
- }
-
- if (isnan(x))
- return jsString("NaN");
-
- if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0
- x = 0;
-
- int decimalPoint;
- int sign;
- char* result = kjs_dtoa(x, 0, 0, &decimalPoint, &sign, NULL);
- size_t resultLength = strlen(result);
- decimalPoint += decimalAdjust;
-
- int i = 0;
- char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)
- if (sign)
- buf[i++] = '-';
-
- if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999??
- // FIXME: Remove magic number 80
- strlcpy(buf + i, result, 80 - i);
- else {
- buf[i++] = result[0];
-
- if (includeAllDigits)
- fractionalDigits = static_cast<int>(resultLength) - 1;
-
- fractionalPartToString(buf, i, result, resultLength, fractionalDigits);
- exponentialPartToString(buf, i, decimalPoint);
- buf[i++] = '\0';
- }
- ASSERT(i <= 80);
-
- kjs_freedtoa(result);
-
- return jsString(buf);
-}
-
-JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
-
- double doublePrecision = args[0]->toIntegerPreserveNaN(exec);
- double x = v->toNumber(exec);
- if (args[0]->isUndefined() || isnan(x) || isinf(x))
- return jsString(v->toString(exec));
-
- UString s;
- if (x < 0) {
- s = "-";
- x = -x;
- }
-
- if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
- return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
- int precision = (int)doublePrecision;
-
- int e = 0;
- UString m;
- if (x) {
- e = static_cast<int>(log10(x));
- double tens = intPow10(e - precision + 1);
- double n = floor(x / tens);
- if (n < intPow10(precision - 1)) {
- e = e - 1;
- tens = intPow10(e - precision + 1);
- n = floor(x / tens);
- }
-
- if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))
- ++n;
- // maintain n < 10^(precision)
- if (n >= intPow10(precision)) {
- n /= 10.0;
- e += 1;
- }
- ASSERT(intPow10(precision - 1) <= n);
- ASSERT(n < intPow10(precision));
-
- m = integer_part_noexp(n);
- if (e < -6 || e >= precision) {
- if (m.size() > 1)
- m = m.substr(0, 1) + "." + m.substr(1);
- if (e >= 0)
- return jsString(s + m + "e+" + UString::from(e));
- return jsString(s + m + "e-" + UString::from(-e));
- }
- } else {
- m = char_sequence('0', precision);
- e = 0;
- }
-
- if (e == precision - 1)
- return jsString(s + m);
- if (e >= 0) {
- if (e + 1 < m.size())
- return jsString(s + m.substr(0, e + 1) + "." + m.substr(e + 1));
- return jsString(s + m);
- }
- return jsString(s + "0." + char_sequence('0', -(e + 1)) + m);
-}
-
-// ------------------------------ NumberObjectImp ------------------------------
-
-const ClassInfo NumberObjectImp::info = { "Function", &InternalFunctionImp::info, &numberTable };
-
-/* Source for number_object.lut.h
-@begin numberTable 5
- NaN NumberObjectImp::NaNValue DontEnum|DontDelete|ReadOnly
- NEGATIVE_INFINITY NumberObjectImp::NegInfinity DontEnum|DontDelete|ReadOnly
- POSITIVE_INFINITY NumberObjectImp::PosInfinity DontEnum|DontDelete|ReadOnly
- MAX_VALUE NumberObjectImp::MaxValue DontEnum|DontDelete|ReadOnly
- MIN_VALUE NumberObjectImp::MinValue DontEnum|DontDelete|ReadOnly
-@end
-*/
-NumberObjectImp::NumberObjectImp(ExecState* exec, FunctionPrototype* funcProto, NumberPrototype* numberProto)
- : InternalFunctionImp(funcProto, numberProto->classInfo()->className)
-{
- // Number.Prototype
- putDirect(exec->propertyNames().prototype, numberProto, DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
-}
-
-bool NumberObjectImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getStaticValueSlot<NumberObjectImp, InternalFunctionImp>(exec, &numberTable, this, propertyName, slot);
-}
-
-JSValue* NumberObjectImp::getValueProperty(ExecState*, int token) const
-{
- // ECMA 15.7.3
- switch (token) {
- case NaNValue:
- return jsNaN();
- case NegInfinity:
- return jsNumberCell(-Inf);
- case PosInfinity:
- return jsNumberCell(Inf);
- case MaxValue:
- return jsNumberCell(1.7976931348623157E+308);
- case MinValue:
- return jsNumberCell(5E-324);
- }
- ASSERT_NOT_REACHED();
- return jsNull();
-}
-
-bool NumberObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.7.1
-JSObject* NumberObjectImp::construct(ExecState* exec, const List& args)
-{
- JSObject* proto = exec->lexicalGlobalObject()->numberPrototype();
- NumberInstance* obj = new NumberInstance(proto);
-
- // FIXME: Check args[0]->isUndefined() instead of args.isEmpty()?
- double n = args.isEmpty() ? 0 : args[0]->toNumber(exec);
- obj->setInternalValue(jsNumber(n));
- return obj;
-}
-
-// ECMA 15.7.2
-JSValue* NumberObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- // FIXME: Check args[0]->isUndefined() instead of args.isEmpty()?
- return jsNumber(args.isEmpty() ? 0 : args[0]->toNumber(exec));
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef NUMBER_OBJECT_H_
-#define NUMBER_OBJECT_H_
-
-#include "function_object.h"
-#include "JSWrapperObject.h"
-
-namespace KJS {
-
- class NumberInstance : public JSWrapperObject {
- public:
- NumberInstance(JSObject* prototype);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * The initial value of Number.prototype (and thus all objects created
- * with the Number constructor
- */
- class NumberPrototype : public NumberInstance {
- public:
- NumberPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Number" property
- */
- class NumberObjectImp : public InternalFunctionImp {
- public:
- NumberObjectImp(ExecState*, FunctionPrototype*, NumberPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
-
- bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- JSValue* getValueProperty(ExecState*, int token) const;
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
-
- JSObject* construct(const List&);
- };
-
-} // namespace KJS
-
-#endif // NUMBER_OBJECT_H_
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
- * Copyright (C) 2007 Eric Seidel (eric@webkit.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "object.h"
-
-#include "date_object.h"
-#include "error_object.h"
-#include "lookup.h"
-#include "nodes.h"
-#include "operations.h"
-#include "PropertyNameArray.h"
-#include <math.h>
-#include <wtf/Assertions.h>
-
-// maximum global call stack size. Protects against accidental or
-// malicious infinite recursions. Define to -1 if you want no limit.
-// In real-world testing it appears ok to bump the stack depth count to 500.
-// This of course is dependent on stack frame size.
-#define KJS_MAX_STACK 500
-
-#define JAVASCRIPT_CALL_TRACING 0
-#define JAVASCRIPT_MARK_TRACING 0
-
-#if JAVASCRIPT_CALL_TRACING
-static bool _traceJavaScript = false;
-
-extern "C" {
- void setTraceJavaScript(bool f)
- {
- _traceJavaScript = f;
- }
-
- static bool traceJavaScript()
- {
- return _traceJavaScript;
- }
-}
-#endif
-
-namespace KJS {
-
-// ------------------------------ Object ---------------------------------------
-
-JSValue *JSObject::call(ExecState *exec, JSObject *thisObj, const List &args)
-{
- ASSERT(implementsCall());
-
-#if KJS_MAX_STACK > 0
- static int depth = 0; // sum of all extant function calls
-
-#if JAVASCRIPT_CALL_TRACING
- static bool tracing = false;
- if (traceJavaScript() && !tracing) {
- tracing = true;
- for (int i = 0; i < depth; i++)
- putchar (' ');
- printf ("*** calling: %s\n", toString(exec).ascii());
- for (int j = 0; j < args.size(); j++) {
- for (int i = 0; i < depth; i++)
- putchar (' ');
- printf ("*** arg[%d] = %s\n", j, args[j]->toString(exec).ascii());
- }
- tracing = false;
- }
-#endif
-
- if (++depth > KJS_MAX_STACK) {
- --depth;
- return throwError(exec, RangeError, "Maximum call stack size exceeded.");
- }
-#endif
-
- JSValue *ret = callAsFunction(exec,thisObj,args);
-
-#if KJS_MAX_STACK > 0
- --depth;
-#endif
-
-#if JAVASCRIPT_CALL_TRACING
- if (traceJavaScript() && !tracing) {
- tracing = true;
- for (int i = 0; i < depth; i++)
- putchar (' ');
- printf ("*** returning: %s\n", ret->toString(exec).ascii());
- tracing = false;
- }
-#endif
-
- return ret;
-}
-
-// ------------------------------ JSObject ------------------------------------
-
-void JSObject::mark()
-{
- JSCell::mark();
-
-#if JAVASCRIPT_MARK_TRACING
- static int markStackDepth = 0;
- markStackDepth++;
- for (int i = 0; i < markStackDepth; i++)
- putchar('-');
-
- printf("%s (%p)\n", className().UTF8String().c_str(), this);
-#endif
-
- JSValue *proto = _proto;
- if (!proto->marked())
- proto->mark();
-
- _prop.mark();
-
-#if JAVASCRIPT_MARK_TRACING
- markStackDepth--;
-#endif
-}
-
-JSType JSObject::type() const
-{
- return ObjectType;
-}
-
-const ClassInfo *JSObject::classInfo() const
-{
- return 0;
-}
-
-UString JSObject::className() const
-{
- const ClassInfo *ci = classInfo();
- if ( ci )
- return ci->className;
- return "Object";
-}
-
-JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const
-{
- PropertySlot slot;
-
- if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
-
- return jsUndefined();
-}
-
-JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const
-{
- PropertySlot slot;
- if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
-
- return jsUndefined();
-}
-
-bool JSObject::getPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
-{
- JSObject *imp = this;
-
- while (true) {
- if (imp->getOwnPropertySlot(exec, propertyName, slot))
- return true;
-
- JSValue *proto = imp->_proto;
- if (!proto->isObject())
- break;
-
- imp = static_cast<JSObject *>(proto);
- }
-
- return false;
-}
-
-bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
-{
- return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
-}
-
-static void throwSetterError(ExecState *exec)
-{
- throwError(exec, TypeError, "setting a property that has only a getter");
-}
-
-// ECMA 8.6.2.2
-void JSObject::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
-{
- ASSERT(value);
-
- if (propertyName == exec->propertyNames().underscoreProto) {
- JSObject* proto = value->getObject();
- while (proto) {
- if (proto == this)
- throwError(exec, GeneralError, "cyclic __proto__ value");
- proto = proto->prototype() ? proto->prototype()->getObject() : 0;
- }
-
- setPrototype(value);
- return;
- }
-
- // The put calls from JavaScript execution either have no attributes set, or in some cases
- // have DontDelete set. For those calls, respect the ReadOnly flag.
- bool checkReadOnly = !(attr & ~DontDelete);
-
- // Check if there are any setters or getters in the prototype chain
- JSObject *obj = this;
- bool hasGettersOrSetters = false;
- while (true) {
- if (obj->_prop.hasGetterSetterProperties()) {
- hasGettersOrSetters = true;
- break;
- }
-
- if (!obj->_proto->isObject())
- break;
-
- obj = static_cast<JSObject *>(obj->_proto);
- }
-
- if (hasGettersOrSetters) {
- if (checkReadOnly && !canPut(exec, propertyName))
- return;
-
- obj = this;
- while (true) {
- unsigned attributes;
- if (JSValue *gs = obj->_prop.get(propertyName, attributes)) {
- if (attributes & GetterSetter) {
- JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter();
-
- if (!setterFunc) {
- throwSetterError(exec);
- return;
- }
-
- List args;
- args.append(value);
-
- setterFunc->call(exec, this, args);
- return;
- } else {
- // If there's an existing property on the object or one of its
- // prototype it should be replaced, so we just break here.
- break;
- }
- }
-
- if (!obj->_proto->isObject())
- break;
-
- obj = static_cast<JSObject *>(obj->_proto);
- }
- }
-
- _prop.put(propertyName, value, attr, checkReadOnly);
-}
-
-void JSObject::put(ExecState *exec, unsigned propertyName,
- JSValue *value, int attr)
-{
- put(exec, Identifier::from(propertyName), value, attr);
-}
-
-// ECMA 8.6.2.3
-bool JSObject::canPut(ExecState *, const Identifier &propertyName) const
-{
- unsigned attributes;
-
- // Don't look in the prototype here. We can always put an override
- // in the object, even if the prototype has a ReadOnly property.
- // Also, there is no need to check the static property table, as this
- // would have been done by the subclass already.
-
- if (!_prop.get(propertyName, attributes))
- return true;
-
- return !(attributes & ReadOnly);
-}
-
-// ECMA 8.6.2.4
-bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const
-{
- PropertySlot slot;
- return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
-}
-
-bool JSObject::hasProperty(ExecState *exec, unsigned propertyName) const
-{
- PropertySlot slot;
- return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
-}
-
-// ECMA 8.6.2.5
-bool JSObject::deleteProperty(ExecState* /*exec*/, const Identifier &propertyName)
-{
- unsigned attributes;
- JSValue *v = _prop.get(propertyName, attributes);
- if (v) {
- if ((attributes & DontDelete))
- return false;
- _prop.remove(propertyName);
- if (attributes & GetterSetter)
- _prop.setHasGetterSetterProperties(_prop.containsGettersOrSetters());
- return true;
- }
-
- // Look in the static hashtable of properties
- const HashEntry* entry = findPropertyHashEntry(propertyName);
- if (entry && entry->attr & DontDelete)
- return false; // this builtin property can't be deleted
- return true;
-}
-
-bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
-{
- PropertySlot slot;
- return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
-}
-
-bool JSObject::deleteProperty(ExecState *exec, unsigned propertyName)
-{
- return deleteProperty(exec, Identifier::from(propertyName));
-}
-
-static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObject *object, const Identifier &propertyName) {
- JSValue *v = object->get(exec, propertyName);
- if (v->isObject()) {
- JSObject *o = static_cast<JSObject*>(v);
- if (o->implementsCall()) { // spec says "not primitive type" but ...
- JSObject *thisObj = const_cast<JSObject*>(object);
- JSValue* def = o->call(exec, thisObj, exec->emptyList());
- JSType defType = def->type();
- ASSERT(defType != GetterSetterType);
- if (defType != ObjectType)
- return def;
- }
- }
- return NULL;
-}
-
-bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
-{
- result = defaultValue(exec, NumberType);
- number = result->toNumber(exec);
- return !result->isString();
-}
-
-// ECMA 8.6.2.6
-JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
-{
- /* Prefer String for Date objects */
- if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
- if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
- return v;
- if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
- return v;
- } else {
- if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
- return v;
- if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
- return v;
- }
-
- if (exec->hadException())
- return exec->exception();
-
- return throwError(exec, TypeError, "No default value");
-}
-
-const HashEntry* JSObject::findPropertyHashEntry(const Identifier& propertyName) const
-{
- for (const ClassInfo *info = classInfo(); info; info = info->parentClass) {
- if (const HashTable *propHashTable = info->propHashTable) {
- if (const HashEntry *e = Lookup::findEntry(propHashTable, propertyName))
- return e;
- }
- }
- return 0;
-}
-
-void JSObject::defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc)
-{
- JSValue *o = getDirect(propertyName);
- GetterSetterImp *gs;
-
- if (o && o->type() == GetterSetterType) {
- gs = static_cast<GetterSetterImp *>(o);
- } else {
- gs = new GetterSetterImp;
- putDirect(propertyName, gs, GetterSetter);
- }
-
- _prop.setHasGetterSetterProperties(true);
- gs->setGetter(getterFunc);
-}
-
-void JSObject::defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc)
-{
- JSValue *o = getDirect(propertyName);
- GetterSetterImp *gs;
-
- if (o && o->type() == GetterSetterType) {
- gs = static_cast<GetterSetterImp *>(o);
- } else {
- gs = new GetterSetterImp;
- putDirect(propertyName, gs, GetterSetter);
- }
-
- _prop.setHasGetterSetterProperties(true);
- gs->setSetter(setterFunc);
-}
-
-bool JSObject::implementsConstruct() const
-{
- return false;
-}
-
-JSObject* JSObject::construct(ExecState*, const List& /*args*/)
-{
- ASSERT(false);
- return NULL;
-}
-
-JSObject* JSObject::construct(ExecState* exec, const List& args, const Identifier& /*functionName*/, const UString& /*sourceURL*/, int /*lineNumber*/)
-{
- return construct(exec, args);
-}
-
-bool JSObject::implementsCall() const
-{
- return false;
-}
-
-JSValue *JSObject::callAsFunction(ExecState* /*exec*/, JSObject* /*thisObj*/, const List &/*args*/)
-{
- ASSERT(false);
- return NULL;
-}
-
-bool JSObject::implementsHasInstance() const
-{
- return false;
-}
-
-bool JSObject::hasInstance(ExecState* exec, JSValue* value)
-{
- JSValue* proto = get(exec, exec->propertyNames().prototype);
- if (!proto->isObject()) {
- throwError(exec, TypeError, "intanceof called on an object with an invalid prototype property.");
- return false;
- }
-
- if (!value->isObject())
- return false;
-
- JSObject* o = static_cast<JSObject*>(value);
- while ((o = o->prototype()->getObject())) {
- if (o == proto)
- return true;
- }
- return false;
-}
-
-bool JSObject::propertyIsEnumerable(ExecState*, const Identifier& propertyName) const
-{
- unsigned attributes;
-
- if (!getPropertyAttributes(propertyName, attributes))
- return false;
- else
- return !(attributes & DontEnum);
-}
-
-bool JSObject::getPropertyAttributes(const Identifier& propertyName, unsigned& attributes) const
-{
- if (_prop.get(propertyName, attributes))
- return true;
-
- // Look in the static hashtable of properties
- const HashEntry* e = findPropertyHashEntry(propertyName);
- if (e) {
- attributes = e->attr;
- return true;
- }
-
- return false;
-}
-
-void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
-{
- _prop.getEnumerablePropertyNames(propertyNames);
-
- // Add properties from the static hashtable of properties
- const ClassInfo *info = classInfo();
- while (info) {
- if (info->propHashTable) {
- int size = info->propHashTable->size;
- const HashEntry *e = info->propHashTable->entries;
- for (int i = 0; i < size; ++i, ++e) {
- if (e->s && !(e->attr & DontEnum))
- propertyNames.add(e->s);
- }
- }
- info = info->parentClass;
- }
- if (_proto->isObject())
- static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);
-}
-
-bool JSObject::toBoolean(ExecState*) const
-{
- return true;
-}
-
-double JSObject::toNumber(ExecState *exec) const
-{
- JSValue *prim = toPrimitive(exec,NumberType);
- if (exec->hadException()) // should be picked up soon in nodes.cpp
- return 0.0;
- return prim->toNumber(exec);
-}
-
-UString JSObject::toString(ExecState *exec) const
-{
- JSValue *prim = toPrimitive(exec,StringType);
- if (exec->hadException()) // should be picked up soon in nodes.cpp
- return "";
- return prim->toString(exec);
-}
-
-JSObject *JSObject::toObject(ExecState*) const
-{
- return const_cast<JSObject*>(this);
-}
-
-void JSObject::putDirect(const Identifier &propertyName, JSValue *value, int attr)
-{
- _prop.put(propertyName, value, attr);
-}
-
-void JSObject::putDirect(const Identifier &propertyName, int value, int attr)
-{
- _prop.put(propertyName, jsNumber(value), attr);
-}
-
-void JSObject::removeDirect(const Identifier &propertyName)
-{
- _prop.remove(propertyName);
-}
-
-void JSObject::putDirectFunction(InternalFunctionImp* func, int attr)
-{
- putDirect(func->functionName(), func, attr);
-}
-
-void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue **location)
-{
- GetterSetterImp *gs = static_cast<GetterSetterImp *>(*location);
- JSObject *getterFunc = gs->getGetter();
- if (getterFunc)
- slot.setGetterSlot(this, getterFunc);
- else
- slot.setUndefined(this);
-}
-
-// ------------------------------ Error ----------------------------------------
-
-const char * const errorNamesArr[] = {
- I18N_NOOP("Error"), // GeneralError
- I18N_NOOP("Evaluation error"), // EvalError
- I18N_NOOP("Range error"), // RangeError
- I18N_NOOP("Reference error"), // ReferenceError
- I18N_NOOP("Syntax error"), // SyntaxError
- I18N_NOOP("Type error"), // TypeError
- I18N_NOOP("URI error"), // URIError
-};
-
-const char * const * const Error::errorNames = errorNamesArr;
-
-JSObject *Error::create(ExecState *exec, ErrorType errtype, const UString &message,
- int lineno, intptr_t sourceID, const UString &sourceURL)
-{
- JSObject *cons;
- switch (errtype) {
- case EvalError:
- cons = exec->lexicalGlobalObject()->evalErrorConstructor();
- break;
- case RangeError:
- cons = exec->lexicalGlobalObject()->rangeErrorConstructor();
- break;
- case ReferenceError:
- cons = exec->lexicalGlobalObject()->referenceErrorConstructor();
- break;
- case SyntaxError:
- cons = exec->lexicalGlobalObject()->syntaxErrorConstructor();
- break;
- case TypeError:
- cons = exec->lexicalGlobalObject()->typeErrorConstructor();
- break;
- case URIError:
- cons = exec->lexicalGlobalObject()->URIErrorConstructor();
- break;
- default:
- cons = exec->lexicalGlobalObject()->errorConstructor();
- break;
- }
-
- List args;
- if (message.isEmpty())
- args.append(jsString(errorNames[errtype]));
- else
- args.append(jsString(message));
- JSObject *err = static_cast<JSObject *>(cons->construct(exec,args));
-
- if (lineno != -1)
- err->put(exec, "line", jsNumber(lineno));
- if (sourceID != -1)
- err->put(exec, "sourceID", jsNumber(sourceID));
-
- if(!sourceURL.isNull())
- err->put(exec, "sourceURL", jsString(sourceURL));
-
- return err;
-}
-
-JSObject *Error::create(ExecState *exec, ErrorType type, const char *message)
-{
- return create(exec, type, message, -1, -1, NULL);
-}
-
-JSObject *throwError(ExecState *exec, ErrorType type)
-{
- JSObject *error = Error::create(exec, type, UString(), -1, -1, NULL);
- exec->setException(error);
- return error;
-}
-
-JSObject *throwError(ExecState *exec, ErrorType type, const UString &message)
-{
- JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
- exec->setException(error);
- return error;
-}
-
-JSObject *throwError(ExecState *exec, ErrorType type, const char *message)
-{
- JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
- exec->setException(error);
- return error;
-}
-
-JSObject *throwError(ExecState *exec, ErrorType type, const UString &message, int line, intptr_t sourceID, const UString &sourceURL)
-{
- JSObject *error = Error::create(exec, type, message, line, sourceID, sourceURL);
- exec->setException(error);
- return error;
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_OBJECT_H
-#define KJS_OBJECT_H
-
-#include "CommonIdentifiers.h"
-#include "ExecState.h"
-#include "JSType.h"
-#include "list.h"
-#include "property_map.h"
-#include "property_slot.h"
-#include "scope_chain.h"
-
-namespace KJS {
-
- class InternalFunctionImp;
- class PropertyNameArray;
-
- struct HashEntry;
- struct HashTable;
-
- // ECMA 262-3 8.6.1
- // Property attributes
- enum Attribute { None = 0,
- ReadOnly = 1 << 1, // property can be only read, not written
- DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
- DontDelete = 1 << 3, // property can't be deleted
- Internal = 1 << 4, // an internal property, set to bypass checks
- Function = 1 << 5, // property is a function - only used by static hashtables
- GetterSetter = 1 << 6 }; // property is a getter or setter
-
- /**
- * Class Information
- */
- struct ClassInfo {
- /**
- * A string denoting the class name. Example: "Window".
- */
- const char* className;
- /**
- * Pointer to the class information of the base class.
- * 0L if there is none.
- */
- const ClassInfo* parentClass;
- /**
- * Static hash-table of properties.
- */
- const HashTable* propHashTable;
- };
-
- // This is an internal value object which stores getter and setter functions
- // for a property.
- class GetterSetterImp : public JSCell {
- public:
- JSType type() const { return GetterSetterType; }
-
- GetterSetterImp() : getter(0), setter(0) { }
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState *exec) const;
- virtual double toNumber(ExecState *exec) const;
- virtual UString toString(ExecState *exec) const;
- virtual JSObject *toObject(ExecState *exec) const;
-
- virtual void mark();
-
- JSObject *getGetter() { return getter; }
- void setGetter(JSObject *g) { getter = g; }
- JSObject *getSetter() { return setter; }
- void setSetter(JSObject *s) { setter = s; }
-
- private:
- JSObject *getter;
- JSObject *setter;
- };
-
- class JSObject : public JSCell {
- public:
- /**
- * Creates a new JSObject with the specified prototype
- *
- * @param proto The prototype
- */
- JSObject(JSValue* proto);
-
- /**
- * Creates a new JSObject with a prototype of jsNull()
- * (that is, the ECMAScript "null" value, not a null object pointer).
- */
- JSObject();
-
- virtual void mark();
- virtual JSType type() const;
-
- /**
- * A pointer to a ClassInfo struct for this class. This provides a basic
- * facility for run-time type information, and can be used to check an
- * object's class an inheritance (see inherits()). This should
- * always return a statically declared pointer, or 0 to indicate that
- * there is no class information.
- *
- * This is primarily useful if you have application-defined classes that you
- * wish to check against for casting purposes.
- *
- * For example, to specify the class info for classes FooImp and BarImp,
- * where FooImp inherits from BarImp, you would add the following in your
- * class declarations:
- *
- * \code
- * class BarImp : public JSObject {
- * virtual const ClassInfo *classInfo() const { return &info; }
- * static const ClassInfo info;
- * // ...
- * };
- *
- * class FooImp : public JSObject {
- * virtual const ClassInfo *classInfo() const { return &info; }
- * static const ClassInfo info;
- * // ...
- * };
- * \endcode
- *
- * And in your source file:
- *
- * \code
- * const ClassInfo BarImp::info = { "Bar", 0, 0 }; // no parent class
- * const ClassInfo FooImp::info = { "Foo", &BarImp::info, 0 };
- * \endcode
- *
- * @see inherits()
- */
- virtual const ClassInfo *classInfo() const;
-
- /**
- * Checks whether this object inherits from the class with the specified
- * classInfo() pointer. This requires that both this class and the other
- * class return a non-NULL pointer for their classInfo() methods (otherwise
- * it will return false).
- *
- * For example, for two JSObject pointers obj1 and obj2, you can check
- * if obj1's class inherits from obj2's class using the following:
- *
- * if (obj1->inherits(obj2->classInfo())) {
- * // ...
- * }
- *
- * If you have a handle to a statically declared ClassInfo, such as in the
- * classInfo() example, you can check for inheritance without needing
- * an instance of the other class:
- *
- * if (obj1->inherits(FooImp::info)) {
- * // ...
- * }
- *
- * @param cinfo The ClassInfo pointer for the class you want to check
- * inheritance against.
- * @return true if this object's class inherits from class with the
- * ClassInfo pointer specified in cinfo
- */
- bool inherits(const ClassInfo *cinfo) const;
-
- // internal properties (ECMA 262-3 8.6.2)
-
- /**
- * Returns the prototype of this object. Note that this is not the same as
- * the "prototype" property.
- *
- * See ECMA 8.6.2
- *
- * @return The object's prototype
- */
- JSValue *prototype() const;
- void setPrototype(JSValue *proto);
-
- /**
- * Returns the class name of the object
- *
- * See ECMA 8.6.2
- *
- * @return The object's class name
- */
- /**
- * Implementation of the [[Class]] internal property (implemented by all
- * Objects)
- *
- * The default implementation uses classInfo().
- * You should either implement classInfo(), or
- * if you simply need a classname, you can reimplement className()
- * instead.
- */
- virtual UString className() const;
-
- /**
- * Retrieves the specified property from the object. If neither the object
- * or any other object in it's prototype chain have the property, this
- * function will return Undefined.
- *
- * See ECMA 8.6.2.1
- *
- * @param exec The current execution state
- * @param propertyName The name of the property to retrieve
- *
- * @return The specified property, or Undefined
- */
- JSValue *get(ExecState *exec, const Identifier &propertyName) const;
- JSValue *get(ExecState *exec, unsigned propertyName) const;
-
- bool getPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- bool getPropertySlot(ExecState *, unsigned, PropertySlot&);
-
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot&);
-
- /**
- * Sets the specified property.
- *
- * See ECMA 8.6.2.2
- *
- * @param exec The current execution state
- * @param propertyName The name of the property to set
- * @param propertyValue The value to set
- */
- virtual void put(ExecState* exec, const Identifier &propertyName, JSValue* value, int attr = None);
- virtual void put(ExecState* exec, unsigned propertyName, JSValue* value, int attr = None);
-
- /**
- * Used to check whether or not a particular property is allowed to be set
- * on an object
- *
- * See ECMA 8.6.2.3
- *
- * @param exec The current execution state
- * @param propertyName The name of the property
- * @return true if the property can be set, otherwise false
- */
- /**
- * Implementation of the [[CanPut]] internal property (implemented by all
- * Objects)
- */
- virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
-
- /**
- * Checks if a property is enumerable, that is if it doesn't have the DontEnum
- * flag set
- *
- * See ECMA 15.2.4
- * @param exec The current execution state
- * @param propertyName The name of the property
- * @return true if the property is enumerable, otherwise false
- */
- bool propertyIsEnumerable(ExecState *exec, const Identifier &propertyName) const;
-
- /**
- * Checks to see whether the object (or any object in it's prototype chain)
- * has a property with the specified name.
- *
- * See ECMA 8.6.2.4
- *
- * @param exec The current execution state
- * @param propertyName The name of the property to check for
- * @return true if the object has the property, otherwise false
- */
- bool hasProperty(ExecState*, const Identifier&) const;
- bool hasProperty(ExecState*, unsigned) const;
- bool hasOwnProperty(ExecState*, const Identifier&) const;
-
- /**
- * Removes the specified property from the object.
- *
- * See ECMA 8.6.2.5
- *
- * @param exec The current execution state
- * @param propertyName The name of the property to delete
- * @return true if the property was successfully deleted or did not
- * exist on the object. false if deleting the specified property is not
- * allowed.
- */
- virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
- virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
-
- /**
- * Converts the object into a primitive value. The value return may differ
- * depending on the supplied hint
- *
- * See ECMA 8.6.2.6
- *
- * @param exec The current execution state
- * @param hint The desired primitive type to convert to
- * @return A primitive value converted from the objetc. Note that the
- * type of primitive value returned may not be the same as the requested
- * hint.
- */
- /**
- * Implementation of the [[DefaultValue]] internal property (implemented by
- * all Objects)
- */
- virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
-
- /**
- * Whether or not the object implements the construct() method. If this
- * returns false you should not call the construct() method on this
- * object (typically, an assertion will fail to indicate this).
- *
- * @return true if this object implements the construct() method, otherwise
- * false
- */
- virtual bool implementsConstruct() const;
-
- /**
- * Creates a new object based on this object. Typically this means the
- * following:
- * 1. A new object is created
- * 2. The prototype of the new object is set to the value of this object's
- * "prototype" property
- * 3. The call() method of this object is called, with the new object
- * passed as the this value
- * 4. The new object is returned
- *
- * In some cases, Host objects may differ from these semantics, although
- * this is discouraged.
- *
- * If an error occurs during construction, the execution state's exception
- * will be set. This can be tested for with ExecState::hadException().
- * Under some circumstances, the exception object may also be returned.
- *
- * Note: This function should not be called if implementsConstruct() returns
- * false, in which case it will result in an assertion failure.
- *
- * @param exec The current execution state
- * @param args The arguments to be passed to call() once the new object has
- * been created
- * @return The newly created & initialized object
- */
- /**
- * Implementation of the [[Construct]] internal property
- */
- virtual JSObject* construct(ExecState* exec, const List& args);
- virtual JSObject* construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber);
-
- /**
- * Whether or not the object implements the call() method. If this returns
- * false you should not call the call() method on this object (typically,
- * an assertion will fail to indicate this).
- *
- * @return true if this object implements the call() method, otherwise
- * false
- */
- virtual bool implementsCall() const;
-
- /**
- * Calls this object as if it is a function.
- *
- * Note: This function should not be called if implementsCall() returns
- * false, in which case it will result in an assertion failure.
- *
- * See ECMA 8.6.2.3
- *
- * @param exec The current execution state
- * @param thisObj The obj to be used as "this" within function execution.
- * Note that in most cases this will be different from the C++ "this"
- * object. For example, if the ECMAScript code "window.location->toString()"
- * is executed, call() will be invoked on the C++ object which implements
- * the toString method, with the thisObj being window.location
- * @param args List of arguments to be passed to the function
- * @return The return value from the function
- */
- JSValue *call(ExecState *exec, JSObject *thisObj, const List &args);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
- /**
- * Whether or not the object implements the hasInstance() method. If this
- * returns false you should not call the hasInstance() method on this
- * object (typically, an assertion will fail to indicate this).
- *
- * @return true if this object implements the hasInstance() method,
- * otherwise false
- */
- virtual bool implementsHasInstance() const;
-
- /**
- * Checks whether value delegates behavior to this object. Used by the
- * instanceof operator.
- *
- * @param exec The current execution state
- * @param value The value to check
- * @return true if value delegates behavior to this object, otherwise
- * false
- */
- virtual bool hasInstance(ExecState *exec, JSValue *value);
-
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState *exec) const;
- virtual double toNumber(ExecState *exec) const;
- virtual UString toString(ExecState *exec) const;
- virtual JSObject *toObject(ExecState *exec) const;
-
- bool getPropertyAttributes(const Identifier& propertyName, unsigned& attributes) const;
-
- // WebCore uses this to make document.all and style.filter undetectable
- virtual bool masqueradeAsUndefined() const { return false; }
-
- // This get function only looks at the property map.
- // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want
- // to look up in the prototype, it might already exist there)
- JSValue *getDirect(const Identifier& propertyName) const
- { return _prop.get(propertyName); }
- JSValue **getDirectLocation(const Identifier& propertyName)
- { return _prop.getLocation(propertyName); }
- void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0);
- void putDirect(const Identifier &propertyName, int value, int attr = 0);
- void removeDirect(const Identifier &propertyName);
-
- // convenience to add a function property under the function's own built-in name
- void putDirectFunction(InternalFunctionImp*, int attr = 0);
-
- void fillGetterPropertySlot(PropertySlot& slot, JSValue **location);
-
- void defineGetter(ExecState *exec, const Identifier& propertyName, JSObject *getterFunc);
- void defineSetter(ExecState *exec, const Identifier& propertyName, JSObject *setterFunc);
-
- void saveProperties(SavedProperties &p) const { _prop.save(p); }
- void restoreProperties(const SavedProperties &p) { _prop.restore(p); }
-
- virtual bool isActivationObject() { return false; }
- virtual bool isGlobalObject() const { return false; }
-
- protected:
- PropertyMap _prop;
-
- private:
- const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
- JSValue *_proto;
- };
-
- /**
- * Types of Native Errors available. For custom errors, GeneralError
- * should be used.
- */
- enum ErrorType { GeneralError = 0,
- EvalError = 1,
- RangeError = 2,
- ReferenceError = 3,
- SyntaxError = 4,
- TypeError = 5,
- URIError = 6,
- TimeoutError = 7
- };
-
- /**
- * @short Factory methods for error objects.
- */
- class Error {
- public:
- /**
- * Factory method for error objects.
- *
- * @param exec The current execution state
- * @param errtype Type of error.
- * @param message Optional error message.
- * @param lineNumber Optional line number.
- * @param sourceId Optional source id.
- * @param sourceURL Optional source URL.
- */
- static JSObject *create(ExecState *, ErrorType, const UString &message, int lineNumber, intptr_t sourceID, const UString &sourceURL);
- static JSObject *create(ExecState *, ErrorType, const char *message);
-
- /**
- * Array of error names corresponding to ErrorType
- */
- static const char * const * const errorNames;
- };
-
-JSObject *throwError(ExecState *, ErrorType, const UString &message, int lineNumber, intptr_t sourceID, const UString &sourceURL);
-JSObject *throwError(ExecState *, ErrorType, const UString &message);
-JSObject *throwError(ExecState *, ErrorType, const char *message);
-JSObject *throwError(ExecState *, ErrorType);
-
-inline JSObject::JSObject(JSValue* proto)
- : _proto(proto)
-{
- ASSERT(proto);
-}
-
-inline JSObject::JSObject()
- : _proto(jsNull())
-{
-}
-
-inline JSValue *JSObject::prototype() const
-{
- return _proto;
-}
-
-inline void JSObject::setPrototype(JSValue *proto)
-{
- ASSERT(proto);
- _proto = proto;
-}
-
-inline bool JSObject::inherits(const ClassInfo *info) const
-{
- for (const ClassInfo *ci = classInfo(); ci; ci = ci->parentClass)
- if (ci == info)
- return true;
- return false;
-}
-
-// this method is here to be after the inline declaration of JSObject::inherits
-inline bool JSCell::isObject(const ClassInfo *info) const
-{
- return isObject() && static_cast<const JSObject *>(this)->inherits(info);
-}
-
-// this method is here to be after the inline declaration of JSCell::isObject
-inline bool JSValue::isObject(const ClassInfo *c) const
-{
- return !JSImmediate::isImmediate(this) && asCell()->isObject(c);
-}
-
-// It may seem crazy to inline a function this large but it makes a big difference
-// since this is function very hot in variable lookup
-inline bool JSObject::getPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
-{
- JSObject *object = this;
- while (true) {
- if (object->getOwnPropertySlot(exec, propertyName, slot))
- return true;
-
- JSValue *proto = object->_proto;
- if (!proto->isObject())
- return false;
-
- object = static_cast<JSObject *>(proto);
- }
-}
-
-// It may seem crazy to inline a function this large, especially a virtual function,
-// but it makes a big difference to property lookup that derived classes can inline their
-// base class call to this.
-ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (JSValue **location = getDirectLocation(propertyName)) {
- if (_prop.hasGetterSetterProperties() && location[0]->type() == GetterSetterType)
- fillGetterPropertySlot(slot, location);
- else
- slot.setValueSlot(this, location);
- return true;
- }
-
- // non-standard Netscape extension
- if (propertyName == exec->propertyNames().underscoreProto) {
- slot.setValueSlot(this, &_proto);
- return true;
- }
-
- return false;
-}
-
-inline void ScopeChain::release()
-{
- // This function is only called by deref(),
- // Deref ensures these conditions are true.
- ASSERT(_node && _node->refCount == 0);
- ScopeChainNode *n = _node;
- do {
- ScopeChainNode *next = n->next;
- delete n;
- n = next;
- } while (n && --n->refCount == 0);
-}
-
-inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const
-{
- return defaultValue(exec, preferredType);
-}
-
-} // namespace
-
-#endif // KJS_OBJECT_H
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "object_object.h"
-
-#include "JSGlobalObject.h"
-#include "operations.h"
-#include "function_object.h"
-#include <stdio.h>
-
-namespace KJS {
-
-// ------------------------------ ObjectPrototype --------------------------------
-
-static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncHasOwnProperty(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncDefineGetter(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncDefineSetter(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncLookupGetter(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncLookupSetter(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, const List&);
-static JSValue* objectProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
-
-ObjectPrototype::ObjectPrototype(ExecState* exec, FunctionPrototype* functionPrototype)
- : JSObject() // [[Prototype]] is null
-{
- static const Identifier* hasOwnPropertyPropertyName = new Identifier("hasOwnProperty");
- static const Identifier* propertyIsEnumerablePropertyName = new Identifier("propertyIsEnumerable");
- static const Identifier* isPrototypeOfPropertyName = new Identifier("isPrototypeOf");
- static const Identifier* defineGetterPropertyName = new Identifier("__defineGetter__");
- static const Identifier* defineSetterPropertyName = new Identifier("__defineSetter__");
- static const Identifier* lookupGetterPropertyName = new Identifier("__lookupGetter__");
- static const Identifier* lookupSetterPropertyName = new Identifier("__lookupSetter__");
-
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *hasOwnPropertyPropertyName, objectProtoFuncHasOwnProperty), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *propertyIsEnumerablePropertyName, objectProtoFuncPropertyIsEnumerable), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *isPrototypeOfPropertyName, objectProtoFuncIsPrototypeOf), DontEnum);
-
- // Mozilla extensions
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 2, *defineGetterPropertyName, objectProtoFuncDefineGetter), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 2, *defineSetterPropertyName, objectProtoFuncDefineSetter), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *lookupGetterPropertyName, objectProtoFuncLookupGetter), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *lookupSetterPropertyName, objectProtoFuncLookupSetter), DontEnum);
-}
-
-
-// ------------------------------ Functions --------------------------------
-
-// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
-
-JSValue* objectProtoFuncValueOf(ExecState*, JSObject* thisObj, const List&)
-{
- return thisObj;
-}
-
-JSValue* objectProtoFuncHasOwnProperty(ExecState* exec, JSObject* thisObj, const List& args)
-{
- return jsBoolean(thisObj->hasOwnProperty(exec, Identifier(args[0]->toString(exec))));
-}
-
-JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject* thisObj, const List& args)
-{
- if (!args[0]->isObject())
- return jsBoolean(false);
-
- JSValue* v = static_cast<JSObject*>(args[0])->prototype();
-
- while (true) {
- if (!v->isObject())
- return jsBoolean(false);
- if (thisObj == static_cast<JSObject*>(v))\v
- return jsBoolean(true);
- v = static_cast<JSObject*>(v)->prototype();
- }
-}
-
-JSValue* objectProtoFuncDefineGetter(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!args[1]->isObject() || !static_cast<JSObject*>(args[1])->implementsCall())
- return throwError(exec, SyntaxError, "invalid getter usage");
-
- thisObj->defineGetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
- return jsUndefined();
-}
-
-JSValue* objectProtoFuncDefineSetter(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!args[1]->isObject() || !static_cast<JSObject*>(args[1])->implementsCall())
- return throwError(exec, SyntaxError, "invalid setter usage");
-
- thisObj->defineSetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
- return jsUndefined();
-}
-
-JSValue* objectProtoFuncLookupGetter(ExecState* exec, JSObject* thisObj, const List& args)
-{
- Identifier propertyName = Identifier(args[0]->toString(exec));
- JSObject* obj = thisObj;
- while (true) {
- JSValue* v = obj->getDirect(propertyName);
- if (v) {
- if (v->type() != GetterSetterType)
- return jsUndefined();
- JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getGetter();
- if (!funcObj)
- return jsUndefined();
- return funcObj;
- }
-
- if (!obj->prototype() || !obj->prototype()->isObject())
- return jsUndefined();
- obj = static_cast<JSObject*>(obj->prototype());
- }
-}
-
-JSValue* objectProtoFuncLookupSetter(ExecState* exec, JSObject* thisObj, const List& args)
-{
- Identifier propertyName = Identifier(args[0]->toString(exec));
- JSObject* obj = thisObj;
- while (true) {
- JSValue* v = obj->getDirect(propertyName);
- if (v) {
- if (v->type() != GetterSetterType)
- return jsUndefined();
- JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getSetter();
- if (!funcObj)
- return jsUndefined();
- return funcObj;
- }
-
- if (!obj->prototype() || !obj->prototype()->isObject())
- return jsUndefined();
- obj = static_cast<JSObject*>(obj->prototype());
- }
-}
-
-JSValue* objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject* thisObj, const List& args)
-{
- return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(args[0]->toString(exec))));
-}
-
-JSValue* objectProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List&)
-{
- return jsString(thisObj->toString(exec));
-}
-
-JSValue* objectProtoFuncToString(ExecState*, JSObject* thisObj, const List&)
-{
- return jsString("[object " + thisObj->className() + "]");
-}
-
-// ------------------------------ ObjectObjectImp --------------------------------
-
-ObjectObjectImp::ObjectObjectImp(ExecState* exec, ObjectPrototype* objProto, FunctionPrototype* funcProto)
- : InternalFunctionImp(funcProto, "Object")
-{
- // ECMA 15.2.3.1
- putDirect(exec->propertyNames().prototype, objProto, DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
-}
-
-
-bool ObjectObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.2.2
-JSObject* ObjectObjectImp::construct(ExecState* exec, const List& args)
-{
- JSValue* arg = args[0];
- switch (arg->type()) {
- case StringType:
- case BooleanType:
- case NumberType:
- case ObjectType:
- return arg->toObject(exec);
- case NullType:
- case UndefinedType:
- return new JSObject(exec->lexicalGlobalObject()->objectPrototype());
- default:
- ASSERT_NOT_REACHED();
- return 0;
- }
-}
-
-JSValue* ObjectObjectImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, const List &args)
-{
- return construct(exec, args);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef _OBJECT_OBJECT_H_
-#define _OBJECT_OBJECT_H_
-
-#include "function.h"
-
-namespace KJS {
-
- /**
- * @internal
- *
- * The initial value of Object.prototype (and thus all objects created
- * with the Object constructor
- */
- class ObjectPrototype : public JSObject {
- public:
- ObjectPrototype(ExecState*, FunctionPrototype*);
- };
-
- JSValue* objectProtoFuncToString(ExecState*, JSObject*, const List&);
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Object" property
- */
- class ObjectObjectImp : public InternalFunctionImp {
- public:
- ObjectObjectImp(ExecState*, ObjectPrototype*, FunctionPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
-
-} // namespace KJS
-
-#endif // _OBJECT_OBJECT_H_
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "operations.h"
-
-#include "internal.h"
-#include "object.h"
-#include <math.h>
-#include <stdio.h>
-#include <wtf/MathExtras.h>
-
-#if HAVE(FLOAT_H)
-#include <float.h>
-#endif
-
-namespace KJS {
-
-// ECMA 11.9.3
-bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
-{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
-
- if (t1 != t2) {
- if (t1 == UndefinedType)
- t1 = NullType;
- if (t2 == UndefinedType)
- t2 = NullType;
-
- if (t1 == BooleanType)
- t1 = NumberType;
- if (t2 == BooleanType)
- t2 = NumberType;
-
- if (t1 == NumberType && t2 == StringType) {
- // use toNumber
- } else if (t1 == StringType && t2 == NumberType)
- t1 = NumberType;
- // use toNumber
- else {
- if ((t1 == StringType || t1 == NumberType) && t2 == ObjectType) {
- v2 = v2->toPrimitive(exec);
- if (exec->hadException())
- return false;
- return equal(exec, v1, v2);
- }
- if (t1 == NullType && t2 == ObjectType)
- return static_cast<JSObject *>(v2)->masqueradeAsUndefined();
- if (t1 == ObjectType && (t2 == StringType || t2 == NumberType)) {
- v1 = v1->toPrimitive(exec);
- if (exec->hadException())
- return false;
- return equal(exec, v1, v2);
- }
- if (t1 == ObjectType && t2 == NullType)
- return static_cast<JSObject *>(v1)->masqueradeAsUndefined();
- if (t1 != t2)
- return false;
- }
- }
-
- if (t1 == UndefinedType || t1 == NullType)
- return true;
-
- if (t1 == NumberType) {
- double d1 = v1->toNumber(exec);
- double d2 = v2->toNumber(exec);
- return d1 == d2;
- }
-
- if (t1 == StringType)
- return static_cast<StringImp*>(v1)->value() == static_cast<StringImp*>(v2)->value();
-
- if (t1 == BooleanType)
- return v1->toBoolean(exec) == v2->toBoolean(exec);
-
- // types are Object
- return v1 == v2;
-}
-
-bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
-{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
-
- if (t1 != t2)
- return false;
- if (t1 == UndefinedType || t1 == NullType)
- return true;
- if (t1 == NumberType) {
- double n1 = v1->toNumber(exec);
- double n2 = v2->toNumber(exec);
- if (n1 == n2)
- return true;
- return false;
- } else if (t1 == StringType)
- return v1->toString(exec) == v2->toString(exec);
- else if (t2 == BooleanType)
- return v1->toBoolean(exec) == v2->toBoolean(exec);
-
- if (v1 == v2)
- return true;
- /* TODO: joined objects */
-
- return false;
-}
-
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _KJS_OPERATIONS_H_
-#define _KJS_OPERATIONS_H_
-
-namespace KJS {
-
- class ExecState;
- class JSValue;
-
- bool equal(ExecState *exec, JSValue *v1, JSValue *v2);
- bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2);
-}
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "property_map.h"
-
-#include "object.h"
-#include "protect.h"
-#include "PropertyNameArray.h"
-#include <algorithm>
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashTable.h>
-#include <wtf/Vector.h>
-
-using std::max;
-using WTF::doubleHash;
-
-#ifndef NDEBUG
-#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
-#define DUMP_PROPERTYMAP_STATS 0
-#else
-#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
-#define DUMP_PROPERTYMAP_STATS 0
-#endif
-
-#define USE_SINGLE_ENTRY 1
-
-// 2/28/2006 ggaren: command-line JS iBench says that USE_SINGLE_ENTRY is a
-// 3.2% performance boost.
-
-namespace KJS {
-
-// Choose a number for the following so that most property maps are smaller,
-// but it's not going to blow out the stack to allocate this number of pointers.
-static const int smallMapThreshold = 1024;
-
-// The point at which the function call overhead of the qsort implementation
-// becomes small compared to the inefficiency of insertion sort.
-static const unsigned tinyMapThreshold = 20;
-
-#if DUMP_PROPERTYMAP_STATS
-
-static int numProbes;
-static int numCollisions;
-static int numRehashes;
-static int numRemoves;
-
-struct PropertyMapStatisticsExitLogger { ~PropertyMapStatisticsExitLogger(); };
-
-static PropertyMapStatisticsExitLogger logger;
-
-PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
-{
- printf("\nKJS::PropertyMap statistics\n\n");
- printf("%d probes\n", numProbes);
- printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
- printf("%d rehashes\n", numRehashes);
- printf("%d removes\n", numRemoves);
-}
-
-#endif
-
-struct PropertyMapEntry {
- UString::Rep* key;
- JSValue* value;
- unsigned attributes;
- unsigned index;
-
- PropertyMapEntry(UString::Rep* k, JSValue* v, int a)
- : key(k), value(v), attributes(a), index(0)
- {
- }
-};
-
-// lastIndexUsed is an ever-increasing index used to identify the order items
-// were inserted into the property map. It's required that getEnumerablePropertyNames
-// return the properties in the order they were added for compatibility with other
-// browsers' JavaScript implementations.
-struct PropertyMapHashTable {
- unsigned sizeMask;
- unsigned size;
- unsigned keyCount;
- unsigned deletedSentinelCount;
- unsigned lastIndexUsed;
- unsigned entryIndicies[1];
-
- PropertyMapEntry* entries()
- {
- // The entries vector comes after the indices vector.
- // The 0th item in the entries vector is not really used; it has to
- // have a 0 in its key to allow the hash table lookup to handle deleted
- // sentinels without any special-case code, but the other fields are unused.
- return reinterpret_cast<PropertyMapEntry*>(&entryIndicies[size]);
- }
-
- static size_t allocationSize(unsigned size)
- {
- // We never let a hash table get more than half full,
- // So the number of indices we need is the size of the hash table.
- // But the number of entries is half that (plus one for the deleted sentinel).
- return sizeof(PropertyMapHashTable)
- + (size - 1) * sizeof(unsigned)
- + (1 + size / 2) * sizeof(PropertyMapEntry);
- }
-};
-
-static const unsigned emptyEntryIndex = 0;
-static const unsigned deletedSentinelIndex = 1;
-
-SavedProperties::SavedProperties()
- : count(0)
-{
-}
-
-SavedProperties::~SavedProperties()
-{
-}
-
-#if !DO_PROPERTYMAP_CONSTENCY_CHECK
-
-inline void PropertyMap::checkConsistency()
-{
-}
-
-#endif
-
-PropertyMap::~PropertyMap()
-{
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (m_singleEntryKey)
- m_singleEntryKey->deref();
-#endif
- return;
- }
-
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (UString::Rep* key = m_u.table->entries()[i].key)
- key->deref();
- }
- fastFree(m_u.table);
-}
-
-void PropertyMap::clear()
-{
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (m_singleEntryKey) {
- m_singleEntryKey->deref();
- m_singleEntryKey = 0;
- }
-#endif
- return;
- }
-
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (UString::Rep* key = m_u.table->entries()[i].key)
- key->deref();
- }
- for (unsigned i = 0; i < m_u.table->size; i++)
- m_u.table->entryIndicies[i] = emptyEntryIndex;
- m_u.table->keyCount = 0;
- m_u.table->deletedSentinelCount = 0;
-}
-
-JSValue* PropertyMap::get(const Identifier& name, unsigned& attributes) const
-{
- ASSERT(!name.isNull());
-
- UString::Rep* rep = name._ustring.rep();
-
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (rep == m_singleEntryKey) {
- attributes = m_singleEntryAttributes;
- return m_u.singleEntryValue;
- }
-#endif
- return 0;
- }
-
- unsigned i = rep->computedHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key) {
- attributes = m_u.table->entries()[entryIndex - 1].attributes;
- return m_u.table->entries()[entryIndex - 1].value;
- }
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->computedHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
-
- entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key) {
- attributes = m_u.table->entries()[entryIndex - 1].attributes;
- return m_u.table->entries()[entryIndex - 1].value;
- }
- }
-}
-
-JSValue* PropertyMap::get(const Identifier& name) const
-{
- ASSERT(!name.isNull());
-
- UString::Rep* rep = name._ustring.rep();
-
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (rep == m_singleEntryKey)
- return m_u.singleEntryValue;
-#endif
- return 0;
- }
-
- unsigned i = rep->computedHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key)
- return m_u.table->entries()[entryIndex - 1].value;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->computedHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
-
- entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key)
- return m_u.table->entries()[entryIndex - 1].value;
- }
-}
-
-JSValue** PropertyMap::getLocation(const Identifier& name)
-{
- ASSERT(!name.isNull());
-
- UString::Rep* rep = name._ustring.rep();
-
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (rep == m_singleEntryKey)
- return &m_u.singleEntryValue;
-#endif
- return 0;
- }
-
- unsigned i = rep->computedHash();
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key)
- return &m_u.table->entries()[entryIndex - 1].value;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
- unsigned k = 1 | doubleHash(rep->computedHash());
-
- while (1) {
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
-
- entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return 0;
-
- if (rep == m_u.table->entries()[entryIndex - 1].key)
- return &m_u.table->entries()[entryIndex - 1].value;
- }
-}
-
-void PropertyMap::put(const Identifier& name, JSValue* value, unsigned attributes, bool checkReadOnly)
-{
- ASSERT(!name.isNull());
- ASSERT(value);
-
- checkConsistency();
-
- UString::Rep* rep = name._ustring.rep();
-
-#if USE_SINGLE_ENTRY
- if (!m_usingTable) {
- if (!m_singleEntryKey) {
- rep->ref();
- m_singleEntryKey = rep;
- m_u.singleEntryValue = value;
- m_singleEntryAttributes = static_cast<short>(attributes);
- checkConsistency();
- return;
- }
- if (rep == m_singleEntryKey && !(checkReadOnly && (m_singleEntryAttributes & ReadOnly))) {
- m_u.singleEntryValue = value;
- return;
- }
- }
-#endif
-
- if (!m_usingTable || (m_u.table->keyCount + m_u.table->deletedSentinelCount) * 2 >= m_u.table->size)
- expand();
-
- // FIXME: Consider a fast case for tables with no deleted sentinels.
-
- unsigned i = rep->computedHash();
- unsigned k = 0;
- bool foundDeletedElement = false;
- unsigned deletedElementIndex = 0; // initialize to make the compiler happy
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- while (1) {
- unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- break;
-
- if (m_u.table->entries()[entryIndex - 1].key == rep) {
- if (checkReadOnly && (m_u.table->entries()[entryIndex - 1].attributes & ReadOnly))
- return;
- // Put a new value in an existing hash table entry.
- m_u.table->entries()[entryIndex - 1].value = value;
- // Attributes are intentionally not updated.
- return;
- } else if (entryIndex == deletedSentinelIndex) {
- // If we find a deleted-element sentinel, remember it for use later.
- if (!foundDeletedElement) {
- foundDeletedElement = true;
- deletedElementIndex = i;
- }
- }
-
- if (k == 0) {
- k = 1 | doubleHash(rep->computedHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- // Figure out which entry to use.
- unsigned entryIndex = m_u.table->keyCount + m_u.table->deletedSentinelCount + 2;
- if (foundDeletedElement) {
- i = deletedElementIndex;
- --m_u.table->deletedSentinelCount;
-
- // Since we're not making the table bigger, we can't use the entry one past
- // the end that we were planning on using, so search backwards for the empty
- // slot that we can use. We know it will be there because we did at least one
- // deletion in the past that left an entry empty.
- while (m_u.table->entries()[--entryIndex - 1].key)
- ;
- }
-
-
- // Create a new hash table entry.
- m_u.table->entryIndicies[i & m_u.table->sizeMask] = entryIndex;
-
- // Create a new hash table entry.
- rep->ref();
- m_u.table->entries()[entryIndex - 1].key = rep;
- m_u.table->entries()[entryIndex - 1].value = value;
- m_u.table->entries()[entryIndex - 1].attributes = attributes;
- m_u.table->entries()[entryIndex - 1].index = ++m_u.table->lastIndexUsed;
- ++m_u.table->keyCount;
-
- checkConsistency();
-}
-
-void PropertyMap::insert(const Entry& entry)
-{
- ASSERT(m_u.table);
-
- unsigned i = entry.key->computedHash();
- unsigned k = 0;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
-#endif
-
- while (1) {
- unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- break;
-
- if (k == 0) {
- k = 1 | doubleHash(entry.key->computedHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- unsigned entryIndex = m_u.table->keyCount + 2;
- m_u.table->entryIndicies[i & m_u.table->sizeMask] = entryIndex;
- m_u.table->entries()[entryIndex - 1] = entry;
- ++m_u.table->keyCount;
-}
-
-void PropertyMap::expand()
-{
- if (!m_usingTable)
- createTable();
- else
- rehash(m_u.table->size * 2);
-}
-
-void PropertyMap::rehash()
-{
- ASSERT(m_usingTable);
- ASSERT(m_u.table);
- ASSERT(m_u.table->size);
- rehash(m_u.table->size);
-}
-
-void PropertyMap::createTable()
-{
- const unsigned newTableSize = 16;
-
- ASSERT(!m_usingTable);
-
- checkConsistency();
-
-#if USE_SINGLE_ENTRY
- JSValue* oldSingleEntryValue = m_u.singleEntryValue;
-#endif
-
- m_u.table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
- m_u.table->size = newTableSize;
- m_u.table->sizeMask = newTableSize - 1;
- m_usingTable = true;
-
-#if USE_SINGLE_ENTRY
- if (m_singleEntryKey) {
- insert(Entry(m_singleEntryKey, oldSingleEntryValue, m_singleEntryAttributes));
- m_singleEntryKey = 0;
- }
-#endif
-
- checkConsistency();
-}
-
-void PropertyMap::rehash(unsigned newTableSize)
-{
- ASSERT(!m_singleEntryKey);
- ASSERT(m_u.table);
- ASSERT(m_usingTable);
-
- checkConsistency();
-
- Table* oldTable = m_u.table;
-
- m_u.table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
- m_u.table->size = newTableSize;
- m_u.table->sizeMask = newTableSize - 1;
-
- unsigned lastIndexUsed = 0;
- unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i) {
- if (oldTable->entries()[i].key) {
- lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
- insert(oldTable->entries()[i]);
- }
- }
- m_u.table->lastIndexUsed = lastIndexUsed;
-
- fastFree(oldTable);
-
- checkConsistency();
-}
-
-void PropertyMap::remove(const Identifier& name)
-{
- ASSERT(!name.isNull());
-
- checkConsistency();
-
- UString::Rep* rep = name._ustring.rep();
-
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (rep == m_singleEntryKey) {
- m_singleEntryKey->deref();
- m_singleEntryKey = 0;
- checkConsistency();
- }
-#endif
- return;
- }
-
-#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
- ++numRemoves;
-#endif
-
- // Find the thing to remove.
- unsigned i = rep->computedHash();
- unsigned k = 0;
- unsigned entryIndex;
- UString::Rep* key = 0;
- while (1) {
- entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- if (entryIndex == emptyEntryIndex)
- return;
-
- key = m_u.table->entries()[entryIndex - 1].key;
- if (rep == key)
- break;
-
- if (k == 0) {
- k = 1 | doubleHash(rep->computedHash());
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
- }
-
- i += k;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
- }
-
- // Replace this one element with the deleted sentinel. Also clear out
- // the entry so we can iterate all the entries as needed.
- m_u.table->entryIndicies[i & m_u.table->sizeMask] = deletedSentinelIndex;
- key->deref();
- m_u.table->entries()[entryIndex - 1].key = 0;
- m_u.table->entries()[entryIndex - 1].value = jsUndefined();
- m_u.table->entries()[entryIndex - 1].attributes = 0;
- ASSERT(m_u.table->keyCount >= 1);
- --m_u.table->keyCount;
- ++m_u.table->deletedSentinelCount;
-
- if (m_u.table->deletedSentinelCount * 4 >= m_u.table->size)
- rehash();
-
- checkConsistency();
-}
-
-void PropertyMap::mark() const
-{
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (m_singleEntryKey) {
- JSValue* v = m_u.singleEntryValue;
- if (!v->marked())
- v->mark();
- }
-#endif
- return;
- }
-
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- JSValue* v = m_u.table->entries()[i].value;
- if (!v->marked())
- v->mark();
- }
-}
-
-static int comparePropertyMapEntryIndices(const void* a, const void* b)
-{
- unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
- unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index;
- if (ia < ib)
- return -1;
- if (ia > ib)
- return +1;
- return 0;
-}
-
-bool PropertyMap::containsGettersOrSetters() const
-{
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- return !!(m_singleEntryAttributes & GetterSetter);
-#else
- return false;
-#endif
- }
-
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (m_u.table->entries()[i].attributes & GetterSetter)
- return true;
- }
-
- return false;
-}
-
-void PropertyMap::getEnumerablePropertyNames(PropertyNameArray& propertyNames) const
-{
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- UString::Rep* key = m_singleEntryKey;
- if (key && !(m_singleEntryAttributes & DontEnum))
- propertyNames.add(Identifier(key));
-#endif
- return;
- }
-
- if (m_u.table->keyCount < tinyMapThreshold) {
- Entry* a[tinyMapThreshold];
- int i = 0;
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned k = 1; k <= entryCount; k++) {
- if (m_u.table->entries()[k].key && !(m_u.table->entries()[k].attributes & DontEnum)) {
- Entry* value = &m_u.table->entries()[k];
- int j;
- for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
- a[j + 1] = a[j];
- a[j + 1] = value;
- ++i;
- }
- }
- for (int k = 0; k < i; ++k)
- propertyNames.add(Identifier(a[k]->key));
- return;
- }
-
- // Allocate a buffer to use to sort the keys.
- Vector<Entry*, smallMapThreshold> sortedEnumerables(m_u.table->keyCount);
-
- // Get pointers to the enumerable entries in the buffer.
- Entry** p = sortedEnumerables.data();
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; i++) {
- if (m_u.table->entries()[i].key && !(m_u.table->entries()[i].attributes & DontEnum))
- *p++ = &m_u.table->entries()[i];
- }
-
- // Sort the entries by index.
- qsort(sortedEnumerables.data(), p - sortedEnumerables.data(), sizeof(Entry*), comparePropertyMapEntryIndices);
-
- // Put the keys of the sorted entries into the list.
- for (Entry** q = sortedEnumerables.data(); q != p; ++q)
- propertyNames.add(Identifier(q[0]->key));
-}
-
-void PropertyMap::save(SavedProperties& s) const
-{
- unsigned count = 0;
-
- if (!m_usingTable) {
-#if USE_SINGLE_ENTRY
- if (m_singleEntryKey && !(m_singleEntryAttributes & (ReadOnly | Function)))
- ++count;
-#endif
- } else {
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i)
- if (m_u.table->entries()[i].key && !(m_u.table->entries()[i].attributes & (ReadOnly | Function)))
- ++count;
- }
-
- s.properties.clear();
- s.count = count;
-
- if (count == 0)
- return;
-
- s.properties.set(new SavedProperty[count]);
-
- SavedProperty* prop = s.properties.get();
-
-#if USE_SINGLE_ENTRY
- if (!m_usingTable) {
- prop->init(m_singleEntryKey, m_u.singleEntryValue, m_singleEntryAttributes);
- return;
- }
-#endif
-
- // Save in the right order so we don't lose the order.
- // Another possibility would be to save the indices.
-
- // Allocate a buffer to use to sort the keys.
- Vector<Entry*, smallMapThreshold> sortedEntries(count);
-
- // Get pointers to the entries in the buffer.
- Entry** p = sortedEntries.data();
- unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
- for (unsigned i = 1; i <= entryCount; ++i) {
- if (m_u.table->entries()[i].key && !(m_u.table->entries()[i].attributes & (ReadOnly | Function)))
- *p++ = &m_u.table->entries()[i];
- }
- ASSERT(p == sortedEntries.data() + count);
-
- // Sort the entries by index.
- qsort(sortedEntries.data(), p - sortedEntries.data(), sizeof(Entry*), comparePropertyMapEntryIndices);
-
- // Put the sorted entries into the saved properties list.
- for (Entry** q = sortedEntries.data(); q != p; ++q, ++prop) {
- Entry* e = *q;
- prop->init(e->key, e->value, e->attributes);
- }
-}
-
-void PropertyMap::restore(const SavedProperties& p)
-{
- for (unsigned i = 0; i != p.count; ++i)
- put(Identifier(p.properties[i].name()), p.properties[i].value(), p.properties[i].attributes());
-}
-
-#if DO_PROPERTYMAP_CONSTENCY_CHECK
-
-void PropertyMap::checkConsistency()
-{
- if (!m_usingTable)
- return;
-
- ASSERT(m_u.table->size >= 16);
- ASSERT(m_u.table->sizeMask);
- ASSERT(m_u.table->size == m_u.table->sizeMask + 1);
- ASSERT(!(m_u.table->size & m_u.table->sizeMask));
-
- ASSERT(m_u.table->keyCount <= m_u.table->size / 2);
- ASSERT(m_u.table->deletedSentinelCount <= m_u.table->size / 4);
-
- ASSERT(m_u.table->keyCount + m_u.table->deletedSentinelCount <= m_u.table->size / 2);
-
- unsigned indexCount = 0;
- unsigned deletedIndexCount = 0;
- for (unsigned a = 0; a != m_u.table->size; ++a) {
- unsigned entryIndex = m_u.table->entryIndicies[a];
- if (entryIndex == emptyEntryIndex)
- continue;
- if (entryIndex == deletedSentinelIndex) {
- ++deletedIndexCount;
- continue;
- }
- ASSERT(entryIndex > deletedSentinelIndex);
- ASSERT(entryIndex - 1 <= m_u.table->keyCount + m_u.table->deletedSentinelCount);
- ++indexCount;
-
- for (unsigned b = a + 1; b != m_u.table->size; ++b)
- ASSERT(m_u.table->entryIndicies[b] != entryIndex);
- }
- ASSERT(indexCount == m_u.table->keyCount);
- ASSERT(deletedIndexCount == m_u.table->deletedSentinelCount);
-
- ASSERT(m_u.table->entries()[0].key == 0);
-
- unsigned nonEmptyEntryCount = 0;
- for (unsigned c = 1; c <= m_u.table->keyCount + m_u.table->deletedSentinelCount; ++c) {
- UString::Rep* rep = m_u.table->entries()[c].key;
- if (!rep) {
- ASSERT(m_u.table->entries()[c].value->isUndefined());
- continue;
- }
- ++nonEmptyEntryCount;
- unsigned i = rep->computedHash();
- unsigned k = 0;
- unsigned entryIndex;
- while (1) {
- entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
- ASSERT(entryIndex != emptyEntryIndex);
- if (rep == m_u.table->entries()[entryIndex - 1].key)
- break;
- if (k == 0)
- k = 1 | doubleHash(rep->computedHash());
- i += k;
- }
- ASSERT(entryIndex == c + 1);
- }
-
- ASSERT(nonEmptyEntryCount == m_u.table->keyCount);
-}
-
-#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
-
-} // namespace KJS
+++ /dev/null
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_PROPERTY_MAP_H_
-#define KJS_PROPERTY_MAP_H_
-
-#include "identifier.h"
-#include "protect.h"
-#include <wtf/OwnArrayPtr.h>
-
-namespace KJS {
-
- class JSObject;
- class JSValue;
- class PropertyNameArray;
-
- struct PropertyMapEntry;
- struct PropertyMapHashTable;
-
- class SavedProperty : Noncopyable {
- public:
- // Since we use this in arrays, we allocate it uninitialized
- // and then explicitly initialize. This means we can allocate
- // the array without initializing every saved property in the
- // array twice. To accomplish this, the class uses data members
- // with types that don't have constructors.
- SavedProperty();
- void init(UString::Rep* name, JSValue*, unsigned attributes);
- ~SavedProperty();
-
- UString::Rep* name() const;
- JSValue* value() const;
- unsigned attributes() const;
-
- private:
- UString::Rep* m_name;
- JSValue* m_value;
- unsigned m_attributes;
- };
-
- struct SavedProperties {
- SavedProperties();
- ~SavedProperties();
-
- unsigned count;
- OwnArrayPtr<SavedProperty> properties;
- };
-
- class PropertyMap : Noncopyable {
- public:
- PropertyMap();
- ~PropertyMap();
-
- void clear();
-
- void put(const Identifier&, JSValue*, unsigned attributes, bool checkReadOnly = false);
- void remove(const Identifier&);
- JSValue* get(const Identifier&) const;
- JSValue* get(const Identifier&, unsigned& attributes) const;
- JSValue** getLocation(const Identifier& name);
-
- void mark() const;
- void getEnumerablePropertyNames(PropertyNameArray&) const;
-
- void save(SavedProperties&) const;
- void restore(const SavedProperties&);
-
- bool hasGetterSetterProperties() const { return m_getterSetterFlag; }
- void setHasGetterSetterProperties(bool f) { m_getterSetterFlag = f; }
-
- bool containsGettersOrSetters() const;
-
- private:
- typedef PropertyMapEntry Entry;
- typedef PropertyMapHashTable Table;
-
- static bool keysMatch(const UString::Rep*, const UString::Rep*);
- void expand();
- void rehash();
- void rehash(unsigned newTableSize);
- void createTable();
-
- void insert(const Entry&);
-
- void checkConsistency();
-
- UString::Rep* m_singleEntryKey;
- union {
- JSValue* singleEntryValue;
- Table* table;
- } m_u;
-
- short m_singleEntryAttributes;
- bool m_getterSetterFlag : 1;
- bool m_usingTable : 1;
- };
-
- inline PropertyMap::PropertyMap()
- : m_singleEntryKey(0)
- , m_getterSetterFlag(false)
- , m_usingTable(false)
-
- {
- }
-
- inline SavedProperty::SavedProperty()
-#ifndef NDEBUG
- : m_name(0)
- , m_value(0)
- , m_attributes(0)
-#endif
- {
- }
-
- inline void SavedProperty::init(UString::Rep* name, JSValue* value, unsigned attributes)
- {
- ASSERT(name);
- ASSERT(value);
-
- ASSERT(!m_name);
- ASSERT(!m_value);
- ASSERT(!m_attributes);
-
- m_name = name;
- m_value = value;
- m_attributes = attributes;
- name->ref();
- gcProtect(value);
- }
-
- inline SavedProperty::~SavedProperty()
- {
- ASSERT(m_name);
- ASSERT(m_value);
-
- m_name->deref();
- gcUnprotect(m_value);
- }
-
- inline UString::Rep* SavedProperty::name() const
- {
- ASSERT(m_name);
- ASSERT(m_value);
-
- return m_name;
- }
-
- inline JSValue* SavedProperty::value() const
- {
- ASSERT(m_name);
- ASSERT(m_value);
-
- return m_value;
- }
-
- inline unsigned SavedProperty::attributes() const
- {
- ASSERT(m_name);
- ASSERT(m_value);
-
- return m_attributes;
- }
-
-} // namespace
-
-#endif // _KJS_PROPERTY_MAP_H_
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "config.h"
-#include "property_slot.h"
-#include "object.h"
-
-namespace KJS {
-
-JSValue *PropertySlot::undefinedGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
-{
- return jsUndefined();
-}
-
-JSValue* PropertySlot::ungettableGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
-{
- ASSERT_NOT_REACHED();
- return jsUndefined();
-}
-
-JSValue *PropertySlot::functionGetter(ExecState* exec, JSObject* originalObject, const Identifier&, const PropertySlot& slot)
-{
- return slot.m_data.getterFunc->call(exec, originalObject, exec->emptyList());
-}
-
-}
+++ /dev/null
-// -*- c-basic-offset: 4 -*-
-/*
- * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_PROPERTY_SLOT_H
-#define KJS_PROPERTY_SLOT_H
-
-#include "identifier.h"
-#include "value.h"
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-class ExecState;
-class JSObject;
-
-struct HashEntry;
-
-#define KJS_VALUE_SLOT_MARKER 0
-#define KJS_NUMERIC_PROPERTY_NAME_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
-
-class PropertySlot {
-public:
- typedef JSValue* (*GetValueFunc)(ExecState*, JSObject* originalObject, const Identifier&, const PropertySlot&);
- typedef JSValue* (*GetValueNumericFunc)(ExecState*, JSObject* originalObject, unsigned index, const PropertySlot&);
-
- JSValue* getValue(ExecState* exec, JSObject* originalObject, const Identifier& propertyName) const
- {
- if (m_getValue == KJS_VALUE_SLOT_MARKER)
- return *m_data.valueSlot;
- ASSERT(m_getValue != KJS_NUMERIC_PROPERTY_NAME_SLOT_MARKER);
- return m_getValue(exec, originalObject, propertyName, *this);
- }
-
- JSValue* getValue(ExecState* exec, JSObject* originalObject, unsigned propertyName) const
- {
- if (m_getValue == KJS_VALUE_SLOT_MARKER)
- return *m_data.valueSlot;
- if (m_getValue == KJS_NUMERIC_PROPERTY_NAME_SLOT_MARKER)
- return m_data.numericFunc(exec, originalObject, propertyName, *this);
- return m_getValue(exec, originalObject, Identifier::from(propertyName), *this);
- }
-
- void setValueSlot(JSObject* slotBase, JSValue** valueSlot)
- {
- m_getValue = KJS_VALUE_SLOT_MARKER;
- m_slotBase = slotBase;
- m_data.valueSlot = valueSlot;
- }
-
- void setStaticEntry(JSObject* slotBase, const HashEntry* staticEntry, GetValueFunc getValue)
- {
- ASSERT(getValue);
- m_getValue = getValue;
- m_slotBase = slotBase;
- m_data.staticEntry = staticEntry;
- }
-
- void setCustom(JSObject* slotBase, GetValueFunc getValue)
- {
- ASSERT(getValue);
- m_getValue = getValue;
- m_slotBase = slotBase;
- }
-
- void setCustomIndex(JSObject* slotBase, unsigned index, GetValueFunc getValue)
- {
- ASSERT(getValue);
- m_getValue = getValue;
- m_slotBase = slotBase;
- m_data.index = index;
- }
-
- void setCustomNumeric(JSObject* slotBase, GetValueNumericFunc getValue)
- {
- ASSERT(getValue);
- m_slotBase = slotBase;
- m_getValue = KJS_NUMERIC_PROPERTY_NAME_SLOT_MARKER;
- m_data.numericFunc = getValue;
- }
-
- void setGetterSlot(JSObject* slotBase, JSObject* getterFunc)
- {
- m_getValue = functionGetter;
- m_slotBase = slotBase;
- m_data.getterFunc = getterFunc;
- }
-
- void setUndefined(JSObject *slotBase)
- {
- m_slotBase = slotBase;
- m_getValue = undefinedGetter;
- }
-
- void setUngettable(JSObject* slotBase) // Used to signal that you have a property, but trying to get it at this time is an error.
- {
- m_slotBase = slotBase;
- m_getValue = ungettableGetter;
- }
-
- JSObject* slotBase() const { return m_slotBase; }
-
- const HashEntry* staticEntry() const { return m_data.staticEntry; }
- unsigned index() const { return m_data.index; }
-
-private:
- static JSValue* undefinedGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- static JSValue* ungettableGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- static JSValue* functionGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
-
- GetValueFunc m_getValue;
-
- JSObject* m_slotBase;
- union {
- JSObject* getterFunc;
- JSValue** valueSlot;
- const HashEntry* staticEntry;
- unsigned index;
- GetValueNumericFunc numericFunc;
- } m_data;
-};
-
-}
-
-#endif // KJS_PROPERTY_SLOT_H
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2004 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-
-#ifndef _KJS_PROTECT_H_
-#define _KJS_PROTECT_H_
-
-#include "value.h"
-#include "collector.h"
-#include "JSLock.h"
-
-namespace KJS {
-
- inline void gcProtect(JSValue *val)
- {
- Collector::protect(val);
- }
-
- inline void gcUnprotect(JSValue *val)
- {
- Collector::unprotect(val);
- }
-
- inline void gcProtectNullTolerant(JSValue *val)
- {
- if (val)
- gcProtect(val);
- }
-
- inline void gcUnprotectNullTolerant(JSValue *val)
- {
- if (val)
- gcUnprotect(val);
- }
-
- // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
- // and the implicit conversion to raw pointer
- template <class T> class ProtectedPtr {
- public:
- ProtectedPtr() : m_ptr(NULL) { }
- ProtectedPtr(T *ptr);
- ProtectedPtr(const ProtectedPtr &);
- ~ProtectedPtr();
-
- template <class U> ProtectedPtr(const ProtectedPtr<U> &);
-
- T *get() const { return m_ptr; }
- operator T *() const { return m_ptr; }
- T *operator->() const { return m_ptr; }
-
- bool operator!() const { return m_ptr == NULL; }
-
- ProtectedPtr &operator=(const ProtectedPtr &);
- ProtectedPtr &operator=(T *);
-
- private:
- T *m_ptr;
- };
-
- template <class T> ProtectedPtr<T>::ProtectedPtr(T *ptr)
- : m_ptr(ptr)
- {
- if (ptr) {
- JSLock lock;
- gcProtect(ptr);
- }
- }
-
- template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr &o)
- : m_ptr(o.get())
- {
- if (T *ptr = m_ptr) {
- JSLock lock;
- gcProtect(ptr);
- }
- }
-
- template <class T> ProtectedPtr<T>::~ProtectedPtr()
- {
- if (T *ptr = m_ptr) {
- JSLock lock;
- gcUnprotect(ptr);
- }
- }
-
- template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U> &o)
- : m_ptr(o.get())
- {
- if (T *ptr = m_ptr) {
- JSLock lock;
- gcProtect(ptr);
- }
- }
-
- template <class T> ProtectedPtr<T> &ProtectedPtr<T>::operator=(const ProtectedPtr<T> &o)
- {
- JSLock lock;
- T *optr = o.m_ptr;
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- template <class T> inline ProtectedPtr<T> &ProtectedPtr<T>::operator=(T *optr)
- {
- JSLock lock;
- gcProtectNullTolerant(optr);
- gcUnprotectNullTolerant(m_ptr);
- m_ptr = optr;
- return *this;
- }
-
- template <class T> inline bool operator==(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() == b.get(); }
- template <class T> inline bool operator==(const ProtectedPtr<T> &a, const T *b) { return a.get() == b; }
- template <class T> inline bool operator==(const T *a, const ProtectedPtr<T> &b) { return a == b.get(); }
-
- template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() != b.get(); }
- template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const T *b) { return a.get() != b; }
- template <class T> inline bool operator!=(const T *a, const ProtectedPtr<T> &b) { return a != b.get(); }
-
-} // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
- * Copyright (c) 2007, Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "regexp.h"
-
-#include "lexer.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
-RegExp::RegExp(const UString& pattern)
- : m_pattern(pattern)
- , m_flagBits(0)
- , m_constructionError(0)
- , m_numSubpatterns(0)
-{
- m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(pattern.data()), pattern.size(),
- JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
-}
-
-RegExp::RegExp(const UString& pattern, const UString& flags)
- : m_pattern(pattern)
- , m_flags(flags)
- , m_flagBits(0)
- , m_constructionError(0)
- , m_numSubpatterns(0)
-{
- // NOTE: The global flag is handled on a case-by-case basis by functions like
- // String::match and RegExpImp::match.
- if (flags.find('g') != -1)
- m_flagBits |= Global;
-
- // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
- JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
- if (flags.find('i') != -1) {
- m_flagBits |= IgnoreCase;
- ignoreCaseOption = JSRegExpIgnoreCase;
- }
-
- JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
- if (flags.find('m') != -1) {
- m_flagBits |= Multiline;
- multilineOption = JSRegExpMultiline;
- }
-
- m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(pattern.data()), pattern.size(),
- ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
-}
-
-RegExp::~RegExp()
-{
- jsRegExpFree(m_regExp);
-}
-
-int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
-{
- if (i < 0)
- i = 0;
- if (ovector)
- ovector->clear();
-
- if (i > s.size() || s.isNull())
- return -1;
-
- if (!m_regExp)
- return -1;
-
- // Set up the offset vector for the result.
- // First 2/3 used for result, the last third used by PCRE.
- int* offsetVector;
- int offsetVectorSize;
- int fixedSizeOffsetVector[3];
- if (!ovector) {
- offsetVectorSize = 3;
- offsetVector = fixedSizeOffsetVector;
- } else {
- offsetVectorSize = (m_numSubpatterns + 1) * 3;
- offsetVector = new int [offsetVectorSize];
- ovector->set(offsetVector);
- }
-
- int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const ::UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
-
- if (numMatches < 0) {
-#ifndef NDEBUG
- if (numMatches != JSRegExpErrorNoMatch)
- fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
-#endif
- if (ovector)
- ovector->clear();
- return -1;
- }
-
- return offsetVector[0];
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef KJS_REGEXP_H
-#define KJS_REGEXP_H
-
-#include "ustring.h"
-#include <pcre/pcre.h>
-#include <sys/types.h>
-#include <wtf/OwnArrayPtr.h>
-#include <wtf/RefCounted.h>
-
-namespace KJS {
-
- class RegExp : public RefCounted<RegExp> {
- private:
- enum {
- Global = 1,
- IgnoreCase = 2,
- Multiline = 4
- };
-
- public:
- RegExp(const UString& pattern);
- RegExp(const UString& pattern, const UString& flags);
- ~RegExp();
-
- bool global() const { return m_flagBits & Global; }
- bool ignoreCase() const { return m_flagBits & IgnoreCase; }
- bool multiline() const { return m_flagBits & Multiline; }
-
- const UString& pattern() const { return m_pattern; }
- const UString& flags() const { return m_flags; }
-
- bool isValid() const { return !m_constructionError; }
- const char* errorMessage() const { return m_constructionError; }
-
- int match(const UString&, int offset, OwnArrayPtr<int>* ovector = 0);
- unsigned numSubpatterns() const { return m_numSubpatterns; }
-
- private:
- void compile();
-
- // Data supplied by caller.
- UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
- UString m_flags; // FIXME: Just decompile m_regExp instead of storing this.
- int m_flagBits;
-
- // Data supplied by PCRE.
- JSRegExp* m_regExp;
- const char* m_constructionError;
- unsigned m_numSubpatterns;
- };
-
-} // namespace
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "regexp_object.h"
-#include "regexp_object.lut.h"
-
-#include "array_instance.h"
-#include "array_object.h"
-#include "error_object.h"
-#include "internal.h"
-#include "object.h"
-#include "operations.h"
-#include "regexp.h"
-#include "types.h"
-#include "value.h"
-#include "UnusedParam.h"
-
-#include <stdio.h>
-
-namespace KJS {
-
-// ------------------------------ RegExpPrototype ---------------------------
-
-static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, const List&);
-static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, const List&);
-static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, const List&);
-static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, const List&);
-
-// ECMA 15.10.5
-
-const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0 };
-
-RegExpPrototype::RegExpPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
- : JSObject(objectPrototype)
-{
- static const Identifier* compilePropertyName = new Identifier("compile");
- static const Identifier* execPropertyName = new Identifier("exec");
- static const Identifier* testPropertyName = new Identifier("test");
-
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *compilePropertyName, regExpProtoFuncCompile), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *execPropertyName, regExpProtoFuncExec), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *testPropertyName, regExpProtoFuncTest), DontEnum);
- putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
-}
-
-// ------------------------------ Functions ---------------------------
-
-JSValue* regExpProtoFuncTest(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&RegExpImp::info))
- return throwError(exec, TypeError);
-
- return static_cast<RegExpImp*>(thisObj)->test(exec, args);
-}
-
-JSValue* regExpProtoFuncExec(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&RegExpImp::info))
- return throwError(exec, TypeError);
-
- return static_cast<RegExpImp*>(thisObj)->exec(exec, args);
-}
-
-JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (!thisObj->inherits(&RegExpImp::info))
- return throwError(exec, TypeError);
-
- RefPtr<RegExp> regExp;
- JSValue* arg0 = args[0];
- JSValue* arg1 = args[1];
-
- if (arg0->isObject(&RegExpImp::info)) {
- if (!arg1->isUndefined())
- return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
- regExp = static_cast<RegExpImp*>(arg0)->regExp();
- } else {
- UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
- UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- regExp = new RegExp(pattern, flags);
- }
-
- if (!regExp->isValid())
- return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
-
- static_cast<RegExpImp*>(thisObj)->setRegExp(regExp.release());
- static_cast<RegExpImp*>(thisObj)->setLastIndex(0);
- return jsUndefined();
-}
-
-JSValue* regExpProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&RegExpImp::info)) {
- if (thisObj->inherits(&RegExpPrototype::info))
- return jsString("//");
- return throwError(exec, TypeError);
- }
-
- UString result = "/" + thisObj->get(exec, exec->propertyNames().source)->toString(exec) + "/";
- if (thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec))
- result += "g";
- if (thisObj->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))
- result += "i";
- if (thisObj->get(exec, exec->propertyNames().multiline)->toBoolean(exec))
- result += "m";
- return jsString(result);
-}
-
-// ------------------------------ RegExpImp ------------------------------------
-
-const ClassInfo RegExpImp::info = { "RegExp", 0, &RegExpImpTable };
-
-/* Source for regexp_object.lut.h
-@begin RegExpImpTable 5
- global RegExpImp::Global DontDelete|ReadOnly|DontEnum
- ignoreCase RegExpImp::IgnoreCase DontDelete|ReadOnly|DontEnum
- multiline RegExpImp::Multiline DontDelete|ReadOnly|DontEnum
- source RegExpImp::Source DontDelete|ReadOnly|DontEnum
- lastIndex RegExpImp::LastIndex DontDelete|DontEnum
-@end
-*/
-
-RegExpImp::RegExpImp(RegExpPrototype* regexpProto, PassRefPtr<RegExp> regExp)
- : JSObject(regexpProto)
- , m_regExp(regExp)
- , m_lastIndex(0)
-{
-}
-
-RegExpImp::~RegExpImp()
-{
-}
-
-bool RegExpImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getStaticValueSlot<RegExpImp, JSObject>(exec, &RegExpImpTable, this, propertyName, slot);
-}
-
-JSValue* RegExpImp::getValueProperty(ExecState*, int token) const
-{
- switch (token) {
- case Global:
- return jsBoolean(m_regExp->global());
- case IgnoreCase:
- return jsBoolean(m_regExp->ignoreCase());
- case Multiline:
- return jsBoolean(m_regExp->multiline());
- case Source:
- return jsString(m_regExp->pattern());
- case LastIndex:
- return jsNumber(m_lastIndex);
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-void RegExpImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attributes)
-{
- lookupPut<RegExpImp, JSObject>(exec, propertyName, value, attributes, &RegExpImpTable, this);
-}
-
-void RegExpImp::putValueProperty(ExecState* exec, int token, JSValue* value, int)
-{
- UNUSED_PARAM(token);
- ASSERT(token == LastIndex);
- m_lastIndex = value->toInteger(exec);
-}
-
-bool RegExpImp::match(ExecState* exec, const List& args)
-{
- RegExpObjectImp* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
-
- UString input;
- if (!args.isEmpty())
- input = args[0]->toString(exec);
- else {
- input = regExpObj->input();
- if (input.isNull()) {
- throwError(exec, GeneralError, "No input.");
- return false;
- }
- }
-
- bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
- int lastIndex = 0;
- if (global) {
- if (m_lastIndex < 0 || m_lastIndex > input.size()) {
- m_lastIndex = 0;
- return false;
- }
- lastIndex = static_cast<int>(m_lastIndex);
- }
-
- int foundIndex;
- int foundLength;
- regExpObj->performMatch(m_regExp.get(), input, lastIndex, foundIndex, foundLength);
-
- if (global) {
- lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
- m_lastIndex = lastIndex;
- }
-
- return foundIndex >= 0;
-}
-
-JSValue* RegExpImp::test(ExecState* exec, const List& args)
-{
- return jsBoolean(match(exec, args));
-}
-
-JSValue* RegExpImp::exec(ExecState* exec, const List& args)
-{
- return match(exec, args)
- ? exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec)
- : jsNull();
-}
-
-bool RegExpImp::implementsCall() const
-{
- return true;
-}
-
-JSValue* RegExpImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
-{
- return RegExpImp::exec(exec, args);
-}
-
-// ------------------------------ RegExpObjectImp ------------------------------
-
-const ClassInfo RegExpObjectImp::info = { "Function", &InternalFunctionImp::info, &RegExpObjectImpTable };
-
-/* Source for regexp_object.lut.h
-@begin RegExpObjectImpTable 21
- input RegExpObjectImp::Input None
- $_ RegExpObjectImp::Input DontEnum
- multiline RegExpObjectImp::Multiline None
- $* RegExpObjectImp::Multiline DontEnum
- lastMatch RegExpObjectImp::LastMatch DontDelete|ReadOnly
- $& RegExpObjectImp::LastMatch DontDelete|ReadOnly|DontEnum
- lastParen RegExpObjectImp::LastParen DontDelete|ReadOnly
- $+ RegExpObjectImp::LastParen DontDelete|ReadOnly|DontEnum
- leftContext RegExpObjectImp::LeftContext DontDelete|ReadOnly
- $` RegExpObjectImp::LeftContext DontDelete|ReadOnly|DontEnum
- rightContext RegExpObjectImp::RightContext DontDelete|ReadOnly
- $' RegExpObjectImp::RightContext DontDelete|ReadOnly|DontEnum
- $1 RegExpObjectImp::Dollar1 DontDelete|ReadOnly
- $2 RegExpObjectImp::Dollar2 DontDelete|ReadOnly
- $3 RegExpObjectImp::Dollar3 DontDelete|ReadOnly
- $4 RegExpObjectImp::Dollar4 DontDelete|ReadOnly
- $5 RegExpObjectImp::Dollar5 DontDelete|ReadOnly
- $6 RegExpObjectImp::Dollar6 DontDelete|ReadOnly
- $7 RegExpObjectImp::Dollar7 DontDelete|ReadOnly
- $8 RegExpObjectImp::Dollar8 DontDelete|ReadOnly
- $9 RegExpObjectImp::Dollar9 DontDelete|ReadOnly
-@end
-*/
-
-struct RegExpObjectImpPrivate {
- // Global search cache / settings
- RegExpObjectImpPrivate() : lastNumSubPatterns(0), multiline(false) { }
- UString lastInput;
- OwnArrayPtr<int> lastOvector;
- unsigned lastNumSubPatterns : 31;
- bool multiline : 1;
-};
-
-RegExpObjectImp::RegExpObjectImp(ExecState* exec, FunctionPrototype* funcProto, RegExpPrototype* regProto)
- : InternalFunctionImp(funcProto, "RegExp")
- , d(new RegExpObjectImpPrivate)
-{
- // ECMA 15.10.5.1 RegExp.prototype
- putDirect(exec->propertyNames().prototype, regProto, DontEnum | DontDelete | ReadOnly);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
-}
-
-/*
- To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
- expression matching through the performMatch function. We use cached results to calculate,
- e.g., RegExp.lastMatch and RegExp.leftParen.
-*/
-void RegExpObjectImp::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
-{
- OwnArrayPtr<int> tmpOvector;
- position = r->match(s, startOffset, &tmpOvector);
-
- if (ovector)
- *ovector = tmpOvector.get();
-
- if (position != -1) {
- ASSERT(tmpOvector);
-
- length = tmpOvector[1] - tmpOvector[0];
-
- d->lastInput = s;
- d->lastOvector.set(tmpOvector.release());
- d->lastNumSubPatterns = r->numSubpatterns();
- }
-}
-
-JSObject* RegExpObjectImp::arrayOfMatches(ExecState* exec) const
-{
- unsigned lastNumSubpatterns = d->lastNumSubPatterns;
- ArrayInstance* arr = new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), lastNumSubpatterns + 1);
- for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
- int start = d->lastOvector[2 * i];
- if (start >= 0)
- arr->put(exec, i, jsString(d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start)));
- }
- arr->put(exec, exec->propertyNames().index, jsNumber(d->lastOvector[0]));
- arr->put(exec, exec->propertyNames().input, jsString(d->lastInput));
- return arr;
-}
-
-JSValue* RegExpObjectImp::getBackref(unsigned i) const
-{
- if (d->lastOvector && i <= d->lastNumSubPatterns)
- return jsString(d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i]));
- return jsString("");
-}
-
-JSValue* RegExpObjectImp::getLastParen() const
-{
- unsigned i = d->lastNumSubPatterns;
- if (i > 0) {
- ASSERT(d->lastOvector);
- return jsString(d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i]));
- }
- return jsString("");
-}
-
-JSValue *RegExpObjectImp::getLeftContext() const
-{
- if (d->lastOvector)
- return jsString(d->lastInput.substr(0, d->lastOvector[0]));
- return jsString("");
-}
-
-JSValue *RegExpObjectImp::getRightContext() const
-{
- if (d->lastOvector) {
- UString s = d->lastInput;
- return jsString(s.substr(d->lastOvector[1], s.size() - d->lastOvector[1]));
- }
- return jsString("");
-}
-
-bool RegExpObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
-{
- return getStaticValueSlot<RegExpObjectImp, InternalFunctionImp>(exec, &RegExpObjectImpTable, this, propertyName, slot);
-}
-
-JSValue *RegExpObjectImp::getValueProperty(ExecState*, int token) const
-{
- switch (token) {
- case Dollar1:
- return getBackref(1);
- case Dollar2:
- return getBackref(2);
- case Dollar3:
- return getBackref(3);
- case Dollar4:
- return getBackref(4);
- case Dollar5:
- return getBackref(5);
- case Dollar6:
- return getBackref(6);
- case Dollar7:
- return getBackref(7);
- case Dollar8:
- return getBackref(8);
- case Dollar9:
- return getBackref(9);
- case Input:
- return jsString(d->lastInput);
- case Multiline:
- return jsBoolean(d->multiline);
- case LastMatch:
- return getBackref(0);
- case LastParen:
- return getLastParen();
- case LeftContext:
- return getLeftContext();
- case RightContext:
- return getRightContext();
- default:
- ASSERT(0);
- }
-
- return jsString("");
-}
-
-void RegExpObjectImp::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
-{
- lookupPut<RegExpObjectImp, InternalFunctionImp>(exec, propertyName, value, attr, &RegExpObjectImpTable, this);
-}
-
-void RegExpObjectImp::putValueProperty(ExecState *exec, int token, JSValue *value, int)
-{
- switch (token) {
- case Input:
- d->lastInput = value->toString(exec);
- break;
- case Multiline:
- d->multiline = value->toBoolean(exec);
- break;
- default:
- ASSERT(0);
- }
-}
-
-bool RegExpObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.10.4
-JSObject *RegExpObjectImp::construct(ExecState *exec, const List &args)
-{
- JSValue* arg0 = args[0];
- JSValue* arg1 = args[1];
-
- if (arg0->isObject(&RegExpImp::info)) {
- if (!arg1->isUndefined())
- return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
- return static_cast<JSObject*>(arg0);
- }
-
- UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
- UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
-
- return createRegExpImp(exec, new RegExp(pattern, flags));
-}
-
-JSObject* RegExpObjectImp::createRegExpImp(ExecState* exec, PassRefPtr<RegExp> regExp)
-{
- return regExp->isValid()
- ? new RegExpImp(static_cast<RegExpPrototype*>(exec->lexicalGlobalObject()->regExpPrototype()), regExp)
- : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
-}
-
-// ECMA 15.10.3
-JSValue *RegExpObjectImp::callAsFunction(ExecState *exec, JSObject * /*thisObj*/, const List &args)
-{
- return construct(exec, args);
-}
-
-const UString& RegExpObjectImp::input() const
-{
- // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
- // state (since jsString turns null strings to empty strings).
- return d->lastInput;
-}
-
-}
+++ /dev/null
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef REGEXP_OBJECT_H_
-#define REGEXP_OBJECT_H_
-
-#include "function_object.h"
-#include "regexp.h"
-
-namespace KJS {
-
- struct RegExpObjectImpPrivate;
-
- class RegExpPrototype : public JSObject {
- public:
- RegExpPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class RegExpImp : public JSObject {
- public:
- enum { Global, IgnoreCase, Multiline, Source, LastIndex };
-
- RegExpImp(RegExpPrototype*, PassRefPtr<RegExp>);
- virtual ~RegExpImp();
-
- void setRegExp(PassRefPtr<RegExp> r) { m_regExp = r; }
- RegExp* regExp() const { return m_regExp.get(); }
-
- JSValue* test(ExecState*, const List& args);
- JSValue* exec(ExecState*, const List& args);
-
- virtual bool implementsCall() const;
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- JSValue* getValueProperty(ExecState*, int token) const;
- void put(ExecState*, const Identifier&, JSValue*, int attributes = None);
- void putValueProperty(ExecState*, int token, JSValue*, int attributes);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- void setLastIndex(double lastIndex) { m_lastIndex = lastIndex; }
-
- private:
- bool match(ExecState*, const List& args);
-
- RefPtr<RegExp> m_regExp;
- double m_lastIndex;
- };
-
- class RegExpObjectImp : public InternalFunctionImp {
- public:
- enum { Dollar1, Dollar2, Dollar3, Dollar4, Dollar5, Dollar6, Dollar7, Dollar8, Dollar9,
- Input, Multiline, LastMatch, LastParen, LeftContext, RightContext };
-
- RegExpObjectImp(ExecState*, FunctionPrototype*, RegExpPrototype*);
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List&);
- JSObject* createRegExpImp(ExecState*, PassRefPtr<RegExp>);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- virtual void put(ExecState*, const Identifier&, JSValue*, int attributes = None);
- void putValueProperty(ExecState*, int token, JSValue*, int attributes);
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- JSValue* getValueProperty(ExecState*, int token) const;
- virtual const ClassInfo* classInfo() const { return &info; }
-
- void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
- JSObject* arrayOfMatches(ExecState*) const;
- const UString& input() const;
-
- private:
- JSValue* getBackref(unsigned) const;
- JSValue* getLastParen() const;
- JSValue* getLeftContext() const;
- JSValue* getRightContext() const;
-
- OwnPtr<RegExpObjectImpPrivate> d;
-
- static const ClassInfo info;
- };
-
-} // namespace
-
-#endif
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003, 2006 Apple Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "scope_chain.h"
-#include "PropertyNameArray.h"
-#include <stdio.h>
-#include "object.h"
-
-namespace KJS {
-
-void ScopeChain::push(const ScopeChain &c)
-{
- ScopeChainNode **tail = &_node;
- for (ScopeChainNode *n = c._node; n; n = n->next) {
- ScopeChainNode *newNode = new ScopeChainNode(*tail, n->object);
- *tail = newNode;
- tail = &newNode->next;
- }
-}
-
-#ifndef NDEBUG
-
-void ScopeChain::print()
-{
- ScopeChainIterator scopeEnd = end();
- for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
- JSObject* o = *scopeIter;
- PropertyNameArray propertyNames;
- // FIXME: should pass ExecState here!
- o->getPropertyNames(0, propertyNames);
- PropertyNameArray::const_iterator propEnd = propertyNames.end();
-
- fprintf(stderr, "----- [scope %p] -----\n", o);
- for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
- Identifier name = *propIter;
- fprintf(stderr, "%s, ", name.ascii());
- }
- fprintf(stderr, "\n");
- }
-}
-
-#endif
-
-} // namespace KJS
+++ /dev/null
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_SCOPE_CHAIN_H
-#define KJS_SCOPE_CHAIN_H
-
-#include <wtf/Assertions.h>
-
-namespace KJS {
-
- class JSObject;
- class ExecState;
-
- class ScopeChainNode {
- public:
- ScopeChainNode(ScopeChainNode *n, JSObject *o)
- : next(n), object(o), refCount(1) { }
-
- ScopeChainNode *next;
- JSObject *object;
- int refCount;
- };
-
- class ScopeChainIterator {
- public:
- ScopeChainIterator(ScopeChainNode *node) : m_node(node) {}
-
- JSObject * const & operator*() const { return m_node->object; }
- JSObject * const * operator->() const { return &(operator*()); }
-
- ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
-
- // postfix ++ intentionally omitted
-
- bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
- bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
-
- private:
- ScopeChainNode *m_node;
- };
-
- class ScopeChain {
- public:
- typedef ScopeChainIterator const_iterator;
- typedef JSObject* ValueType;
-
- ScopeChain() : _node(0) { }
- ~ScopeChain() { deref(); }
-
- ScopeChain(const ScopeChain &c) : _node(c._node)
- { if (_node) ++_node->refCount; }
- ScopeChain &operator=(const ScopeChain &);
-
- bool isEmpty() const { return !_node; }
- JSObject *top() const { return _node->object; }
-
- JSObject *bottom() const;
-
- ScopeChainIterator begin() const { return ScopeChainIterator(_node); }
- ScopeChainIterator end() const { return ScopeChainIterator(0); }
-
- void clear() { deref(); _node = 0; }
- void push(JSObject *);
- void push(const ScopeChain &);
- void replaceTop(JSObject*);
- void pop();
-
- void mark();
-
-#ifndef NDEBUG
- void print();
-#endif
-
- private:
- ScopeChainNode *_node;
-
- void deref() { if (_node && --_node->refCount == 0) release(); }
- void ref() const;
-
- void release();
- };
-
-inline void ScopeChain::ref() const
-{
- for (ScopeChainNode *n = _node; n; n = n->next) {
- if (n->refCount++ != 0)
- break;
- }
-}
-
-inline ScopeChain &ScopeChain::operator=(const ScopeChain &c)
-{
- c.ref();
- deref();
- _node = c._node;
- return *this;
-}
-
-inline JSObject *ScopeChain::bottom() const
-{
- ScopeChainNode *last = 0;
- for (ScopeChainNode *n = _node; n; n = n->next)
- last = n;
- if (!last)
- return 0;
- return last->object;
-}
-
-inline void ScopeChain::push(JSObject *o)
-{
- ASSERT(o);
- _node = new ScopeChainNode(_node, o);
-}
-
-inline void ScopeChain::replaceTop(JSObject* o)
-{
- ASSERT(o);
- _node->object = o;
-}
-
-inline void ScopeChain::pop()
-{
- ScopeChainNode *oldNode = _node;
- ASSERT(oldNode);
- ScopeChainNode *newNode = oldNode->next;
- _node = newNode;
-
- if (--oldNode->refCount != 0) {
- if (newNode)
- ++newNode->refCount;
- } else {
- delete oldNode;
- }
-}
-
-} // namespace KJS
-
-#endif // KJS_SCOPE_CHAIN_H
+++ /dev/null
-/*
- * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef scope_chain_mark_h
-#define scope_chain_mark_h
-
-#include "Activation.h"
-#include "scope_chain.h"
-
-namespace KJS {
-
- inline void ScopeChain::mark()
- {
- for (ScopeChainNode* n = _node; n; n = n->next) {
- JSObject* o = n->object;
-
- // An ActivationImp that is on the activation stack can't have the
- // JSObject::marked() method called on it, because it doesn't have an
- // entry in a GC mark bitmap, so we check here whether it is on the
- // stack and directly call the portion of the marking code that is
- // still relevant.
-
- if (o->isActivationObject() && static_cast<ActivationImp*>(o)->isOnStack())
- static_cast<ActivationImp*>(o)->markChildren();
- else if (!o->marked())
- o->mark();
- }
- }
-
-} // namespace KJS
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "config.h"
-#include "string_object.h"
-#include "string_object.lut.h"
-
-#include "JSWrapperObject.h"
-#include "PropertyNameArray.h"
-#include "array_object.h"
-#include "error_object.h"
-#include "operations.h"
-#include "regexp_object.h"
-#include <wtf/MathExtras.h>
-#include <wtf/unicode/Unicode.h>
-
-#if PLATFORM(CF)
-#include <CoreFoundation/CoreFoundation.h>
-#elif PLATFORM(WIN_OS)
-#include <windows.h>
-#endif
-
-using namespace WTF;
-
-namespace KJS {
-
-// ------------------------------ StringInstance ----------------------------
-
-const ClassInfo StringInstance::info = { "String", 0, 0 };
-
-StringInstance::StringInstance(JSObject *proto)
- : JSWrapperObject(proto)
-{
- setInternalValue(jsString(""));
-}
-
-StringInstance::StringInstance(JSObject *proto, StringImp* string)
- : JSWrapperObject(proto)
-{
- setInternalValue(string);
-}
-
-StringInstance::StringInstance(JSObject *proto, const UString &string)
- : JSWrapperObject(proto)
-{
- setInternalValue(jsString(string));
-}
-
-JSValue *StringInstance::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot &slot)
-{
- return jsNumber(static_cast<StringInstance*>(slot.slotBase())->internalValue()->value().size());
-}
-
-JSValue* StringInstance::indexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- return jsString(static_cast<StringInstance*>(slot.slotBase())->internalValue()->value().substr(slot.index(), 1));
-}
-
-static JSValue* stringInstanceNumericPropertyGetter(ExecState*, JSObject*, unsigned index, const PropertySlot& slot)
-{
- return jsString(static_cast<StringInstance*>(slot.slotBase())->internalValue()->value().substr(index, 1));
-}
-
-bool StringInstance::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- bool isStrictUInt32;
- unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
- unsigned length = internalValue()->value().size();
- if (isStrictUInt32 && i < length) {
- slot.setCustomIndex(this, i, indexGetter);
- return true;
- }
-
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-bool StringInstance::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
-{
- unsigned length = internalValue()->value().size();
- if (propertyName < length) {
- slot.setCustomNumeric(this, stringInstanceNumericPropertyGetter);
- return true;
- }
-
- return JSObject::getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
-}
-
-void StringInstance::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
-{
- if (propertyName == exec->propertyNames().length)
- return;
- JSObject::put(exec, propertyName, value, attr);
-}
-
-bool StringInstance::deleteProperty(ExecState *exec, const Identifier &propertyName)
-{
- if (propertyName == exec->propertyNames().length)
- return false;
- return JSObject::deleteProperty(exec, propertyName);
-}
-
-void StringInstance::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
-{
- int size = internalValue()->getString().size();
- for (int i = 0; i < size; i++)
- propertyNames.add(Identifier(UString::from(i)));
- return JSObject::getPropertyNames(exec, propertyNames);
-}
-
-// ------------------------------ StringPrototype ---------------------------
-const ClassInfo StringPrototype::info = { "String", &StringInstance::info, &stringTable };
-/* Source for string_object.lut.h
-@begin stringTable 26
- toString &stringProtoFuncToString DontEnum|Function 0
- valueOf &stringProtoFuncValueOf DontEnum|Function 0
- charAt &stringProtoFuncCharAt DontEnum|Function 1
- charCodeAt &stringProtoFuncCharCodeAt DontEnum|Function 1
- concat &stringProtoFuncConcat DontEnum|Function 1
- indexOf &stringProtoFuncIndexOf DontEnum|Function 1
- lastIndexOf &stringProtoFuncLastIndexOf DontEnum|Function 1
- match &stringProtoFuncMatch DontEnum|Function 1
- replace &stringProtoFuncReplace DontEnum|Function 2
- search &stringProtoFuncSearch DontEnum|Function 1
- slice &stringProtoFuncSlice DontEnum|Function 2
- split &stringProtoFuncSplit DontEnum|Function 2
- substr &stringProtoFuncSubstr DontEnum|Function 2
- substring &stringProtoFuncSubstring DontEnum|Function 2
- toLowerCase &stringProtoFuncToLowerCase DontEnum|Function 0
- toUpperCase &stringProtoFuncToUpperCase DontEnum|Function 0
- toLocaleLowerCase &stringProtoFuncToLocaleLowerCase DontEnum|Function 0
- toLocaleUpperCase &stringProtoFuncToLocaleUpperCase DontEnum|Function 0
- localeCompare &stringProtoFuncLocaleCompare DontEnum|Function 1
-
- big &stringProtoFuncBig DontEnum|Function 0
- small &stringProtoFuncSmall DontEnum|Function 0
- blink &stringProtoFuncBlink DontEnum|Function 0
- bold &stringProtoFuncBold DontEnum|Function 0
- fixed &stringProtoFuncFixed DontEnum|Function 0
- italics &stringProtoFuncItalics DontEnum|Function 0
- strike &stringProtoFuncStrike DontEnum|Function 0
- sub &stringProtoFuncSub DontEnum|Function 0
- sup &stringProtoFuncSup DontEnum|Function 0
- fontcolor &stringProtoFuncFontcolor DontEnum|Function 1
- fontsize &stringProtoFuncFontsize DontEnum|Function 1
- anchor &stringProtoFuncAnchor DontEnum|Function 1
- link &stringProtoFuncLink DontEnum|Function 1
-@end
-*/
-// ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, ObjectPrototype* objProto)
- : StringInstance(objProto)
-{
- // The constructor will be added later, after StringObjectImp has been built
- putDirect(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
-}
-
-bool StringPrototype::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
-{
- return getStaticFunctionSlot<StringInstance>(exec, &stringTable, this, propertyName, slot);
-}
-
-// ------------------------------ Functions --------------------------
-
-static inline void expandSourceRanges(UString::Range * & array, int& count, int& capacity)
-{
- int newCapacity;
- if (capacity == 0) {
- newCapacity = 16;
- } else {
- newCapacity = capacity * 2;
- }
-
- UString::Range *newArray = new UString::Range[newCapacity];
- for (int i = 0; i < count; i++) {
- newArray[i] = array[i];
- }
-
- delete [] array;
-
- capacity = newCapacity;
- array = newArray;
-}
-
-static void pushSourceRange(UString::Range * & array, int& count, int& capacity, UString::Range range)
-{
- if (count + 1 > capacity)
- expandSourceRanges(array, count, capacity);
-
- array[count] = range;
- count++;
-}
-
-static inline void expandReplacements(UString * & array, int& count, int& capacity)
-{
- int newCapacity;
- if (capacity == 0) {
- newCapacity = 16;
- } else {
- newCapacity = capacity * 2;
- }
-
- UString *newArray = new UString[newCapacity];
- for (int i = 0; i < count; i++) {
- newArray[i] = array[i];
- }
-
- delete [] array;
-
- capacity = newCapacity;
- array = newArray;
-}
-
-static void pushReplacement(UString * & array, int& count, int& capacity, UString replacement)
-{
- if (count + 1 > capacity)
- expandReplacements(array, count, capacity);
-
- array[count] = replacement;
- count++;
-}
-
-static inline UString substituteBackreferences(const UString &replacement, const UString &source, int *ovector, RegExp *reg)
-{
- UString substitutedReplacement = replacement;
-
- int i = -1;
- while ((i = substitutedReplacement.find(UString("$"), i + 1)) != -1) {
- if (i+1 == substitutedReplacement.size())
- break;
-
- unsigned short ref = substitutedReplacement[i+1].unicode();
- int backrefStart = 0;
- int backrefLength = 0;
- int advance = 0;
-
- if (ref == '$') { // "$$" -> "$"
- substitutedReplacement = substitutedReplacement.substr(0, i + 1) + substitutedReplacement.substr(i + 2);
- continue;
- } else if (ref == '&') {
- backrefStart = ovector[0];
- backrefLength = ovector[1] - backrefStart;
- } else if (ref == '`') {
- backrefStart = 0;
- backrefLength = ovector[0];
- } else if (ref == '\'') {
- backrefStart = ovector[1];
- backrefLength = source.size() - backrefStart;
- } else if (ref >= '0' && ref <= '9') {
- // 1- and 2-digit back references are allowed
- unsigned backrefIndex = ref - '0';
- if (backrefIndex > reg->numSubpatterns())
- continue;
- if (substitutedReplacement.size() > i + 2) {
- ref = substitutedReplacement[i+2].unicode();
- if (ref >= '0' && ref <= '9') {
- backrefIndex = 10 * backrefIndex + ref - '0';
- if (backrefIndex > reg->numSubpatterns())
- backrefIndex = backrefIndex / 10; // Fall back to the 1-digit reference
- else
- advance = 1;
- }
- }
- backrefStart = ovector[2 * backrefIndex];
- backrefLength = ovector[2 * backrefIndex + 1] - backrefStart;
- } else
- continue;
-
- substitutedReplacement = substitutedReplacement.substr(0, i) + source.substr(backrefStart, backrefLength) + substitutedReplacement.substr(i + 2 + advance);
- i += backrefLength - 1; // - 1 offsets 'i + 1'
- }
-
- return substitutedReplacement;
-}
-static inline int localeCompare(const UString& a, const UString& b)
-{
-#if PLATFORM(WIN_OS)
- int retval = CompareStringW(LOCALE_USER_DEFAULT, 0,
- reinterpret_cast<LPCWSTR>(a.data()), a.size(),
- reinterpret_cast<LPCWSTR>(b.data()), b.size());
- return !retval ? retval : retval - 2;
-#elif PLATFORM(CF)
- CFStringRef sa = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(a.data()), a.size(), kCFAllocatorNull);
- CFStringRef sb = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(b.data()), b.size(), kCFAllocatorNull);
-
- int retval = CFStringCompare(sa, sb, kCFCompareLocalized);
-
- CFRelease(sa);
- CFRelease(sb);
-
- return retval;
-#else
- return compare(a, b);
-#endif
-}
-
-static JSValue *replace(ExecState *exec, StringImp* sourceVal, JSValue *pattern, JSValue *replacement)
-{
- UString source = sourceVal->value();
- JSObject *replacementFunction = 0;
- UString replacementString;
-
- if (replacement->isObject() && replacement->toObject(exec)->implementsCall())
- replacementFunction = replacement->toObject(exec);
- else
- replacementString = replacement->toString(exec);
-
- if (pattern->isObject() && static_cast<JSObject *>(pattern)->inherits(&RegExpImp::info)) {
- RegExp *reg = static_cast<RegExpImp *>(pattern)->regExp();
- bool global = reg->global();
-
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
-
- int lastIndex = 0;
- int startPosition = 0;
-
- UString::Range *sourceRanges = 0;
- int sourceRangeCount = 0;
- int sourceRangeCapacity = 0;
- UString *replacements = 0;
- int replacementCount = 0;
- int replacementCapacity = 0;
-
- // This is either a loop (if global is set) or a one-way (if not).
- do {
- int matchIndex;
- int matchLen;
- int* ovector;
- regExpObj->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
- if (matchIndex < 0)
- break;
-
- pushSourceRange(sourceRanges, sourceRangeCount, sourceRangeCapacity, UString::Range(lastIndex, matchIndex - lastIndex));
-
- UString substitutedReplacement;
- if (replacementFunction) {
- int completeMatchStart = ovector[0];
- List args;
-
- for (unsigned i = 0; i < reg->numSubpatterns() + 1; i++) {
- int matchStart = ovector[i * 2];
- int matchLen = ovector[i * 2 + 1] - matchStart;
-
- if (matchStart < 0)
- args.append(jsUndefined());
- else
- args.append(jsString(source.substr(matchStart, matchLen)));
- }
-
- args.append(jsNumber(completeMatchStart));
- args.append(sourceVal);
-
- substitutedReplacement = replacementFunction->call(exec, exec->dynamicGlobalObject(),
- args)->toString(exec);
- } else
- substitutedReplacement = substituteBackreferences(replacementString, source, ovector, reg);
-
- pushReplacement(replacements, replacementCount, replacementCapacity, substitutedReplacement);
-
- lastIndex = matchIndex + matchLen;
- startPosition = lastIndex;
-
- // special case of empty match
- if (matchLen == 0) {
- startPosition++;
- if (startPosition > source.size())
- break;
- }
- } while (global);
-
- if (lastIndex < source.size())
- pushSourceRange(sourceRanges, sourceRangeCount, sourceRangeCapacity, UString::Range(lastIndex, source.size() - lastIndex));
-
- UString result;
-
- if (sourceRanges)
- result = source.spliceSubstringsWithSeparators(sourceRanges, sourceRangeCount, replacements, replacementCount);
-
- delete [] sourceRanges;
- delete [] replacements;
-
- if (result == source)
- return sourceVal;
-
- return jsString(result);
- }
-
- // First arg is a string
- UString patternString = pattern->toString(exec);
- int matchPos = source.find(patternString);
- int matchLen = patternString.size();
- // Do the replacement
- if (matchPos == -1)
- return sourceVal;
-
- if (replacementFunction) {
- List args;
-
- args.append(jsString(source.substr(matchPos, matchLen)));
- args.append(jsNumber(matchPos));
- args.append(sourceVal);
-
- replacementString = replacementFunction->call(exec, exec->dynamicGlobalObject(),
- args)->toString(exec);
- }
-
- return jsString(source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
-}
-
-JSValue* stringProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&StringInstance::info))
- return throwError(exec, TypeError);
-
- return static_cast<StringInstance*>(thisObj)->internalValue();
-}
-
-JSValue* stringProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
-{
- if (!thisObj->inherits(&StringInstance::info))
- return throwError(exec, TypeError);
-
- return static_cast<StringInstance*>(thisObj)->internalValue();
-}
-
-JSValue* stringProtoFuncCharAt(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- UString u;
- JSValue* a0 = args[0];
- double dpos = a0->toInteger(exec);
- if (dpos >= 0 && dpos < len)
- u = s.substr(static_cast<int>(dpos), 1);
- else
- u = "";
- return jsString(u);
-}
-
-JSValue* stringProtoFuncCharCodeAt(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* result = 0;
-
- JSValue* a0 = args[0];
- double dpos = a0->toInteger(exec);
- if (dpos >= 0 && dpos < len)
- result = jsNumber(s[static_cast<int>(dpos)].unicode());
- else
- result = jsNaN();
- return result;
-}
-
-JSValue* stringProtoFuncConcat(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- List::const_iterator end = args.end();
- for (List::const_iterator it = args.begin(); it != end; ++it) {
- s += (*it)->toString(exec);
- }
- return jsString(s);
-}
-
-JSValue* stringProtoFuncIndexOf(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
- UString u2 = a0->toString(exec);
- double dpos = a1->toInteger(exec);
- if (dpos < 0)
- dpos = 0;
- else if (dpos > len)
- dpos = len;
- return jsNumber(s.find(u2, static_cast<int>(dpos)));
-}
-
-JSValue* stringProtoFuncLastIndexOf(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- UString u2 = a0->toString(exec);
- double dpos = a1->toIntegerPreserveNaN(exec);
- if (dpos < 0)
- dpos = 0;
- else if (!(dpos <= len)) // true for NaN
- dpos = len;
- return jsNumber(s.rfind(u2, static_cast<int>(dpos)));
-}
-
-JSValue* stringProtoFuncMatch(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- JSValue* a0 = args[0];
-
- UString u = s;
- RegExp* reg;
- RegExp* tmpReg = 0;
- RegExpImp* imp = 0;
- if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
- reg = static_cast<RegExpImp *>(a0)->regExp();
- } else {
- /*
- * ECMA 15.5.4.12 String.prototype.search (regexp)
- * If regexp is not an object whose [[Class]] property is "RegExp", it is
- * replaced with the result of the expression new RegExp(regexp).
- */
- reg = tmpReg = new RegExp(a0->toString(exec));
- }
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
- int pos;
- int matchLength;
- regExpObj->performMatch(reg, u, 0, pos, matchLength);
- JSValue* result;
- if (!(reg->global())) {
- // case without 'g' flag is handled like RegExp.prototype.exec
- if (pos < 0)
- result = jsNull();
- else
- result = regExpObj->arrayOfMatches(exec);
- } else {
- // return array of matches
- List list;
- int lastIndex = 0;
- while (pos >= 0) {
- list.append(jsString(u.substr(pos, matchLength)));
- lastIndex = pos;
- pos += matchLength == 0 ? 1 : matchLength;
- regExpObj->performMatch(reg, u, pos, pos, matchLength);
- }
- if (imp)
- imp->setLastIndex(lastIndex);
- if (list.isEmpty()) {
- // if there are no matches at all, it's important to return
- // Null instead of an empty array, because this matches
- // other browsers and because Null is a false value.
- result = jsNull();
- } else {
- result = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, list);
- }
- }
- delete tmpReg;
- return result;
-}
-
-JSValue* stringProtoFuncSearch(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- JSValue* a0 = args[0];
-
- UString u = s;
- RegExp* reg;
- RegExp* tmpReg = 0;
- if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
- reg = static_cast<RegExpImp *>(a0)->regExp();
- } else {
- /*
- * ECMA 15.5.4.12 String.prototype.search (regexp)
- * If regexp is not an object whose [[Class]] property is "RegExp", it is
- * replaced with the result of the expression new RegExp(regexp).
- */
- reg = tmpReg = new RegExp(a0->toString(exec));
- }
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
- int pos;
- int matchLength;
- regExpObj->performMatch(reg, u, 0, pos, matchLength);
- delete tmpReg;
- return jsNumber(pos);
-}
-
-JSValue* stringProtoFuncReplace(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- StringImp* sVal = thisObj->inherits(&StringInstance::info) ?
- static_cast<StringInstance*>(thisObj)->internalValue() :
- static_cast<StringImp*>(jsString(s));
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- return replace(exec, sVal, a0, a1);
-}
-
-JSValue* stringProtoFuncSlice(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- // The arg processing is very much like ArrayProtoFunc::Slice
- double start = a0->toInteger(exec);
- double end = a1->isUndefined() ? len : a1->toInteger(exec);
- double from = start < 0 ? len + start : start;
- double to = end < 0 ? len + end : end;
- if (to > from && to > 0 && from < len) {
- if (from < 0)
- from = 0;
- if (to > len)
- to = len;
- return jsString(s.substr(static_cast<int>(from), static_cast<int>(to - from)));
- }
-
- return jsString("");
-}
-
-JSValue* stringProtoFuncSplit(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- JSObject *constructor = exec->lexicalGlobalObject()->arrayConstructor();
- JSObject* res = static_cast<JSObject*>(constructor->construct(exec, exec->emptyList()));
- JSValue* result = res;
- UString u = s;
- int pos;
- int i = 0;
- int p0 = 0;
- uint32_t limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec);
- if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpImp::info)) {
- RegExp *reg = static_cast<RegExpImp *>(a0)->regExp();
- if (u.isEmpty() && reg->match(u, 0) >= 0) {
- // empty string matched by regexp -> empty array
- res->put(exec, exec->propertyNames().length, jsNumber(0));
- return result;
- }
- pos = 0;
- while (static_cast<uint32_t>(i) != limit && pos < u.size()) {
- OwnArrayPtr<int> ovector;
- int mpos = reg->match(u, pos, &ovector);
- if (mpos < 0)
- break;
- int mlen = ovector[1] - ovector[0];
- pos = mpos + (mlen == 0 ? 1 : mlen);
- if (mpos != p0 || mlen) {
- res->put(exec,i, jsString(u.substr(p0, mpos-p0)));
- p0 = mpos + mlen;
- i++;
- }
- for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) {
- int spos = ovector[si * 2];
- if (spos < 0)
- res->put(exec, i++, jsUndefined());
- else
- res->put(exec, i++, jsString(u.substr(spos, ovector[si * 2 + 1] - spos)));
- }
- }
- } else {
- UString u2 = a0->toString(exec);
- if (u2.isEmpty()) {
- if (u.isEmpty()) {
- // empty separator matches empty string -> empty array
- res->put(exec, exec->propertyNames().length, jsNumber(0));
- return result;
- } else {
- while (static_cast<uint32_t>(i) != limit && i < u.size()-1)
- res->put(exec, i++, jsString(u.substr(p0++, 1)));
- }
- } else {
- while (static_cast<uint32_t>(i) != limit && (pos = u.find(u2, p0)) >= 0) {
- res->put(exec, i, jsString(u.substr(p0, pos-p0)));
- p0 = pos + u2.size();
- i++;
- }
- }
- }
- // add remaining string, if any
- if (static_cast<uint32_t>(i) != limit)
- res->put(exec, i++, jsString(u.substr(p0)));
- res->put(exec, exec->propertyNames().length, jsNumber(i));
- return result;
-}
-
-JSValue* stringProtoFuncSubstr(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- double start = a0->toInteger(exec);
- double length = a1->isUndefined() ? len : a1->toInteger(exec);
- if (start >= len)
- return jsString("");
- if (length < 0)
- return jsString("");
- if (start < 0) {
- start += len;
- if (start < 0)
- start = 0;
- }
- if (length > len)
- length = len;
- return jsString(s.substr(static_cast<int>(start), static_cast<int>(length)));
-}
-
-JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- int len = s.size();
-
- JSValue* a0 = args[0];
- JSValue* a1 = args[1];
-
- double start = a0->toNumber(exec);
- double end = a1->toNumber(exec);
- if (isnan(start))
- start = 0;
- if (isnan(end))
- end = 0;
- if (start < 0)
- start = 0;
- if (end < 0)
- end = 0;
- if (start > len)
- start = len;
- if (end > len)
- end = len;
- if (a1->isUndefined())
- end = len;
- if (start > end) {
- double temp = end;
- end = start;
- start = temp;
- }
- return jsString(s.substr((int)start, (int)end-(int)start));
-}
-
-JSValue* stringProtoFuncToLowerCase(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- StringImp* sVal = thisObj->inherits(&StringInstance::info)
- ? static_cast<StringInstance*>(thisObj)->internalValue()
- : static_cast<StringImp*>(jsString(s));
- int ssize = s.size();
- if (!ssize)
- return sVal;
- Vector< ::UChar> buffer(ssize);
- bool error;
- int length = Unicode::toLower(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error) {
- buffer.resize(length);
- length = Unicode::toLower(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error)
- return sVal;
- }
- if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
- return sVal;
- return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-}
-
-JSValue* stringProtoFuncToUpperCase(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- StringImp* sVal = thisObj->inherits(&StringInstance::info)
- ? static_cast<StringInstance*>(thisObj)->internalValue()
- : static_cast<StringImp*>(jsString(s));
- int ssize = s.size();
- if (!ssize)
- return sVal;
- Vector< ::UChar> buffer(ssize);
- bool error;
- int length = Unicode::toUpper(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error) {
- buffer.resize(length);
- length = Unicode::toUpper(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error)
- return sVal;
- }
- if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
- return sVal;
- return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-}
-
-JSValue* stringProtoFuncToLocaleLowerCase(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- // FIXME: See http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt for locale-sensitive mappings that aren't implemented.
- StringImp* sVal = thisObj->inherits(&StringInstance::info)
- ? static_cast<StringInstance*>(thisObj)->internalValue()
- : static_cast<StringImp*>(jsString(s));
- int ssize = s.size();
- if (!ssize)
- return sVal;
- Vector< ::UChar> buffer(ssize);
- bool error;
- int length = Unicode::toLower(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error) {
- buffer.resize(length);
- length = Unicode::toLower(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error)
- return sVal;
- }
- if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
- return sVal;
- return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-}
-
-JSValue* stringProtoFuncToLocaleUpperCase(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
-
- StringImp* sVal = thisObj->inherits(&StringInstance::info)
- ? static_cast<StringInstance*>(thisObj)->internalValue()
- : static_cast<StringImp*>(jsString(s));
- int ssize = s.size();
- if (!ssize)
- return sVal;
- Vector< ::UChar> buffer(ssize);
- bool error;
- int length = Unicode::toUpper(buffer.data(), ssize, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error) {
- buffer.resize(length);
- length = Unicode::toUpper(buffer.data(), length, reinterpret_cast<const ::UChar*>(s.data()), ssize, &error);
- if (error)
- return sVal;
- }
- if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
- return sVal;
- return jsString(UString(reinterpret_cast<UChar*>(buffer.releaseBuffer()), length, false));
-}
-
-JSValue* stringProtoFuncLocaleCompare(ExecState* exec, JSObject* thisObj, const List& args)
-{
- if (args.size() < 1)
- return jsNumber(0);
-
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- JSValue* a0 = args[0];
- return jsNumber(localeCompare(s, a0->toString(exec)));
-}
-
-JSValue* stringProtoFuncBig(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<big>" + s + "</big>");
-}
-
-JSValue* stringProtoFuncSmall(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<small>" + s + "</small>");
-}
-
-JSValue* stringProtoFuncBlink(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<blink>" + s + "</blink>");
-}
-
-JSValue* stringProtoFuncBold(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<b>" + s + "</b>");
-}
-
-JSValue* stringProtoFuncFixed(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<tt>" + s + "</tt>");
-}
-
-JSValue* stringProtoFuncItalics(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<i>" + s + "</i>");
-}
-
-JSValue* stringProtoFuncStrike(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<strike>" + s + "</strike>");
-}
-
-JSValue* stringProtoFuncSub(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<sub>" + s + "</sub>");
-}
-
-JSValue* stringProtoFuncSup(ExecState* exec, JSObject* thisObj, const List&)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- return jsString("<sup>" + s + "</sup>");
-}
-
-JSValue* stringProtoFuncFontcolor(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- JSValue* a0 = args[0];
- return jsString("<font color=\"" + a0->toString(exec) + "\">" + s + "</font>");
-}
-
-JSValue* stringProtoFuncFontsize(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- JSValue* a0 = args[0];
- return jsString("<font size=\"" + a0->toString(exec) + "\">" + s + "</font>");
-}
-
-JSValue* stringProtoFuncAnchor(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- JSValue* a0 = args[0];
- return jsString("<a name=\"" + a0->toString(exec) + "\">" + s + "</a>");
-}
-
-JSValue* stringProtoFuncLink(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // This optimizes the common case that thisObj is a StringInstance
- UString s = thisObj->inherits(&StringInstance::info) ? static_cast<StringInstance*>(thisObj)->internalValue()->value() : thisObj->toString(exec);
- JSValue* a0 = args[0];
- return jsString("<a href=\"" + a0->toString(exec) + "\">" + s + "</a>");
-}
-
-// ------------------------------ StringObjectImp ------------------------------
-
-StringObjectImp::StringObjectImp(ExecState* exec, FunctionPrototype* funcProto, StringPrototype* stringProto)
- : InternalFunctionImp(funcProto, stringProto->classInfo()->className)
-{
- // ECMA 15.5.3.1 String.prototype
- putDirect(exec->propertyNames().prototype, stringProto, DontEnum|DontDelete|ReadOnly);
-
- putDirectFunction(new StringObjectFuncImp(exec, funcProto, exec->propertyNames().fromCharCode), DontEnum);
-
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
-}
-
-
-bool StringObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.5.2
-JSObject *StringObjectImp::construct(ExecState *exec, const List &args)
-{
- JSObject *proto = exec->lexicalGlobalObject()->stringPrototype();
- if (args.size() == 0)
- return new StringInstance(proto);
- return new StringInstance(proto, args[0]->toString(exec));
-}
-
-// ECMA 15.5.1
-JSValue *StringObjectImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
-{
- if (args.isEmpty())
- return jsString("");
- else {
- JSValue *v = args[0];
- return jsString(v->toString(exec));
- }
-}
-
-// ------------------------------ StringObjectFuncImp --------------------------
-
-// ECMA 15.5.3.2 fromCharCode()
-StringObjectFuncImp::StringObjectFuncImp(ExecState* exec, FunctionPrototype* funcProto, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
-{
- putDirect(exec->propertyNames().length, jsNumber(1), DontDelete|ReadOnly|DontEnum);
-}
-
-JSValue *StringObjectFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
-{
- UString s;
- if (args.size()) {
- UChar *buf = static_cast<UChar *>(fastMalloc(args.size() * sizeof(UChar)));
- UChar *p = buf;
- List::const_iterator end = args.end();
- for (List::const_iterator it = args.begin(); it != end; ++it) {
- unsigned short u = static_cast<unsigned short>((*it)->toUInt32(exec));
- *p++ = UChar(u);
- }
- s = UString(buf, args.size(), false);
- } else
- s = "";
-
- return jsString(s);
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef STRING_OBJECT_H_
-#define STRING_OBJECT_H_
-
-#include "function_object.h"
-#include "JSWrapperObject.h"
-#include "internal.h"
-#include "lookup.h"
-
-namespace KJS {
-
- class StringInstance : public JSWrapperObject {
- public:
- StringInstance(JSObject *proto);
- StringInstance(JSObject *proto, StringImp*);
- StringInstance(JSObject *proto, const UString&);
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-
- virtual void put(ExecState* exec, const Identifier& propertyName, JSValue*, int attr = None);
- virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
-
- StringImp* internalValue() const { return static_cast<StringImp*>(JSWrapperObject::internalValue());}
-
- private:
- bool inlineGetOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
-
- static JSValue* lengthGetter(ExecState*, JSObject *, const Identifier&, const PropertySlot&);
- static JSValue* indexGetter(ExecState*, JSObject *, const Identifier&, const PropertySlot&);
- };
-
- // WebCore uses this to make style.filter undetectable
- class StringInstanceThatMasqueradesAsUndefined : public StringInstance {
- public:
- StringInstanceThatMasqueradesAsUndefined(JSObject* proto, const UString& string)
- : StringInstance(proto, string) { }
- virtual bool masqueradeAsUndefined() const { return true; }
- virtual bool toBoolean(ExecState*) const { return false; }
- };
-
- /**
- * @internal
- *
- * The initial value of String.prototype (and thus all objects created
- * with the String constructor
- */
- class StringPrototype : public StringInstance {
- public:
- StringPrototype(ExecState *exec,
- ObjectPrototype *objProto);
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * Functions to implement all methods that are properties of the
- * String.prototype object
- */
-
- JSValue* stringProtoFuncToString(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncValueOf(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncCharAt(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncCharCodeAt(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncConcat(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncIndexOf(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncLastIndexOf(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncMatch(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncReplace(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSearch(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSlice(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSplit(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSubstr(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSubstring(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncToLowerCase(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncToUpperCase(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncToLocaleLowerCase(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncToLocaleUpperCase(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncLocaleCompare(ExecState*, JSObject*, const List&);
-
- JSValue* stringProtoFuncBig(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSmall(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncBlink(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncBold(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncFixed(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncItalics(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncStrike(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSub(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncSup(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncFontcolor(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncFontsize(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncAnchor(ExecState*, JSObject*, const List&);
- JSValue* stringProtoFuncLink(ExecState*, JSObject*, const List&);
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "String" property
- */
- class StringObjectImp : public InternalFunctionImp {
- public:
- StringObjectImp(ExecState *exec,
- FunctionPrototype *funcProto,
- StringPrototype *stringProto);
-
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *exec, const List &args);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * String object
- */
- class StringObjectFuncImp : public InternalFunctionImp {
- public:
- StringObjectFuncImp(ExecState*, FunctionPrototype*, const Identifier&);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- };
-
-} // namespace
-
-#endif
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004-2007 Apple Inc.
- * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#include "JSGlobalObject.h"
-#include "JSLock.h"
-#include "Parser.h"
-#include "SourceCode.h"
-#include "collector.h"
-#include "interpreter.h"
-#include "nodes.h"
-#include "object.h"
-#include "protect.h"
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-#include <wtf/HashTraits.h>
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(WIN_OS)
-#include <crtdbg.h>
-#include <windows.h>
-#endif
-
-#if PLATFORM(QT)
-#include <QDateTime>
-#endif
-
-using namespace KJS;
-using namespace WTF;
-
-static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
-
-class StopWatch
-{
-public:
- void start();
- void stop();
- long getElapsedMS(); // call stop() first
-
-private:
-#if PLATFORM(QT)
- uint m_startTime;
- uint m_stopTime;
-#elif PLATFORM(WIN_OS)
- DWORD m_startTime;
- DWORD m_stopTime;
-#else
- // Windows does not have timeval, disabling this class for now (bug 7399)
- timeval m_startTime;
- timeval m_stopTime;
-#endif
-};
-
-void StopWatch::start()
-{
-#if PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- m_startTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
- m_startTime = timeGetTime();
-#else
- gettimeofday(&m_startTime, 0);
-#endif
-}
-
-void StopWatch::stop()
-{
-#if PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- m_stopTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
- m_stopTime = timeGetTime();
-#else
- gettimeofday(&m_stopTime, 0);
-#endif
-}
-
-long StopWatch::getElapsedMS()
-{
-#if PLATFORM(WIN_OS) || PLATFORM(QT)
- return m_stopTime - m_startTime;
-#else
- timeval elapsedTime;
- timersub(&m_stopTime, &m_startTime, &elapsedTime);
-
- return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
-#endif
-}
-
-class GlobalImp : public JSGlobalObject {
-public:
- virtual UString className() const { return "global"; }
-};
-COMPILE_ASSERT(!IsInteger<GlobalImp>::value, WTF_IsInteger_GlobalImp_false);
-
-class TestFunctionImp : public JSObject {
-public:
- enum TestFunctionType { Print, Debug, Quit, GC, Version, Run, Load };
-
- TestFunctionImp(TestFunctionType i, int length);
- virtual bool implementsCall() const { return true; }
- virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List &args);
-
-private:
- TestFunctionType m_type;
-};
-
-TestFunctionImp::TestFunctionImp(TestFunctionType i, int length)
- : JSObject()
- , m_type(i)
-{
- putDirect(Identifier("length"), length, DontDelete | ReadOnly | DontEnum);
-}
-
-JSValue* TestFunctionImp::callAsFunction(ExecState* exec, JSObject*, const List &args)
-{
- switch (m_type) {
- case Print:
- printf("%s\n", args[0]->toString(exec).UTF8String().c_str());
- return jsUndefined();
- case Debug:
- fprintf(stderr, "--> %s\n", args[0]->toString(exec).UTF8String().c_str());
- return jsUndefined();
- case GC:
- {
- JSLock lock;
- Collector::collect();
- return jsUndefined();
- }
- case Version:
- // We need this function for compatibility with the Mozilla JS tests but for now
- // we don't actually do any version-specific handling
- return jsUndefined();
- case Run:
- {
- StopWatch stopWatch;
- UString fileName = args[0]->toString(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return throwError(exec, GeneralError, "Could not open file.");
-
- stopWatch.start();
-
- Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), makeSource(script.data(), fileName));
- stopWatch.stop();
-
- return jsNumber(stopWatch.getElapsedMS());
- }
- case Load:
- {
- UString fileName = args[0]->toString(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return throwError(exec, GeneralError, "Could not open file.");
-
- Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), makeSource(script.data(), fileName));
-
- return jsUndefined();
- }
- case Quit:
- exit(0);
- default:
- abort();
- }
- return 0;
-}
-
-// Use SEH for Release builds only to get rid of the crash report dialog
-// (luckily the same tests fail in Release and Debug builds so far). Need to
-// be in a separate main function because the kjsmain function requires object
-// unwinding.
-
-#if PLATFORM(WIN_OS) && !defined(_DEBUG)
-#define TRY __try {
-#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
-#else
-#define TRY
-#define EXCEPT(x)
-#endif
-
-int kjsmain(int argc, char** argv);
-
-int main(int argc, char** argv)
-{
-#if defined(_DEBUG) && PLATFORM(WIN_OS)
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
-#endif
-
- int res = 0;
- TRY
- res = kjsmain(argc, argv);
- EXCEPT(res = 3)
- return res;
-}
-
-static GlobalImp* createGlobalObject()
-{
- GlobalImp* global = new GlobalImp;
-
- // add debug() function
- global->put(global->globalExec(), "debug", new TestFunctionImp(TestFunctionImp::Debug, 1));
- // add "print" for compatibility with the mozilla js shell
- global->put(global->globalExec(), "print", new TestFunctionImp(TestFunctionImp::Print, 1));
- // add "quit" for compatibility with the mozilla js shell
- global->put(global->globalExec(), "quit", new TestFunctionImp(TestFunctionImp::Quit, 0));
- // add "gc" for compatibility with the mozilla js shell
- global->put(global->globalExec(), "gc", new TestFunctionImp(TestFunctionImp::GC, 0));
- // add "version" for compatibility with the mozilla js shell
- global->put(global->globalExec(), "version", new TestFunctionImp(TestFunctionImp::Version, 1));
- global->put(global->globalExec(), "run", new TestFunctionImp(TestFunctionImp::Run, 1));
- global->put(global->globalExec(), "load", new TestFunctionImp(TestFunctionImp::Load, 1));
-
- Interpreter::setShouldPrintExceptions(true);
- return global;
-}
-
-static bool prettyPrintScript(const UString& fileName, const Vector<char>& script)
-{
- int errLine = 0;
- UString errMsg;
-
- RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(makeSource(script.data(), fileName), &errLine, &errMsg);
- if (!programNode) {
- fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str());
- return false;
- }
-
- printf("%s\n", programNode->toString().UTF8String().c_str());
- return true;
-}
-
-static bool runWithScripts(const Vector<UString>& fileNames, bool prettyPrint)
-{
- GlobalImp* globalObject = createGlobalObject();
- Vector<char> script;
-
- bool success = true;
-
- for (size_t i = 0; i < fileNames.size(); i++) {
- UString fileName = fileNames[i];
-
- if (!fillBufferWithContentsOfFile(fileName, script))
- return false; // fail early so we can catch missing files
-
- if (prettyPrint)
- prettyPrintScript(fileName, script);
- else {
- Completion completion = Interpreter::evaluate(globalObject->globalExec(), makeSource(script.data(), fileName));
- success = success && completion.complType() != Throw;
- }
- }
- return success;
-}
-
-static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, bool& prettyPrint)
-{
- if (argc < 2) {
- fprintf(stderr, "Usage: testkjs file1 [file2...]\n");
- exit(-1);
- }
-
- for (int i = 1; i < argc; i++) {
- const char* fileName = argv[i];
- if (strcmp(fileName, "-f") == 0) // mozilla test driver script uses "-f" prefix for files
- continue;
- if (strcmp(fileName, "-p") == 0) {
- prettyPrint = true;
- continue;
- }
- fileNames.append(fileName);
- }
-}
-
-int kjsmain(int argc, char** argv)
-{
- JSLock lock;
-
- bool prettyPrint = false;
- Vector<UString> fileNames;
- parseArguments(argc, argv, fileNames, prettyPrint);
-
- bool success = runWithScripts(fileNames, prettyPrint);
-
-#ifndef NDEBUG
- Collector::collect();
-#endif
-
- return success ? 0 : 3;
-}
-
-static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
-{
- FILE* f = fopen(fileName.UTF8String().c_str(), "r");
- if (!f) {
- fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str());
- return false;
- }
-
- size_t buffer_size = 0;
- size_t buffer_capacity = 1024;
-
- buffer.resize(buffer_capacity);
-
- while (!feof(f) && !ferror(f)) {
- buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);
- if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
- buffer_capacity *= 2;
- buffer.resize(buffer_capacity);
- }
- }
- fclose(f);
- buffer[buffer_size] = '\0';
-
- return true;
-}
+++ /dev/null
-TEMPLATE = app
-TARGET = testkjs
-DESTDIR = ..
-SOURCES = testkjs.cpp
-QT -= gui
-DEFINES -= KJS_IDENTIFIER_HIDE_GLOBALS
-INCLUDEPATH += $$PWD/.. $$PWD $$PWD/../bindings $$PWD/../bindings/c $$PWD/../wtf
-CONFIG -= app_bundle
-qt-port:DEFINES += BUILDING_QT__
-#qt-port:LIBS += -L$$OUTPUT_DIR/lib -lQtWebKit
-gtk-port {
- QMAKE_CXXFLAGS += $$system(icu-config --cppflags)
- LIBS += $$system(icu-config --ldflags)
-}
-QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
-
-isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/../..
-include($$OUTPUT_DIR/config.pri)
-OBJECTS_DIR = tmp
-OBJECTS_DIR_WTR = $$OBJECTS_DIR/
-win32-*: OBJECTS_DIR_WTR ~= s|/|\|
-include($$PWD/../JavaScriptCore.pri)
-
-# Hack! Fix this.
-SOURCES -= API/JSBase.cpp \
- API/JSCallbackConstructor.cpp \
- API/JSCallbackFunction.cpp \
- API/JSCallbackObject.cpp \
- API/JSClassRef.cpp \
- API/JSContextRef.cpp \
- API/JSObjectRef.cpp \
- API/JSStringRef.cpp \
- API/JSValueRef.cpp
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "completion.h"
-#include "list.h"
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "ustring.h"
-
-#include "JSLock.h"
-#include "collector.h"
-#include "dtoa.h"
-#include "function.h"
-#include "identifier.h"
-#include "operations.h"
-#include <ctype.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <wtf/Assertions.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/MathExtras.h>
-#include <wtf/Vector.h>
-#include <wtf/unicode/UTF8.h>
-
-#if HAVE(STRING_H)
-#include <string.h>
-#endif
-#if HAVE(STRINGS_H)
-#include <strings.h>
-#endif
-
-using namespace WTF;
-using namespace WTF::Unicode;
-using namespace std;
-
-namespace KJS {
-
-extern const double NaN;
-extern const double Inf;
-
-static inline const size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }
-static inline const size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }
-
-static inline UChar* allocChars(size_t length)
-{
- ASSERT(length);
- if (length > maxUChars())
- return 0;
- return static_cast<UChar*>(fastMalloc(sizeof(UChar) * length));
-}
-
-static inline UChar* reallocChars(UChar* buffer, size_t length)
-{
- ASSERT(length);
- if (length > maxUChars())
- return 0;
- return static_cast<UChar*>(fastRealloc(buffer, sizeof(UChar) * length));
-}
-
-COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
-
-CString::CString(const char *c)
-{
- length = strlen(c);
- data = new char[length+1];
- memcpy(data, c, length + 1);
-}
-
-CString::CString(const char *c, size_t len)
-{
- length = len;
- data = new char[len+1];
- memcpy(data, c, len);
- data[len] = 0;
-}
-
-CString::CString(const CString &b)
-{
- length = b.length;
- if (b.data) {
- data = new char[length+1];
- memcpy(data, b.data, length + 1);
- }
- else
- data = 0;
-}
-
-CString::~CString()
-{
- delete [] data;
-}
-
-CString &CString::append(const CString &t)
-{
- char *n;
- n = new char[length+t.length+1];
- if (length)
- memcpy(n, data, length);
- if (t.length)
- memcpy(n+length, t.data, t.length);
- length += t.length;
- n[length] = 0;
-
- delete [] data;
- data = n;
-
- return *this;
-}
-
-CString &CString::operator=(const char *c)
-{
- if (data)
- delete [] data;
- length = strlen(c);
- data = new char[length+1];
- memcpy(data, c, length + 1);
-
- return *this;
-}
-
-CString &CString::operator=(const CString &str)
-{
- if (this == &str)
- return *this;
-
- if (data)
- delete [] data;
- length = str.length;
- if (str.data) {
- data = new char[length + 1];
- memcpy(data, str.data, length + 1);
- }
- else
- data = 0;
-
- return *this;
-}
-
-bool operator==(const CString& c1, const CString& c2)
-{
- size_t len = c1.size();
- return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
-}
-
-// Hack here to avoid a global with a constructor; point to an unsigned short instead of a UChar.
-static unsigned short almostUChar;
-UString::Rep UString::Rep::null = { 0, 0, 1, 0, 0, &UString::Rep::null, 0, 0, 0, 0, 0, 0 };
-UString::Rep UString::Rep::empty = { 0, 0, 1, 0, 0, &UString::Rep::empty, 0, reinterpret_cast<UChar*>(&almostUChar), 0, 0, 0, 0 };
-const int normalStatBufferSize = 4096;
-static char *statBuffer = 0; // FIXME: This buffer is never deallocated.
-static int statBufferSize = 0;
-
-PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar *d, int l)
-{
- int sizeInBytes = l * sizeof(UChar);
- UChar *copyD = static_cast<UChar *>(fastMalloc(sizeInBytes));
- memcpy(copyD, d, sizeInBytes);
-
- return create(copyD, l);
-}
-
-PassRefPtr<UString::Rep> UString::Rep::create(UChar *d, int l)
-{
- Rep* r = new Rep;
- r->offset = 0;
- r->len = l;
- r->rc = 1;
- r->_hash = 0;
- r->isIdentifier = 0;
- r->baseString = r;
- r->reportedCost = 0;
- r->buf = d;
- r->usedCapacity = l;
- r->capacity = l;
- r->usedPreCapacity = 0;
- r->preCapacity = 0;
-
- // steal the single reference this Rep was created with
- return adoptRef(r);
-}
-
-PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
-{
- ASSERT(base);
-
- int baseOffset = base->offset;
-
- base = base->baseString;
-
- ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
- ASSERT(offset + baseOffset + length <= base->usedCapacity);
-
- Rep *r = new Rep;
- r->offset = baseOffset + offset;
- r->len = length;
- r->rc = 1;
- r->_hash = 0;
- r->isIdentifier = 0;
- r->baseString = base.releaseRef();
- r->reportedCost = 0;
- r->buf = 0;
- r->usedCapacity = 0;
- r->capacity = 0;
- r->usedPreCapacity = 0;
- r->preCapacity = 0;
-
- // steal the single reference this Rep was created with
- return adoptRef(r);
-}
-
-void UString::Rep::destroy()
-{
- if (isIdentifier)
- Identifier::remove(this);
- if (baseString != this) {
- baseString->deref();
- } else {
- fastFree(buf);
- }
- delete this;
-}
-
-// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
-// or anything like that.
-const unsigned PHI = 0x9e3779b9U;
-
-// Paul Hsieh's SuperFastHash
-// http://www.azillionmonkeys.com/qed/hash.html
-unsigned UString::Rep::computeHash(const UChar *s, int len)
-{
- unsigned l = len;
- uint32_t hash = PHI;
- uint32_t tmp;
-
- int rem = l & 1;
- l >>= 1;
-
- // Main loop
- for (; l > 0; l--) {
- hash += s[0].uc;
- tmp = (s[1].uc << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case
- if (rem) {
- hash += s[0].uc;
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- if (hash == 0)
- hash = 0x80000000;
-
- return hash;
-}
-
-// Paul Hsieh's SuperFastHash
-// http://www.azillionmonkeys.com/qed/hash.html
-unsigned UString::Rep::computeHash(const char *s)
-{
- // This hash is designed to work on 16-bit chunks at a time. But since the normal case
- // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
- // were 16-bit chunks, which should give matching results
-
- uint32_t hash = PHI;
- uint32_t tmp;
- size_t l = strlen(s);
-
- size_t rem = l & 1;
- l >>= 1;
-
- // Main loop
- for (; l > 0; l--) {
- hash += (unsigned char)s[0];
- tmp = ((unsigned char)s[1] << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case
- if (rem) {
- hash += (unsigned char)s[0];
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- if (hash == 0)
- hash = 0x80000000;
-
- return hash;
-}
-
-// put these early so they can be inlined
-inline size_t UString::expandedSize(size_t size, size_t otherSize) const
-{
- // Do the size calculation in two parts, returning overflowIndicator if
- // we overflow the maximum value that we can handle.
-
- if (size > maxUChars())
- return overflowIndicator();
-
- size_t expandedSize = ((size + 10) / 10 * 11) + 1;
- if (maxUChars() - expandedSize < otherSize)
- return overflowIndicator();
-
- return expandedSize + otherSize;
-}
-
-inline int UString::usedCapacity() const
-{
- return m_rep->baseString->usedCapacity;
-}
-
-inline int UString::usedPreCapacity() const
-{
- return m_rep->baseString->usedPreCapacity;
-}
-
-void UString::expandCapacity(int requiredLength)
-{
- Rep* r = m_rep->baseString;
-
- if (requiredLength > r->capacity) {
- size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
- UChar* oldBuf = r->buf;
- r->buf = reallocChars(r->buf, newCapacity);
- if (!r->buf) {
- r->buf = oldBuf;
- m_rep = &Rep::null;
- return;
- }
- r->capacity = newCapacity - r->preCapacity;
- }
- if (requiredLength > r->usedCapacity) {
- r->usedCapacity = requiredLength;
- }
-}
-
-void UString::expandPreCapacity(int requiredPreCap)
-{
- Rep* r = m_rep->baseString;
-
- if (requiredPreCap > r->preCapacity) {
- size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
- int delta = newCapacity - r->capacity - r->preCapacity;
-
- UChar* newBuf = allocChars(newCapacity);
- if (!newBuf) {
- m_rep = &Rep::null;
- return;
- }
- memcpy(newBuf + delta, r->buf, (r->capacity + r->preCapacity) * sizeof(UChar));
- fastFree(r->buf);
- r->buf = newBuf;
-
- r->preCapacity = newCapacity - r->capacity;
- }
- if (requiredPreCap > r->usedPreCapacity) {
- r->usedPreCapacity = requiredPreCap;
- }
-}
-
-UString::UString(const char *c)
-{
- if (!c) {
- m_rep = &Rep::null;
- return;
- }
-
- if (!c[0]) {
- m_rep = &Rep::empty;
- return;
- }
-
- size_t length = strlen(c);
- UChar *d = allocChars(length);
- if (!d)
- m_rep = &Rep::null;
- else {
- for (size_t i = 0; i < length; i++)
- d[i].uc = c[i];
- m_rep = Rep::create(d, static_cast<int>(length));
- }
-}
-
-UString::UString(const UChar *c, int length)
-{
- if (length == 0)
- m_rep = &Rep::empty;
- else
- m_rep = Rep::createCopying(c, length);
-}
-
-UString::UString(UChar *c, int length, bool copy)
-{
- if (length == 0)
- m_rep = &Rep::empty;
- else if (copy)
- m_rep = Rep::createCopying(c, length);
- else
- m_rep = Rep::create(c, length);
-}
-
-UString::UString(const Vector<UChar>& buffer)
-{
- if (!buffer.size())
- m_rep = &Rep::empty;
- else
- m_rep = Rep::createCopying(buffer.data(), buffer.size());
-}
-
-
-UString::UString(const UString &a, const UString &b)
-{
- int aSize = a.size();
- int aOffset = a.m_rep->offset;
- int bSize = b.size();
- int bOffset = b.m_rep->offset;
- int length = aSize + bSize;
-
- // possible cases:
-
- if (aSize == 0) {
- // a is empty
- m_rep = b.m_rep;
- } else if (bSize == 0) {
- // b is empty
- m_rep = a.m_rep;
- } else if (aOffset + aSize == a.usedCapacity() && aSize >= minShareSize && 4 * aSize >= bSize &&
- (-bOffset != b.usedPreCapacity() || aSize >= bSize)) {
- // - a reaches the end of its buffer so it qualifies for shared append
- // - also, it's at least a quarter the length of b - appending to a much shorter
- // string does more harm than good
- // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
- UString x(a);
- x.expandCapacity(aOffset + length);
- if (a.data() && x.data()) {
- memcpy(const_cast<UChar *>(a.data() + aSize), b.data(), bSize * sizeof(UChar));
- m_rep = Rep::create(a.m_rep, 0, length);
- } else
- m_rep = &Rep::null;
- } else if (-bOffset == b.usedPreCapacity() && bSize >= minShareSize && 4 * bSize >= aSize) {
- // - b reaches the beginning of its buffer so it qualifies for shared prepend
- // - also, it's at least a quarter the length of a - prepending to a much shorter
- // string does more harm than good
- UString y(b);
- y.expandPreCapacity(-bOffset + aSize);
- if (b.data() && y.data()) {
- memcpy(const_cast<UChar *>(b.data() - aSize), a.data(), aSize * sizeof(UChar));
- m_rep = Rep::create(b.m_rep, -aSize, length);
- } else
- m_rep = &Rep::null;
- } else {
- // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- m_rep = &Rep::null;
- else {
- memcpy(d, a.data(), aSize * sizeof(UChar));
- memcpy(d + aSize, b.data(), bSize * sizeof(UChar));
- m_rep = Rep::create(d, length);
- m_rep->capacity = newCapacity;
- }
- }
-}
-
-const UString& UString::null()
-{
- static UString* n = new UString;
- return *n;
-}
-
-UString UString::from(int i)
-{
- UChar buf[1 + sizeof(i) * 3];
- UChar *end = buf + sizeof(buf) / sizeof(UChar);
- UChar *p = end;
-
- if (i == 0) {
- *--p = '0';
- } else if (i == INT_MIN) {
- char minBuf[1 + sizeof(i) * 3];
- snprintf(minBuf, 1 + sizeof(i) * 3, "%d", INT_MIN);
- return UString(minBuf);
- } else {
- bool negative = false;
- if (i < 0) {
- negative = true;
- i = -i;
- }
- while (i) {
- *--p = (unsigned short)((i % 10) + '0');
- i /= 10;
- }
- if (negative) {
- *--p = '-';
- }
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(unsigned int u)
-{
- UChar buf[sizeof(u) * 3];
- UChar *end = buf + sizeof(buf) / sizeof(UChar);
- UChar *p = end;
-
- if (u == 0) {
- *--p = '0';
- } else {
- while (u) {
- *--p = (unsigned short)((u % 10) + '0');
- u /= 10;
- }
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(long l)
-{
- UChar buf[1 + sizeof(l) * 3];
- UChar *end = buf + sizeof(buf) / sizeof(UChar);
- UChar *p = end;
-
- if (l == 0) {
- *--p = '0';
- } else if (l == LONG_MIN) {
- char minBuf[1 + sizeof(l) * 3];
- snprintf(minBuf, 1 + sizeof(l) * 3, "%ld", LONG_MIN);
- return UString(minBuf);
- } else {
- bool negative = false;
- if (l < 0) {
- negative = true;
- l = -l;
- }
- while (l) {
- *--p = (unsigned short)((l % 10) + '0');
- l /= 10;
- }
- if (negative) {
- *--p = '-';
- }
- }
-
- return UString(p, static_cast<int>(end - p));
-}
-
-UString UString::from(double d)
-{
- // avoid ever printing -NaN, in JS conceptually there is only one NaN value
- if (isnan(d))
- return "NaN";
-
- int buflength= 80;
- char buf[buflength];
- int decimalPoint;
- int sign;
-
- char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL);
- int length = static_cast<int>(strlen(result));
-
- int i = 0;
- if (sign) {
- buf[i++] = '-';
- }
-
- if (decimalPoint <= 0 && decimalPoint > -6) {
- buf[i++] = '0';
- buf[i++] = '.';
- for (int j = decimalPoint; j < 0; j++) {
- buf[i++] = '0';
- }
- strlcpy(buf + i, result, buflength - i);
- } else if (decimalPoint <= 21 && decimalPoint > 0) {
- if (length <= decimalPoint) {
- strlcpy(buf + i, result, buflength - i);
- i += length;
- for (int j = 0; j < decimalPoint - length; j++) {
- buf[i++] = '0';
- }
- buf[i] = '\0';
- } else {
- int len = (decimalPoint <= buflength - i ? decimalPoint : buflength - i);
- strncpy(buf + i, result, len);
- i += len;
- buf[i++] = '.';
- strlcpy(buf + i, result + decimalPoint, buflength - i);
- }
- } else if (result[0] < '0' || result[0] > '9') {
- strlcpy(buf + i, result, buflength - i);
- } else {
- buf[i++] = result[0];
- if (length > 1) {
- buf[i++] = '.';
- strlcpy(buf + i, result + 1, buflength - i);
- i += length - 1;
- }
-
- buf[i++] = 'e';
- buf[i++] = (decimalPoint >= 0) ? '+' : '-';
- // decimalPoint can't be more than 3 digits decimal given the
- // nature of float representation
- int exponential = decimalPoint - 1;
- if (exponential < 0)
- exponential = -exponential;
- if (exponential >= 100)
- buf[i++] = static_cast<char>('0' + exponential / 100);
- if (exponential >= 10)
- buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
- buf[i++] = static_cast<char>('0' + exponential % 10);
- buf[i++] = '\0';
- assert(i <= buflength);
- }
-
- kjs_freedtoa(result);
-
- return UString(buf);
-}
-
-UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
-{
- if (rangeCount == 1 && separatorCount == 0) {
- int thisSize = size();
- int position = substringRanges[0].position;
- int length = substringRanges[0].length;
- if (position <= 0 && length >= thisSize)
- return *this;
- return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
- }
-
- int totalLength = 0;
- for (int i = 0; i < rangeCount; i++)
- totalLength += substringRanges[i].length;
- for (int i = 0; i < separatorCount; i++)
- totalLength += separators[i].size();
-
- if (totalLength == 0)
- return "";
-
- UChar* buffer = allocChars(totalLength);
- if (!buffer)
- return null();
-
- int maxCount = max(rangeCount, separatorCount);
- int bufferPos = 0;
- for (int i = 0; i < maxCount; i++) {
- if (i < rangeCount) {
- memcpy(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length * sizeof(UChar));
- bufferPos += substringRanges[i].length;
- }
- if (i < separatorCount) {
- memcpy(buffer + bufferPos, separators[i].data(), separators[i].size() * sizeof(UChar));
- bufferPos += separators[i].size();
- }
- }
-
- return UString::Rep::create(buffer, totalLength);
-}
-
-UString &UString::append(const UString &t)
-{
- int thisSize = size();
- int thisOffset = m_rep->offset;
- int tSize = t.size();
- int length = thisSize + tSize;
-
- // possible cases:
- if (thisSize == 0) {
- // this is empty
- *this = t;
- } else if (tSize == 0) {
- // t is empty
- } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(thisOffset + length);
- if (data()) {
- memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
- m_rep->len = length;
- m_rep->_hash = 0;
- }
- } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
- // this reaches the end of the buffer - extend it if it's long enough to append to
- expandCapacity(thisOffset + length);
- if (data()) {
- memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
- m_rep = Rep::create(m_rep, 0, length);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- m_rep = &Rep::null;
- else {
- memcpy(d, data(), thisSize * sizeof(UChar));
- memcpy(const_cast<UChar*>(d + thisSize), t.data(), tSize * sizeof(UChar));
- m_rep = Rep::create(d, length);
- m_rep->capacity = newCapacity;
- }
- }
-
- return *this;
-}
-
-UString &UString::append(const char *t)
-{
- int thisSize = size();
- int thisOffset = m_rep->offset;
- int tSize = static_cast<int>(strlen(t));
- int length = thisSize + tSize;
-
- // possible cases:
- if (thisSize == 0) {
- // this is empty
- *this = t;
- } else if (tSize == 0) {
- // t is empty, we'll just return *this below.
- } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(thisOffset + length);
- UChar *d = const_cast<UChar *>(data());
- if (d) {
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = t[i];
- m_rep->len = length;
- m_rep->_hash = 0;
- }
- } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
- // this string reaches the end of the buffer - extend it
- expandCapacity(thisOffset + length);
- UChar *d = const_cast<UChar *>(data());
- if (d) {
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = t[i];
- m_rep = Rep::create(m_rep, 0, length);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- m_rep = &Rep::null;
- else {
- memcpy(d, data(), thisSize * sizeof(UChar));
- for (int i = 0; i < tSize; ++i)
- d[thisSize + i] = t[i];
- m_rep = Rep::create(d, length);
- m_rep->capacity = newCapacity;
- }
- }
-
- return *this;
-}
-
-UString &UString::append(unsigned short c)
-{
- int thisOffset = m_rep->offset;
- int length = size();
-
- // possible cases:
- if (length == 0) {
- // this is empty - must make a new m_rep because we don't want to pollute the shared empty one
- size_t newCapacity = expandedSize(1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- m_rep = &Rep::null;
- else {
- d[0] = c;
- m_rep = Rep::create(d, 1);
- m_rep->capacity = newCapacity;
- }
- } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
- // this is direct and has refcount of 1 (so we can just alter it directly)
- expandCapacity(thisOffset + length + 1);
- UChar *d = const_cast<UChar *>(data());
- if (d) {
- d[length] = c;
- m_rep->len = length + 1;
- m_rep->_hash = 0;
- }
- } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
- // this reaches the end of the string - extend it and share
- expandCapacity(thisOffset + length + 1);
- UChar *d = const_cast<UChar *>(data());
- if (d) {
- d[length] = c;
- m_rep = Rep::create(m_rep, 0, length + 1);
- }
- } else {
- // this is shared with someone using more capacity, gotta make a whole new string
- size_t newCapacity = expandedSize(length + 1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
- m_rep = &Rep::null;
- else {
- memcpy(d, data(), length * sizeof(UChar));
- d[length] = c;
- m_rep = Rep::create(d, length + 1);
- m_rep->capacity = newCapacity;
- }
- }
-
- return *this;
-}
-
-CString UString::cstring() const
-{
- return ascii();
-}
-
-char *UString::ascii() const
-{
- // Never make the buffer smaller than normalStatBufferSize.
- // Thus we almost never need to reallocate.
- int length = size();
- int neededSize = length + 1;
- if (neededSize < normalStatBufferSize) {
- neededSize = normalStatBufferSize;
- }
- if (neededSize != statBufferSize) {
- delete [] statBuffer;
- statBuffer = new char [neededSize];
- statBufferSize = neededSize;
- }
-
- const UChar *p = data();
- char *q = statBuffer;
- const UChar *limit = p + length;
- while (p != limit) {
- *q = static_cast<char>(p->uc);
- ++p;
- ++q;
- }
- *q = '\0';
-
- return statBuffer;
-}
-
-UString &UString::operator=(const char *c)
-{
- if (!c) {
- m_rep = &Rep::null;
- return *this;
- }
-
- if (!c[0]) {
- m_rep = &Rep::empty;
- return *this;
- }
-
- int l = static_cast<int>(strlen(c));
- UChar *d;
- if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
- d = m_rep->buf;
- m_rep->_hash = 0;
- m_rep->len = l;
- } else {
- d = allocChars(l);
- if (!d) {
- m_rep = &Rep::null;
- return *this;
- }
- m_rep = Rep::create(d, l);
- }
- for (int i = 0; i < l; i++)
- d[i].uc = c[i];
-
- return *this;
-}
-
-bool UString::is8Bit() const
-{
- const UChar *u = data();
- const UChar *limit = u + size();
- while (u < limit) {
- if (u->uc > 0xFF)
- return false;
- ++u;
- }
-
- return true;
-}
-
-const UChar UString::operator[](int pos) const
-{
- if (pos >= size())
- return '\0';
- return data()[pos];
-}
-
-double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
-{
- double d;
-
- // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
- // after the number, so is8Bit is too strict a check.
- if (!is8Bit())
- return NaN;
-
- const char *c = ascii();
-
- // skip leading white space
- while (isASCIISpace(*c))
- c++;
-
- // empty string ?
- if (*c == '\0')
- return tolerateEmptyString ? 0.0 : NaN;
-
- // hex number ?
- if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
- const char* firstDigitPosition = c + 2;
- c++;
- d = 0.0;
- while (*(++c)) {
- if (*c >= '0' && *c <= '9')
- d = d * 16.0 + *c - '0';
- else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
- d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
- else
- break;
- }
-
- if (d >= mantissaOverflowLowerBound)
- d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
- } else {
- // regular number ?
- char *end;
- d = kjs_strtod(c, &end);
- if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
- c = end;
- } else {
- double sign = 1.0;
-
- if (*c == '+')
- c++;
- else if (*c == '-') {
- sign = -1.0;
- c++;
- }
-
- // We used strtod() to do the conversion. However, strtod() handles
- // infinite values slightly differently than JavaScript in that it
- // converts the string "inf" with any capitalization to infinity,
- // whereas the ECMA spec requires that it be converted to NaN.
-
- if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
- d = sign * Inf;
- c += 8;
- } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
- c = end;
- else
- return NaN;
- }
- }
-
- // allow trailing white space
- while (isASCIISpace(*c))
- c++;
- // don't allow anything after - unless tolerant=true
- if (!tolerateTrailingJunk && *c != '\0')
- d = NaN;
-
- return d;
-}
-
-double UString::toDouble(bool tolerateTrailingJunk) const
-{
- return toDouble(tolerateTrailingJunk, true);
-}
-
-double UString::toDouble() const
-{
- return toDouble(false, true);
-}
-
-uint32_t UString::toUInt32(bool *ok) const
-{
- double d = toDouble();
- bool b = true;
-
- if (d != static_cast<uint32_t>(d)) {
- b = false;
- d = 0;
- }
-
- if (ok)
- *ok = b;
-
- return static_cast<uint32_t>(d);
-}
-
-uint32_t UString::toUInt32(bool *ok, bool tolerateEmptyString) const
-{
- double d = toDouble(false, tolerateEmptyString);
- bool b = true;
-
- if (d != static_cast<uint32_t>(d)) {
- b = false;
- d = 0;
- }
-
- if (ok)
- *ok = b;
-
- return static_cast<uint32_t>(d);
-}
-
-uint32_t UString::toStrictUInt32(bool *ok) const
-{
- if (ok)
- *ok = false;
-
- // Empty string is not OK.
- int len = m_rep->len;
- if (len == 0)
- return 0;
- const UChar *p = m_rep->data();
- unsigned short c = p->unicode();
-
- // If the first digit is 0, only 0 itself is OK.
- if (c == '0') {
- if (len == 1 && ok)
- *ok = true;
- return 0;
- }
-
- // Convert to UInt32, checking for overflow.
- uint32_t i = 0;
- while (1) {
- // Process character, turning it into a digit.
- if (c < '0' || c > '9')
- return 0;
- const unsigned d = c - '0';
-
- // Multiply by 10, checking for overflow out of 32 bits.
- if (i > 0xFFFFFFFFU / 10)
- return 0;
- i *= 10;
-
- // Add in the digit, checking for overflow out of 32 bits.
- const unsigned max = 0xFFFFFFFFU - d;
- if (i > max)
- return 0;
- i += d;
-
- // Handle end of string.
- if (--len == 0) {
- if (ok)
- *ok = true;
- return i;
- }
-
- // Get next character.
- c = (++p)->unicode();
- }
-}
-
-int UString::find(const UString &f, int pos) const
-{
- int sz = size();
- int fsz = f.size();
- if (sz < fsz)
- return -1;
- if (pos < 0)
- pos = 0;
- if (fsz == 0)
- return pos;
- const UChar *end = data() + sz - fsz;
- int fsizeminusone = (fsz - 1) * sizeof(UChar);
- const UChar *fdata = f.data();
- unsigned short fchar = fdata->uc;
- ++fdata;
- for (const UChar *c = data() + pos; c <= end; c++)
- if (c->uc == fchar && !memcmp(c + 1, fdata, fsizeminusone))
- return static_cast<int>(c - data());
-
- return -1;
-}
-
-int UString::find(UChar ch, int pos) const
-{
- if (pos < 0)
- pos = 0;
- const UChar *end = data() + size();
- for (const UChar *c = data() + pos; c < end; c++)
- if (*c == ch)
- return static_cast<int>(c - data());
-
- return -1;
-}
-
-int UString::rfind(const UString &f, int pos) const
-{
- int sz = size();
- int fsz = f.size();
- if (sz < fsz)
- return -1;
- if (pos < 0)
- pos = 0;
- if (pos > sz - fsz)
- pos = sz - fsz;
- if (fsz == 0)
- return pos;
- int fsizeminusone = (fsz - 1) * sizeof(UChar);
- const UChar *fdata = f.data();
- for (const UChar *c = data() + pos; c >= data(); c--) {
- if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
- return static_cast<int>(c - data());
- }
-
- return -1;
-}
-
-int UString::rfind(UChar ch, int pos) const
-{
- if (isEmpty())
- return -1;
- if (pos + 1 >= size())
- pos = size() - 1;
- for (const UChar *c = data() + pos; c >= data(); c--) {
- if (*c == ch)
- return static_cast<int>(c-data());
- }
-
- return -1;
-}
-
-UString UString::substr(int pos, int len) const
-{
- int s = size();
-
- if (pos < 0)
- pos = 0;
- else if (pos >= s)
- pos = s;
- if (len < 0)
- len = s;
- if (pos + len >= s)
- len = s - pos;
-
- if (pos == 0 && len == s)
- return *this;
-
- return UString(Rep::create(m_rep, pos, len));
-}
-
-bool operator==(const UString& s1, const UString& s2)
-{
- if (s1.m_rep->len != s2.m_rep->len)
- return false;
-
- return (memcmp(s1.m_rep->data(), s2.m_rep->data(),
- s1.m_rep->len * sizeof(UChar)) == 0);
-}
-
-bool operator==(const UString& s1, const char *s2)
-{
- if (s2 == 0) {
- return s1.isEmpty();
- }
-
- const UChar *u = s1.data();
- const UChar *uend = u + s1.size();
- while (u != uend && *s2) {
- if (u->uc != (unsigned char)*s2)
- return false;
- s2++;
- u++;
- }
-
- return u == uend && *s2 == 0;
-}
-
-bool operator<(const UString& s1, const UString& s2)
-{
- const int l1 = s1.size();
- const int l2 = s2.size();
- const int lmin = l1 < l2 ? l1 : l2;
- const UChar *c1 = s1.data();
- const UChar *c2 = s2.data();
- int l = 0;
- while (l < lmin && *c1 == *c2) {
- c1++;
- c2++;
- l++;
- }
- if (l < lmin)
- return (c1->uc < c2->uc);
-
- return (l1 < l2);
-}
-
-int compare(const UString& s1, const UString& s2)
-{
- const int l1 = s1.size();
- const int l2 = s2.size();
- const int lmin = l1 < l2 ? l1 : l2;
- const UChar *c1 = s1.data();
- const UChar *c2 = s2.data();
- int l = 0;
- while (l < lmin && *c1 == *c2) {
- c1++;
- c2++;
- l++;
- }
-
- if (l < lmin)
- return (c1->uc > c2->uc) ? 1 : -1;
-
- if (l1 == l2)
- return 0;
-
- return (l1 > l2) ? 1 : -1;
-}
-
-CString UString::UTF8String(bool strict) const
-{
- // Allocate a buffer big enough to hold all the characters.
- const int length = size();
- Vector<char, 1024> buffer(length * 3);
-
- // Convert to runs of 8-bit characters.
- char* p = buffer.data();
- const ::UChar* d = reinterpret_cast<const ::UChar*>(&data()->uc);
- ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
- if (result != conversionOK)
- return CString();
-
- return CString(buffer.data(), p - buffer.data());
-}
-
-} // namespace KJS
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _KJS_USTRING_H_
-#define _KJS_USTRING_H_
-
-#include "JSLock.h"
-#include "collector.h"
-#include <stdint.h>
-#include <wtf/Assertions.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-
-/* On some ARM platforms GCC won't pack structures by default so sizeof(UChar)
- will end up being != 2 which causes crashes since the code depends on that. */
-#if COMPILER(GCC) && PLATFORM(FORCE_PACK)
-#define PACK_STRUCT __attribute__((packed))
-#else
-#define PACK_STRUCT
-#endif
-
-/**
- * @internal
- */
-namespace DOM {
- class DOMString;
- class AtomicString;
-}
-class KJScript;
-
-namespace KJS {
-
- using WTF::PlacementNewAdoptType;
- using WTF::PlacementNewAdopt;
-
- class UString;
-
- /**
- * @short Unicode character.
- *
- * UChar represents a 16 bit Unicode character. It's internal data
- * representation is compatible to XChar2b and QChar. It's therefore
- * possible to exchange data with X and Qt with shallow copies.
- */
- struct UChar {
- /**
- * Construct a character with uninitialized value.
- */
- UChar();
- /**
- * Construct a character with the value denoted by the arguments.
- * @param h higher byte
- * @param l lower byte
- */
- UChar(unsigned char h , unsigned char l);
- /**
- * Construct a character with the given value.
- * @param u 16 bit Unicode value
- */
- UChar(char u);
- UChar(unsigned char u);
- UChar(unsigned short u);
- /**
- * @return The higher byte of the character.
- */
- unsigned char high() const { return static_cast<unsigned char>(uc >> 8); }
- /**
- * @return The lower byte of the character.
- */
- unsigned char low() const { return static_cast<unsigned char>(uc); }
- /**
- * @return the 16 bit Unicode value of the character
- */
- unsigned short unicode() const { return uc; }
-
- unsigned short uc;
- } PACK_STRUCT;
-
- inline UChar::UChar() { }
- inline UChar::UChar(unsigned char h , unsigned char l) : uc(h << 8 | l) { }
- inline UChar::UChar(char u) : uc((unsigned char)u) { }
- inline UChar::UChar(unsigned char u) : uc(u) { }
- inline UChar::UChar(unsigned short u) : uc(u) { }
-
- /**
- * @short 8 bit char based string class
- */
- class CString {
- public:
- CString() : data(0), length(0) { }
- CString(const char *c);
- CString(const char *c, size_t len);
- CString(const CString &);
-
- ~CString();
-
- CString &append(const CString &);
- CString &operator=(const char *c);
- CString &operator=(const CString &);
- CString &operator+=(const CString &c) { return append(c); }
-
- size_t size() const { return length; }
- const char *c_str() const { return data; }
- private:
- char *data;
- size_t length;
- };
-
- /**
- * @short Unicode string class
- */
- class UString {
- friend bool operator==(const UString&, const UString&);
-
- public:
- /**
- * @internal
- */
- struct Rep {
-
- static PassRefPtr<Rep> create(UChar *d, int l);
- static PassRefPtr<Rep> createCopying(const UChar *d, int l);
- static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
-
- void destroy();
-
- bool baseIsSelf() const { return baseString == this; }
- UChar* data() const { return baseString->buf + baseString->preCapacity + offset; }
- int size() const { return len; }
-
- unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; }
- unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers
-
- static unsigned computeHash(const UChar *, int length);
- static unsigned computeHash(const char *);
-
- Rep* ref() { ++rc; return this; }
- ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
-
- // unshared data
- int offset;
- int len;
- int rc;
- mutable unsigned _hash;
- bool isIdentifier;
- UString::Rep* baseString;
- size_t reportedCost;
-
- // potentially shared data
- UChar *buf;
- int usedCapacity;
- int capacity;
- int usedPreCapacity;
- int preCapacity;
-
- static Rep null;
- static Rep empty;
- };
-
- public:
-
- /**
- * Constructs a null string.
- */
- UString();
- /**
- * Constructs a string from a classical zero-terminated char string.
- */
- UString(const char *c);
- /**
- * Constructs a string from an array of Unicode characters of the specified
- * length.
- */
- UString(const UChar *c, int length);
- /**
- * If copy is false the string data will be adopted.
- * That means that the data will NOT be copied and the pointer will
- * be deleted when the UString object is modified or destroyed.
- * Behaviour defaults to a deep copy if copy is true.
- */
- UString(UChar *c, int length, bool copy);
- /**
- * Copy constructor. Makes a shallow copy only.
- */
- UString(const UString &s) : m_rep(s.m_rep) {}
-
- UString(const Vector<UChar>& buffer);
-
- /**
- * Convenience declaration only ! You'll be on your own to write the
- * implementation for a construction from DOM::DOMString.
- *
- * Note: feel free to contact me if you want to see a dummy header for
- * your favorite FooString class here !
- */
- UString(const DOM::DOMString&);
- /**
- * Convenience declaration only ! See UString(const DOM::DOMString&).
- */
- UString(const DOM::AtomicString&);
-
- /**
- * Concatenation constructor. Makes operator+ more efficient.
- */
- UString(const UString &, const UString &);
- /**
- * Destructor.
- */
- ~UString() {}
-
- // Special constructor for cases where we overwrite an object in place.
- UString(PlacementNewAdoptType) : m_rep(PlacementNewAdopt) { }
-
- /**
- * Constructs a string from an int.
- */
- static UString from(int i);
- /**
- * Constructs a string from an unsigned int.
- */
- static UString from(unsigned int u);
- /**
- * Constructs a string from a long int.
- */
- static UString from(long u);
- /**
- * Constructs a string from a double.
- */
- static UString from(double d);
-
- struct Range {
- public:
- Range(int pos, int len) : position(pos), length(len) {}
- Range() {}
- int position;
- int length;
- };
-
- UString spliceSubstringsWithSeparators(const Range *substringRanges, int rangeCount, const UString *separators, int separatorCount) const;
-
- /**
- * Append another string.
- */
- UString &append(const UString &);
- UString &append(const char *);
- UString &append(unsigned short);
- UString &append(char c) { return append(static_cast<unsigned short>(static_cast<unsigned char>(c))); }
- UString &append(UChar c) { return append(c.uc); }
-
- /**
- * @return The string converted to the 8-bit string type CString().
- * This method is not Unicode safe and shouldn't be used unless the string
- * is known to be ASCII.
- */
- CString cstring() const;
- /**
- * Convert the Unicode string to plain ASCII chars chopping of any higher
- * bytes. This method should only be used for *debugging* purposes as it
- * is neither Unicode safe nor free from side effects. In order not to
- * waste any memory the char buffer is static and *shared* by all UString
- * instances.
- */
- char *ascii() const;
-
- /**
- * Convert the string to UTF-8, assuming it is UTF-16 encoded.
- * In non-strict mode, this function is tolerant of badly formed UTF-16, it
- * can create UTF-8 strings that are invalid because they have characters in
- * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
- * guaranteed to be otherwise valid.
- * In strict mode, error is returned as null CString.
- */
- CString UTF8String(bool strict = false) const;
-
- /**
- * @see UString(const DOM::DOMString&).
- */
- DOM::DOMString domString() const;
-
- /**
- * Assignment operator.
- */
- UString &operator=(const char *c);
- /**
- * Appends the specified string.
- */
- UString &operator+=(const UString &s) { return append(s); }
- UString &operator+=(const char *s) { return append(s); }
-
- /**
- * @return A pointer to the internal Unicode data.
- */
- const UChar* data() const { return m_rep->data(); }
- /**
- * @return True if null.
- */
- bool isNull() const { return (m_rep == &Rep::null); }
- /**
- * @return True if null or zero length.
- */
- bool isEmpty() const { return (!m_rep->len); }
- /**
- * Use this if you want to make sure that this string is a plain ASCII
- * string. For example, if you don't want to lose any information when
- * using cstring() or ascii().
- *
- * @return True if the string doesn't contain any non-ASCII characters.
- */
- bool is8Bit() const;
- /**
- * @return The length of the string.
- */
- int size() const { return m_rep->size(); }
- /**
- * Const character at specified position.
- */
- const UChar operator[](int pos) const;
-
- /**
- * Attempts an conversion to a number. Apart from floating point numbers,
- * the algorithm will recognize hexadecimal representations (as
- * indicated by a 0x or 0X prefix) and +/- Infinity.
- * Returns NaN if the conversion failed.
- * @param tolerateTrailingJunk if true, toDouble can tolerate garbage after the number.
- * @param tolerateEmptyString if false, toDouble will turn an empty string into NaN rather than 0.
- */
- double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
- double toDouble(bool tolerateTrailingJunk) const;
- double toDouble() const;
-
- /**
- * Attempts an conversion to a 32-bit integer. ok will be set
- * according to the success.
- * @param tolerateEmptyString if false, toUInt32 will return false for *ok for an empty string.
- */
- uint32_t toUInt32(bool *ok = 0) const;
- uint32_t toUInt32(bool *ok, bool tolerateEmptyString) const;
- uint32_t toStrictUInt32(bool *ok = 0) const;
-
- /**
- * Attempts an conversion to an array index. The "ok" boolean will be set
- * to true if it is a valid array index according to the rule from
- * ECMA 15.2 about what an array index is. It must exactly match the string
- * form of an unsigned integer, and be less than 2^32 - 1.
- */
- unsigned toArrayIndex(bool *ok = 0) const;
-
- /**
- * @return Position of first occurrence of f starting at position pos.
- * -1 if the search was not successful.
- */
- int find(const UString &f, int pos = 0) const;
- int find(UChar, int pos = 0) const;
- /**
- * @return Position of first occurrence of f searching backwards from
- * position pos.
- * -1 if the search was not successful.
- */
- int rfind(const UString &f, int pos) const;
- int rfind(UChar, int pos) const;
- /**
- * @return The sub string starting at position pos and length len.
- */
- UString substr(int pos = 0, int len = -1) const;
- /**
- * Static instance of a null string.
- */
- static const UString &null();
-
- Rep* rep() const { return m_rep.get(); }
- UString(PassRefPtr<Rep> r) : m_rep(r) { ASSERT(m_rep); }
-
- size_t cost() const;
-
- private:
- size_t expandedSize(size_t size, size_t otherSize) const;
- int usedCapacity() const;
- int usedPreCapacity() const;
- void expandCapacity(int requiredLength);
- void expandPreCapacity(int requiredPreCap);
-
- RefPtr<Rep> m_rep;
- };
-
- inline bool operator==(const UChar &c1, const UChar &c2) {
- return (c1.uc == c2.uc);
- }
- bool operator==(const UString& s1, const UString& s2);
- inline bool operator!=(const UString& s1, const UString& s2) {
- return !KJS::operator==(s1, s2);
- }
- bool operator<(const UString& s1, const UString& s2);
- bool operator==(const UString& s1, const char *s2);
- inline bool operator!=(const UString& s1, const char *s2) {
- return !KJS::operator==(s1, s2);
- }
- inline bool operator==(const char *s1, const UString& s2) {
- return operator==(s2, s1);
- }
- inline bool operator!=(const char *s1, const UString& s2) {
- return !KJS::operator==(s1, s2);
- }
- bool operator==(const CString& s1, const CString& s2);
- inline UString operator+(const UString& s1, const UString& s2) {
- return UString(s1, s2);
- }
-
- int compare(const UString &, const UString &);
-
-inline UString::UString()
- : m_rep(&Rep::null)
-{
-}
-
-// Rule from ECMA 15.2 about what an array index is.
-// Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
-inline unsigned UString::toArrayIndex(bool *ok) const
-{
- unsigned i = toStrictUInt32(ok);
- if (ok && i >= 0xFFFFFFFFU)
- *ok = false;
- return i;
-}
-
-// We'd rather not do shared substring append for small strings, since
-// this runs too much risk of a tiny initial string holding down a
-// huge buffer.
-// FIXME: this should be size_t but that would cause warnings until we
-// fix UString sizes to be size_t instead of int
-static const int minShareSize = Collector::minExtraCostSize / sizeof(UChar);
-
-inline size_t UString::cost() const
-{
- size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar);
- size_t reportedCost = m_rep->baseString->reportedCost;
- ASSERT(capacity >= reportedCost);
-
- size_t capacityDelta = capacity - reportedCost;
-
- if (capacityDelta < static_cast<size_t>(minShareSize))
- return 0;
-
- m_rep->baseString->reportedCost = capacity;
- return capacityDelta;
-}
-
-} // namespace
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "value.h"
-
-#include "error_object.h"
-#include "nodes.h"
-#include <stdio.h>
-#include <string.h>
-#include <wtf/MathExtras.h>
-
-namespace KJS {
-
-#if defined NAN && defined INFINITY
-
-extern const double NaN = NAN;
-extern const double Inf = INFINITY;
-
-#else // !(defined NAN && defined INFINITY)
-
-// The trick is to define the NaN and Inf globals with a different type than the declaration.
-// This trick works because the mangled name of the globals does not include the type, although
-// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
-// characters don't necessarily need the same alignment doubles do, but for now it seems to work.
-// It would be good to figure out a 100% clean way that still avoids code that runs at init time.
-
-// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
-// while NaN_double has to be 4-byte aligned for 32-bits.
-// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
-
-static const union {
- struct {
- unsigned char NaN_Bytes[8];
- unsigned char Inf_Bytes[8];
- } bytes;
-
- struct {
- double NaN_Double;
- double Inf_Double;
- } doubles;
-
-} NaNInf = { {
-#if PLATFORM(BIG_ENDIAN)
- { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
- { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
-#elif PLATFORM(MIDDLE_ENDIAN)
- { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
- { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
-#else
- { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
- { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
-#endif
-} } ;
-
-extern const double NaN = NaNInf.doubles.NaN_Double;
-extern const double Inf = NaNInf.doubles.Inf_Double;
-
-#endif // !(defined NAN && defined INFINITY)
-
-static const double D16 = 65536.0;
-static const double D32 = 4294967296.0;
-
-void *JSCell::operator new(size_t size)
-{
- return Collector::allocate(size);
-}
-
-bool JSCell::getUInt32(uint32_t&) const
-{
- return false;
-}
-
-bool JSCell::getTruncatedInt32(int32_t&) const
-{
- return false;
-}
-
-bool JSCell::getTruncatedUInt32(uint32_t&) const
-{
- return false;
-}
-
-// ECMA 9.4
-double JSValue::toInteger(ExecState *exec) const
-{
- int32_t i;
- if (getTruncatedInt32(i))
- return i;
- double d = toNumber(exec);
- return isnan(d) ? 0.0 : trunc(d);
-}
-
-double JSValue::toIntegerPreserveNaN(ExecState *exec) const
-{
- int32_t i;
- if (getTruncatedInt32(i))
- return i;
- return trunc(toNumber(exec));
-}
-
-int32_t JSValue::toInt32SlowCase(double d, bool& ok)
-{
- ok = true;
-
- if (d >= -D32 / 2 && d < D32 / 2)
- return static_cast<int32_t>(d);
-
- if (isnan(d) || isinf(d)) {
- ok = false;
- return 0;
- }
-
- double d32 = fmod(trunc(d), D32);
- if (d32 >= D32 / 2)
- d32 -= D32;
- else if (d32 < -D32 / 2)
- d32 += D32;
- return static_cast<int32_t>(d32);
-}
-
-int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const
-{
- return JSValue::toInt32SlowCase(toNumber(exec), ok);
-}
-
-uint32_t JSValue::toUInt32SlowCase(double d, bool& ok)
-{
- ok = true;
-
- if (d >= 0.0 && d < D32)
- return static_cast<uint32_t>(d);
-
- if (isnan(d) || isinf(d)) {
- ok = false;
- return 0;
- }
-
- double d32 = fmod(trunc(d), D32);
- if (d32 < 0)
- d32 += D32;
- return static_cast<uint32_t>(d32);
-}
-
-uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const
-{
- return JSValue::toUInt32SlowCase(toNumber(exec), ok);
-}
-
-float JSValue::toFloat(ExecState* exec) const
-{
- return static_cast<float>(toNumber(exec));
-}
-
-bool JSCell::getNumber(double &numericValue) const
-{
- if (!isNumber())
- return false;
- numericValue = static_cast<const NumberImp *>(this)->value();
- return true;
-}
-
-double JSCell::getNumber() const
-{
- return isNumber() ? static_cast<const NumberImp *>(this)->value() : NaN;
-}
-
-bool JSCell::getString(UString &stringValue) const
-{
- if (!isString())
- return false;
- stringValue = static_cast<const StringImp *>(this)->value();
- return true;
-}
-
-UString JSCell::getString() const
-{
- return isString() ? static_cast<const StringImp *>(this)->value() : UString();
-}
-
-JSObject *JSCell::getObject()
-{
- return isObject() ? static_cast<JSObject *>(this) : 0;
-}
-
-const JSObject *JSCell::getObject() const
-{
- return isObject() ? static_cast<const JSObject *>(this) : 0;
-}
-
-JSCell* jsString(const char* s)
-{
- return new StringImp(s ? s : "");
-}
-
-JSCell* jsString(const UString& s)
-{
- return s.isNull() ? new StringImp("") : new StringImp(s);
-}
-
-JSCell* jsOwnedString(const UString& s)
-{
- return s.isNull() ? new StringImp("", StringImp::HasOtherOwner) : new StringImp(s, StringImp::HasOtherOwner);
-}
-
-// This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
-// it in a separate function to keep the normal case speedy.
-JSValue *jsNumberCell(double d)
-{
- return new NumberImp(d);
-}
-
-} // namespace KJS
+++ /dev/null
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_VALUE_H
-#define KJS_VALUE_H
-
-#include "JSImmediate.h"
-#include "collector.h"
-#include "ustring.h"
-#include <stddef.h> // for size_t
-
-namespace KJS {
-
-class ExecState;
-class JSObject;
-class JSCell;
-
-struct ClassInfo;
-
-/**
- * JSValue is the base type for all primitives (Undefined, Null, Boolean,
- * String, Number) and objects in ECMAScript.
- *
- * Note: you should never inherit from JSValue as it is for primitive types
- * only (all of which are provided internally by KJS). Instead, inherit from
- * JSObject.
- */
-class JSValue : Noncopyable {
- friend class JSCell; // so it can derive from this class
- friend class Collector; // so it can call asCell()
-
-private:
- JSValue();
- virtual ~JSValue();
-
-public:
- // Querying the type.
- JSType type() const;
- bool isUndefined() const;
- bool isNull() const;
- bool isUndefinedOrNull() const;
- bool isBoolean() const;
- bool isNumber() const;
- bool isString() const;
- bool isObject() const;
- bool isObject(const ClassInfo *) const;
-
- // Extracting the value.
- bool getBoolean(bool&) const;
- bool getBoolean() const; // false if not a boolean
- bool getNumber(double&) const;
- double getNumber() const; // NaN if not a number
- bool getString(UString&) const;
- UString getString() const; // null string if not a string
- JSObject *getObject(); // NULL if not an object
- const JSObject *getObject() const; // NULL if not an object
-
- // Extracting integer values.
- bool getUInt32(uint32_t&) const;
- bool getTruncatedInt32(int32_t&) const;
- bool getTruncatedUInt32(uint32_t&) const;
-
- // Basic conversions.
- JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
- bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value);
-
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
- UString toString(ExecState *exec) const;
- JSObject *toObject(ExecState *exec) const;
-
- // Integer conversions.
- double toInteger(ExecState*) const;
- double toIntegerPreserveNaN(ExecState*) const;
- int32_t toInt32(ExecState*) const;
- int32_t toInt32(ExecState*, bool& ok) const;
- uint32_t toUInt32(ExecState*) const;
- uint32_t toUInt32(ExecState*, bool& ok) const;
-
- // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
- static int32_t toInt32(double);
- static int32_t toUInt32(double);
-
- // Floating point conversions.
- float toFloat(ExecState*) const;
-
- // Garbage collection.
- void mark();
- bool marked() const;
-
- static int32_t toInt32SlowCase(double, bool& ok);
- static uint32_t toUInt32SlowCase(double, bool& ok);
-
-private:
- int32_t toInt32SlowCase(ExecState*, bool& ok) const;
- uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
-
- // Implementation details.
- JSCell *asCell();
- const JSCell *asCell() const;
-
- // Give a compile time error if we try to copy one of these.
- JSValue(const JSValue&);
- JSValue& operator=(const JSValue&);
-};
-
-class JSCell : public JSValue {
- friend class Collector;
- friend class NumberImp;
- friend class StringImp;
- friend class JSObject;
- friend class GetterSetterImp;
-private:
- JSCell();
- virtual ~JSCell();
-public:
- // Querying the type.
- virtual JSType type() const = 0;
- bool isNumber() const;
- bool isString() const;
- bool isObject() const;
- bool isObject(const ClassInfo *) const;
-
- // Extracting the value.
- bool getNumber(double&) const;
- double getNumber() const; // NaN if not a number
- bool getString(UString&) const;
- UString getString() const; // null string if not a string
- JSObject *getObject(); // NULL if not an object
- const JSObject *getObject() const; // NULL if not an object
-
- // Extracting integer values.
- virtual bool getUInt32(uint32_t&) const;
- virtual bool getTruncatedInt32(int32_t&) const;
- virtual bool getTruncatedUInt32(uint32_t&) const;
-
- // Basic conversions.
- virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
- virtual bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value) = 0;
- virtual bool toBoolean(ExecState *exec) const = 0;
- virtual double toNumber(ExecState *exec) const = 0;
- virtual UString toString(ExecState *exec) const = 0;
- virtual JSObject *toObject(ExecState *exec) const = 0;
-
- // Garbage collection.
- void *operator new(size_t);
- virtual void mark();
- bool marked() const;
-};
-
-JSValue *jsNumberCell(double);
-
-JSCell *jsString(const UString&); // returns empty string if passed null string
-JSCell *jsString(const char* = ""); // returns empty string if passed 0
-
-// should be used for strings that are owned by an object that will
-// likely outlive the JSValue this makes, such as the parse tree or a
-// DOM object that contains a UString
-JSCell *jsOwnedString(const UString&);
-
-extern const double NaN;
-extern const double Inf;
-
-inline JSValue *jsUndefined()
-{
- return JSImmediate::undefinedImmediate();
-}
-
-inline JSValue *jsNull()
-{
- return JSImmediate::nullImmediate();
-}
-
-inline JSValue *jsNaN()
-{
- static const union {
- uint64_t bits;
- double d;
- } nan = { 0x7ff80000ULL << 32 };
- return jsNumberCell(nan.d);
-}
-
-inline JSValue *jsBoolean(bool b)
-{
- return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
-}
-
-ALWAYS_INLINE JSValue* jsNumber(double d)
-{
- JSValue* v = JSImmediate::from(d);
- return v ? v : jsNumberCell(d);
-}
-
-ALWAYS_INLINE JSValue* jsNumber(int i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(i);
-}
-
-ALWAYS_INLINE JSValue* jsNumber(unsigned i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(i);
-}
-
-ALWAYS_INLINE JSValue* jsNumber(long i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(i);
-}
-
-ALWAYS_INLINE JSValue* jsNumber(unsigned long i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(i);
-}
-
-ALWAYS_INLINE JSValue* jsNumber(long long i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(static_cast<double>(i));
-}
-
-ALWAYS_INLINE JSValue* jsNumber(unsigned long long i)
-{
- JSValue* v = JSImmediate::from(i);
- return v ? v : jsNumberCell(static_cast<double>(i));
-}
-
-ALWAYS_INLINE JSValue* jsNumberFromAnd(ExecState *exec, JSValue* v1, JSValue* v2)
-{
- if (JSImmediate::areBothImmediateNumbers(v1, v2))
- return JSImmediate::andImmediateNumbers(v1, v2);
- return jsNumber(v1->toInt32(exec) & v2->toInt32(exec));
-}
-
-inline JSValue::JSValue()
-{
-}
-
-inline JSValue::~JSValue()
-{
-}
-
-inline JSCell::JSCell()
-{
-}
-
-inline JSCell::~JSCell()
-{
-}
-
-inline bool JSCell::isNumber() const
-{
- return type() == NumberType;
-}
-
-inline bool JSCell::isString() const
-{
- return type() == StringType;
-}
-
-inline bool JSCell::isObject() const
-{
- return type() == ObjectType;
-}
-
-inline bool JSCell::marked() const
-{
- return Collector::isCellMarked(this);
-}
-
-inline void JSCell::mark()
-{
- return Collector::markCell(this);
-}
-
-ALWAYS_INLINE JSCell* JSValue::asCell()
-{
- ASSERT(!JSImmediate::isImmediate(this));
- return static_cast<JSCell*>(this);
-}
-
-ALWAYS_INLINE const JSCell* JSValue::asCell() const
-{
- ASSERT(!JSImmediate::isImmediate(this));
- return static_cast<const JSCell*>(this);
-}
-
-inline bool JSValue::isUndefined() const
-{
- return this == jsUndefined();
-}
-
-inline bool JSValue::isNull() const
-{
- return this == jsNull();
-}
-
-inline bool JSValue::isUndefinedOrNull() const
-{
- return JSImmediate::isUndefinedOrNull(this);
-}
-
-inline bool JSValue::isBoolean() const
-{
- return JSImmediate::isBoolean(this);
-}
-
-inline bool JSValue::isNumber() const
-{
- return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
-}
-
-inline bool JSValue::isString() const
-{
- return !JSImmediate::isImmediate(this) && asCell()->isString();
-}
-
-inline bool JSValue::isObject() const
-{
- return !JSImmediate::isImmediate(this) && asCell()->isObject();
-}
-
-inline bool JSValue::getBoolean(bool& v) const
-{
- if (JSImmediate::isBoolean(this)) {
- v = JSImmediate::toBoolean(this);
- return true;
- }
-
- return false;
-}
-
-inline bool JSValue::getBoolean() const
-{
- return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
-}
-
-inline bool JSValue::getNumber(double& v) const
-{
- if (JSImmediate::isImmediate(this)) {
- v = JSImmediate::toDouble(this);
- return true;
- }
- return asCell()->getNumber(v);
-}
-
-inline double JSValue::getNumber() const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
-}
-
-inline bool JSValue::getString(UString& s) const
-{
- return !JSImmediate::isImmediate(this) && asCell()->getString(s);
-}
-
-inline UString JSValue::getString() const
-{
- return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
-}
-
-inline JSObject *JSValue::getObject()
-{
- return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
-}
-
-inline const JSObject *JSValue::getObject() const
-{
- return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
-}
-
-ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
-}
-
-ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
-}
-
-inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
-}
-
-inline void JSValue::mark()
-{
- ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
- asCell()->mark();
-}
-
-inline bool JSValue::marked() const
-{
- return JSImmediate::isImmediate(this) || asCell()->marked();
-}
-
-inline JSType JSValue::type() const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
-}
-
-inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
-{
- return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
-}
-
-inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
-{
- if (JSImmediate::isImmediate(this)) {
- number = JSImmediate::toDouble(this);
- value = this;
- return true;
- }
- return asCell()->getPrimitiveNumber(exec, number, value);
-}
-
-inline bool JSValue::toBoolean(ExecState *exec) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
-}
-
-ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
-}
-
-ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
-{
- return JSImmediate::isNumber(this) ? const_cast<JSValue*>(this) : jsNumber(this->toNumber(exec));
-}
-
-inline UString JSValue::toString(ExecState *exec) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
-}
-
-inline JSObject* JSValue::toObject(ExecState* exec) const
-{
- return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
-}
-
-ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
-{
- int32_t i;
- if (getTruncatedInt32(i))
- return i;
- bool ok;
- return toInt32SlowCase(exec, ok);
-}
-
-inline uint32_t JSValue::toUInt32(ExecState* exec) const
-{
- uint32_t i;
- if (getTruncatedUInt32(i))
- return i;
- bool ok;
- return toUInt32SlowCase(exec, ok);
-}
-
-inline int32_t JSValue::toInt32(double val)
-{
- if (!(val >= -2147483648.0 && val < 2147483648.0)) {
- bool ignored;
- return toInt32SlowCase(val, ignored);
- }
- return static_cast<int32_t>(val);
-}
-
-inline int32_t JSValue::toUInt32(double val)
-{
- if (!(val >= 0.0 && val < 4294967296.0)) {
- bool ignored;
- return toUInt32SlowCase(val, ignored);
- }
- return static_cast<uint32_t>(val);
-}
-
-inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
-{
- int32_t i;
- if (getTruncatedInt32(i)) {
- ok = true;
- return i;
- }
- return toInt32SlowCase(exec, ok);
-}
-
-inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
-{
- uint32_t i;
- if (getTruncatedUInt32(i)) {
- ok = true;
- return i;
- }
- return toUInt32SlowCase(exec, ok);
-}
-
-} // namespace
-
-#endif // KJS_VALUE_H
export SRCROOT=$PWD
export WebCore=$PWD
-export CREATE_HASH_TABLE="$SRCROOT/kjs/create_hash_table"
+export CREATE_HASH_TABLE="$SRCROOT/create_hash_table"
mkdir -p DerivedSources/JavaScriptCore
cd DerivedSources/JavaScriptCore
#error "This stdint.h file should only be compiled under Windows"
#endif
+#include <limits.h>
+
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+#ifndef SIZE_MAX
+#ifdef _WIN64
+#define SIZE_MAX _UI64_MAX
+#else
+#define SIZE_MAX _UI32_MAX
+#endif
+#endif
+#endif
+
#ifndef CASSERT
#define CASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
#endif
--- /dev/null
+%pure_parser
+
+%{
+
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include "JSValue.h"
+#include "JSObject.h"
+#include "Nodes.h"
+#include "Lexer.h"
+#include "JSString.h"
+#include "JSGlobalData.h"
+#include "CommonIdentifiers.h"
+#include "NodeInfo.h"
+#include "Parser.h"
+#include <wtf/MathExtras.h>
+
+#define YYMAXDEPTH 10000
+#define YYENABLE_NLS 0
+
+/* default values for bison */
+#define YYDEBUG 0 // Set to 1 to debug a parse error.
+#define jscyydebug 0 // Set to 1 to debug a parse error.
+#if !PLATFORM(DARWIN)
+ // avoid triggering warnings in older bison
+#define YYERROR_VERBOSE
+#endif
+
+int jscyylex(void* lvalp, void* llocp, void* globalPtr);
+int jscyyerror(const char*);
+static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
+
+#define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
+#define LEXER (GLOBAL_DATA->lexer)
+
+#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0)
+#define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot))
+#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
+
+using namespace JSC;
+using namespace std;
+
+static ExpressionNode* makeAssignNode(void*, ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end);
+static ExpressionNode* makePrefixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
+static ExpressionNode* makePostfixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
+static PropertyNode* makeGetterOrSetterPropertyNode(void*, const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
+static ExpressionNodeInfo makeFunctionCallNode(void*, ExpressionNodeInfo func, ArgumentsNodeInfo, int start, int divot, int end);
+static ExpressionNode* makeTypeOfNode(void*, ExpressionNode*);
+static ExpressionNode* makeDeleteNode(void*, ExpressionNode*, int start, int divot, int end);
+static ExpressionNode* makeNegateNode(void*, ExpressionNode*);
+static NumberNode* makeNumberNode(void*, double);
+static ExpressionNode* makeBitwiseNotNode(void*, ExpressionNode*);
+static ExpressionNode* makeMultNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeDivNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeAddNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeSubNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeLeftShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeRightShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static StatementNode* makeVarStatementNode(void*, ExpressionNode*);
+static ExpressionNode* combineVarInitializers(void*, ExpressionNode* list, AssignResolveNode* init);
+
+#if COMPILER(MSVC)
+
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4702)
+
+// At least some of the time, the declarations of malloc and free that bison
+// generates are causing warnings. A way to avoid this is to explicitly define
+// the macros so that bison doesn't try to declare malloc and free.
+#define YYMALLOC malloc
+#define YYFREE free
+
+#endif
+
+#define YYPARSE_PARAM globalPtr
+#define YYLEX_PARAM globalPtr
+
+template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls,
+ CodeFeatures info,
+ int numConstants)
+{
+ ASSERT((info & ~AllFeatures) == 0);
+ NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info, numConstants};
+ return result;
+}
+
+template <typename T> NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
+{
+ ASSERT((info & ~AllFeatures) == 0);
+ NodeInfo<T> result = {node, info, numConstants};
+ return result;
+}
+
+template <typename T> T mergeDeclarationLists(T decls1, T decls2)
+{
+ // decls1 or both are null
+ if (!decls1)
+ return decls2;
+ // only decls1 is non-null
+ if (!decls2)
+ return decls1;
+
+ // Both are non-null
+ decls1->data.append(decls2->data);
+
+ // We manually release the declaration lists to avoid accumulating many many
+ // unused heap allocated vectors
+ decls2->ref();
+ decls2->deref();
+ return decls1;
+}
+
+static void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
+{
+ if (!varDecls)
+ varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+
+ varDecls->data.append(make_pair(ident, attrs));
+
+}
+
+static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
+{
+ unsigned attrs = DeclarationStacks::IsConstant;
+ if (decl->m_init)
+ attrs |= DeclarationStacks::HasInitializer;
+ appendToVarDeclarationList(globalPtr, varDecls, decl->m_ident, attrs);
+}
+
+%}
+
+%union {
+ int intValue;
+ double doubleValue;
+ Identifier* ident;
+
+ // expression subtrees
+ ExpressionNodeInfo expressionNode;
+ FuncDeclNodeInfo funcDeclNode;
+ PropertyNodeInfo propertyNode;
+ ArgumentsNodeInfo argumentsNode;
+ ConstDeclNodeInfo constDeclNode;
+ CaseBlockNodeInfo caseBlockNode;
+ CaseClauseNodeInfo caseClauseNode;
+ FuncExprNodeInfo funcExprNode;
+
+ // statement nodes
+ StatementNodeInfo statementNode;
+ FunctionBodyNode* functionBodyNode;
+ ProgramNode* programNode;
+
+ SourceElementsInfo sourceElements;
+ PropertyListInfo propertyList;
+ ArgumentListInfo argumentList;
+ VarDeclListInfo varDeclList;
+ ConstDeclListInfo constDeclList;
+ ClauseListInfo clauseList;
+ ElementListInfo elementList;
+ ParameterListInfo parameterList;
+
+ Operator op;
+}
+
+%start Program
+
+/* literals */
+%token NULLTOKEN TRUETOKEN FALSETOKEN
+
+/* keywords */
+%token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE
+%token FUNCTION RETURN VOIDTOKEN DELETETOKEN
+%token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF
+%token SWITCH WITH RESERVED
+%token THROW TRY CATCH FINALLY
+%token DEBUGGER
+
+/* give an if without an else higher precedence than an else to resolve the ambiguity */
+%nonassoc IF_WITHOUT_ELSE
+%nonassoc ELSE
+
+/* punctuators */
+%token EQEQ NE /* == and != */
+%token STREQ STRNEQ /* === and !== */
+%token LE GE /* < and > */
+%token OR AND /* || and && */
+%token PLUSPLUS MINUSMINUS /* ++ and -- */
+%token LSHIFT /* << */
+%token RSHIFT URSHIFT /* >> and >>> */
+%token PLUSEQUAL MINUSEQUAL /* += and -= */
+%token MULTEQUAL DIVEQUAL /* *= and /= */
+%token LSHIFTEQUAL /* <<= */
+%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
+%token ANDEQUAL MODEQUAL /* &= and %= */
+%token XOREQUAL OREQUAL /* ^= and |= */
+%token <intValue> OPENBRACE /* { (with char offset) */
+%token <intValue> CLOSEBRACE /* { (with char offset) */
+
+/* terminal types */
+%token <doubleValue> NUMBER
+%token <ident> IDENT STRING
+
+/* automatically inserted semicolon */
+%token AUTOPLUSPLUS AUTOMINUSMINUS
+
+/* non-terminal types */
+%type <expressionNode> Literal ArrayLiteral
+
+%type <expressionNode> PrimaryExpr PrimaryExprNoBrace
+%type <expressionNode> MemberExpr MemberExprNoBF /* BF => brace or function */
+%type <expressionNode> NewExpr NewExprNoBF
+%type <expressionNode> CallExpr CallExprNoBF
+%type <expressionNode> LeftHandSideExpr LeftHandSideExprNoBF
+%type <expressionNode> PostfixExpr PostfixExprNoBF
+%type <expressionNode> UnaryExpr UnaryExprNoBF UnaryExprCommon
+%type <expressionNode> MultiplicativeExpr MultiplicativeExprNoBF
+%type <expressionNode> AdditiveExpr AdditiveExprNoBF
+%type <expressionNode> ShiftExpr ShiftExprNoBF
+%type <expressionNode> RelationalExpr RelationalExprNoIn RelationalExprNoBF
+%type <expressionNode> EqualityExpr EqualityExprNoIn EqualityExprNoBF
+%type <expressionNode> BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
+%type <expressionNode> BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
+%type <expressionNode> BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
+%type <expressionNode> LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
+%type <expressionNode> LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
+%type <expressionNode> ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
+%type <expressionNode> AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
+%type <expressionNode> Expr ExprNoIn ExprNoBF
+
+%type <expressionNode> ExprOpt ExprNoInOpt
+
+%type <statementNode> Statement Block
+%type <statementNode> VariableStatement ConstStatement EmptyStatement ExprStatement
+%type <statementNode> IfStatement IterationStatement ContinueStatement
+%type <statementNode> BreakStatement ReturnStatement WithStatement
+%type <statementNode> SwitchStatement LabelledStatement
+%type <statementNode> ThrowStatement TryStatement
+%type <statementNode> DebuggerStatement
+
+%type <expressionNode> Initializer InitializerNoIn
+%type <statementNode> FunctionDeclaration
+%type <funcExprNode> FunctionExpr
+%type <functionBodyNode> FunctionBody
+%type <sourceElements> SourceElements
+%type <parameterList> FormalParameterList
+%type <op> AssignmentOperator
+%type <argumentsNode> Arguments
+%type <argumentList> ArgumentList
+%type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn
+%type <constDeclList> ConstDeclarationList
+%type <constDeclNode> ConstDeclaration
+%type <caseBlockNode> CaseBlock
+%type <caseClauseNode> CaseClause DefaultClause
+%type <clauseList> CaseClauses CaseClausesOpt
+%type <intValue> Elision ElisionOpt
+%type <elementList> ElementList
+%type <propertyNode> Property
+%type <propertyList> PropertyList
+%%
+
+// FIXME: There are currently two versions of the grammar in this file, the normal one, and the NoNodes version used for
+// lazy recompilation of FunctionBodyNodes. We should move to generating the two versions from a script to avoid bugs.
+// In the mean time, make sure to make any changes to the grammar in both versions.
+
+Literal:
+ NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new NullNode(GLOBAL_DATA), 0, 1); }
+ | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, true), 0, 1); }
+ | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, false), 0, 1); }
+ | NUMBER { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
+ | STRING { $$ = createNodeInfo<ExpressionNode*>(new StringNode(GLOBAL_DATA, *$1), 0, 1); }
+ | '/' /* regexp */ {
+ Lexer& l = *LEXER;
+ if (!l.scanRegExp())
+ YYABORT;
+ RegExpNode* node = new RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
+ int size = l.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())
+ YYABORT;
+ RegExpNode* node = new RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
+ int size = l.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);
+ }
+;
+
+Property:
+ IDENT ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, 0, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
+ | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, $4.m_node.head, $7, LEXER->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ if (!$$.m_node)
+ YYABORT;
+ }
+;
+
+PropertyList:
+ Property { $$.m_node.head = new PropertyListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | PropertyList ',' Property { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail);
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+PrimaryExpr:
+ PrimaryExprNoBrace
+ | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA), 0, 0); }
+ | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+ /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
+ | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+;
+
+PrimaryExprNoBrace:
+ THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new ThisNode(GLOBAL_DATA), ThisFeature, 0); }
+ | Literal
+ | ArrayLiteral
+ | IDENT { $$ = createNodeInfo<ExpressionNode*>(new ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
+ | '(' Expr ')' { $$ = $2; }
+;
+
+ArrayLiteral:
+ '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); }
+ | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+ | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); }
+;
+
+ElementList:
+ ElisionOpt AssignmentExpr { $$.m_node.head = new ElementNode(GLOBAL_DATA, $1, $2.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $2.m_features;
+ $$.m_numConstants = $2.m_numConstants; }
+ | ElementList ',' ElisionOpt AssignmentExpr
+ { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node);
+ $$.m_features = $1.m_features | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants; }
+;
+
+ElisionOpt:
+ /* nothing */ { $$ = 0; }
+ | Elision
+;
+
+Elision:
+ ',' { $$ = 1; }
+ | Elision ',' { $$ = $1 + 1; }
+;
+
+MemberExpr:
+ PrimaryExpr
+ | FunctionExpr { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
+ | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | MemberExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+ | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
+ }
+;
+
+MemberExprNoBF:
+ PrimaryExprNoBrace
+ | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+ | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
+ }
+;
+
+NewExpr:
+ MemberExpr
+ | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
+ }
+;
+
+NewExprNoBF:
+ MemberExprNoBF
+ | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
+ }
+;
+
+CallExpr:
+ MemberExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | CallExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
+;
+
+CallExprNoBF:
+ MemberExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | CallExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+;
+
+Arguments:
+ '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA), 0, 0); }
+ | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+;
+
+ArgumentList:
+ AssignmentExpr { $$.m_node.head = new ArgumentListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | ArgumentList ',' AssignmentExpr { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node);
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+LeftHandSideExpr:
+ NewExpr
+ | CallExpr
+;
+
+LeftHandSideExprNoBF:
+ NewExprNoBF
+ | CallExprNoBF
+;
+
+PostfixExpr:
+ LeftHandSideExpr
+ | LeftHandSideExpr PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+ | LeftHandSideExpr MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+;
+
+PostfixExprNoBF:
+ LeftHandSideExprNoBF
+ | LeftHandSideExprNoBF PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+ | LeftHandSideExprNoBF MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+;
+
+UnaryExprCommon:
+ DELETETOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, $2.m_node, @1.first_column, @2.last_column, @2.last_column), $2.m_features, $2.m_numConstants); }
+ | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); }
+ | TYPEOF UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | PLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | AUTOPLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | MINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | AUTOMINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | '+' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '-' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '~' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '!' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+
+UnaryExpr:
+ PostfixExpr
+ | UnaryExprCommon
+;
+
+UnaryExprNoBF:
+ PostfixExprNoBF
+ | UnaryExprCommon
+;
+
+MultiplicativeExpr:
+ UnaryExpr
+ | MultiplicativeExpr '*' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExpr '/' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+MultiplicativeExprNoBF:
+ UnaryExprNoBF
+ | MultiplicativeExprNoBF '*' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExprNoBF '/' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExprNoBF '%' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+AdditiveExpr:
+ MultiplicativeExpr
+ | AdditiveExpr '+' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | AdditiveExpr '-' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+AdditiveExprNoBF:
+ MultiplicativeExprNoBF
+ | AdditiveExprNoBF '+' MultiplicativeExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | AdditiveExprNoBF '-' MultiplicativeExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ShiftExpr:
+ AdditiveExpr
+ | ShiftExpr LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExpr RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ShiftExprNoBF:
+ AdditiveExprNoBF
+ | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExpr:
+ ShiftExpr
+ | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr INTOKEN ShiftExpr { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExprNoIn:
+ ShiftExpr
+ | RelationalExprNoIn '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn INSTANCEOF ShiftExpr
+ { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExprNoBF:
+ ShiftExprNoBF
+ | RelationalExprNoBF '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF INSTANCEOF ShiftExpr
+ { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF INTOKEN ShiftExpr
+ { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExpr:
+ RelationalExpr
+ | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr STREQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr STRNEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExprNoIn:
+ RelationalExprNoIn
+ | EqualityExprNoIn EQEQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn NE RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn STREQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn STRNEQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExprNoBF:
+ RelationalExprNoBF
+ | EqualityExprNoBF EQEQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF STREQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF STRNEQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExpr:
+ EqualityExpr
+ | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExprNoIn:
+ EqualityExprNoIn
+ | BitwiseANDExprNoIn '&' EqualityExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExprNoBF:
+ EqualityExprNoBF
+ | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExpr:
+ BitwiseANDExpr
+ | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExprNoIn:
+ BitwiseANDExprNoIn
+ | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExprNoBF:
+ BitwiseANDExprNoBF
+ | BitwiseXORExprNoBF '^' BitwiseANDExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExpr:
+ BitwiseXORExpr
+ | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExprNoIn:
+ BitwiseXORExprNoIn
+ | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExprNoBF:
+ BitwiseXORExprNoBF
+ | BitwiseORExprNoBF '|' BitwiseXORExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExpr:
+ BitwiseORExpr
+ | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExprNoIn:
+ BitwiseORExprNoIn
+ | LogicalANDExprNoIn AND BitwiseORExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExprNoBF:
+ BitwiseORExprNoBF
+ | LogicalANDExprNoBF AND BitwiseORExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExpr:
+ LogicalANDExpr
+ | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExprNoIn:
+ LogicalANDExprNoIn
+ | LogicalORExprNoIn OR LogicalANDExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExprNoBF:
+ LogicalANDExprNoBF
+ | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ConditionalExpr:
+ LogicalORExpr
+ | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+ConditionalExprNoIn:
+ LogicalORExprNoIn
+ | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+ConditionalExprNoBF:
+ LogicalORExprNoBF
+ | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+AssignmentExpr:
+ ConditionalExpr
+ | LeftHandSideExpr AssignmentOperator AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentExprNoIn:
+ ConditionalExprNoIn
+ | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentExprNoBF:
+ ConditionalExprNoBF
+ | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentOperator:
+ '=' { $$ = OpEqual; }
+ | PLUSEQUAL { $$ = OpPlusEq; }
+ | MINUSEQUAL { $$ = OpMinusEq; }
+ | MULTEQUAL { $$ = OpMultEq; }
+ | DIVEQUAL { $$ = OpDivEq; }
+ | LSHIFTEQUAL { $$ = OpLShift; }
+ | RSHIFTEQUAL { $$ = OpRShift; }
+ | URSHIFTEQUAL { $$ = OpURShift; }
+ | ANDEQUAL { $$ = OpAndEq; }
+ | XOREQUAL { $$ = OpXOrEq; }
+ | OREQUAL { $$ = OpOrEq; }
+ | MODEQUAL { $$ = OpModEq; }
+;
+
+Expr:
+ AssignmentExpr
+ | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ExprNoIn:
+ AssignmentExprNoIn
+ | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ExprNoBF:
+ AssignmentExprNoBF
+ | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+Statement:
+ Block
+ | VariableStatement
+ | ConstStatement
+ | FunctionDeclaration
+ | EmptyStatement
+ | ExprStatement
+ | IfStatement
+ | IterationStatement
+ | ContinueStatement
+ | BreakStatement
+ | ReturnStatement
+ | WithStatement
+ | SwitchStatement
+ | LabelledStatement
+ | ThrowStatement
+ | TryStatement
+ | DebuggerStatement
+;
+
+Block:
+ OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+;
+
+VariableStatement:
+ VAR VariableDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | VAR VariableDeclarationList error { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @2);
+ AUTO_SEMICOLON; }
+;
+
+VariableDeclarationList:
+ IDENT { $$.m_node = 0;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_numConstants = 0;
+ }
+ | IDENT Initializer { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+ $$.m_node = node;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
+ $$.m_numConstants = $2.m_numConstants;
+ }
+ | VariableDeclarationList ',' IDENT
+ { $$.m_node = $1.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | VariableDeclarationList ',' IDENT Initializer
+ { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+ $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
+ }
+;
+
+VariableDeclarationListNoIn:
+ IDENT { $$.m_node = 0;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_numConstants = 0;
+ }
+ | IDENT InitializerNoIn { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+ $$.m_node = node;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
+ $$.m_numConstants = $2.m_numConstants;
+ }
+ | VariableDeclarationListNoIn ',' IDENT
+ { $$.m_node = $1.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
+ { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+ $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
+ }
+;
+
+ConstStatement:
+ CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | CONSTTOKEN ConstDeclarationList error
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+ConstDeclarationList:
+ ConstDeclaration { $$.m_node.head = $1.m_node;
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $1.m_node);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | ConstDeclarationList ',' ConstDeclaration
+ { $$.m_node.head = $1.m_node.head;
+ $1.m_node.tail->m_next = $3.m_node;
+ $$.m_node.tail = $3.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $3.m_node);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+ConstDeclaration:
+ IDENT { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
+ | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); }
+;
+
+Initializer:
+ '=' AssignmentExpr { $$ = $2; }
+;
+
+InitializerNoIn:
+ '=' AssignmentExprNoIn { $$ = $2; }
+;
+
+EmptyStatement:
+ ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); }
+;
+
+ExprStatement:
+ ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+;
+
+IfStatement:
+ IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+ | IF '(' Expr ')' Statement ELSE Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node),
+ mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
+ $3.m_features | $5.m_features | $7.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+IterationStatement:
+ DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
+ | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+ | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations,
+ $3.m_features | $5.m_features | $7.m_features | $9.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @8);
+ }
+ | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
+ mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
+ mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
+ $4.m_features | $6.m_features | $8.m_features | $10.m_features,
+ $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
+ DBG($$.m_node, @1, @9); }
+ | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
+ {
+ ForInNode* node = new ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @3.last_column, @5.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
+ $3.m_features | $5.m_features | $7.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @6);
+ }
+ | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
+ { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
+ SET_EXCEPTION_LOCATION(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
+ appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
+ $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
+ DBG($$.m_node, @1, @7); }
+ | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
+ { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
+ SET_EXCEPTION_LOCATION(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
+ appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
+ $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
+ ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
+ $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @8); }
+;
+
+ExprOpt:
+ /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
+ | Expr
+;
+
+ExprNoInOpt:
+ /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
+ | ExprNoIn
+;
+
+ContinueStatement:
+ CONTINUE ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | CONTINUE error { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | CONTINUE IDENT ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @3); }
+ | CONTINUE IDENT error { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+BreakStatement:
+ BREAK ';' { BreakNode* node = new BreakNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+ | BREAK error { BreakNode* node = new BreakNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | BREAK IDENT ';' { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); }
+ | BREAK IDENT error { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+ReturnStatement:
+ RETURN ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+ | RETURN error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | RETURN Expr ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); }
+ | RETURN Expr error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+WithStatement:
+ WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
+ $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+SwitchStatement:
+ SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
+ $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+CaseBlock:
+ OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); }
+ | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
+ { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations),
+ $2.m_features | $3.m_features | $4.m_features,
+ $2.m_numConstants + $3.m_numConstants + $4.m_numConstants); }
+;
+
+CaseClausesOpt:
+/* nothing */ { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
+ | CaseClauses
+;
+
+CaseClauses:
+ CaseClause { $$.m_node.head = new ClauseListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ $$.m_funcDeclarations = $1.m_funcDeclarations;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node);
+ $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
+ $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
+ $$.m_features = $1.m_features | $2.m_features;
+ $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
+ }
+;
+
+CaseClause:
+ CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); }
+ | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); }
+;
+
+DefaultClause:
+ DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); }
+ | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
+;
+
+LabelledStatement:
+ IDENT ':' Statement { LabelNode* node = new LabelNode(GLOBAL_DATA, *$1, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
+;
+
+ThrowStatement:
+ THROW Expr ';' { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2);
+ }
+ | THROW Expr error { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON;
+ }
+;
+
+TryStatement:
+ TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node),
+ mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
+ mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
+ $2.m_features | $4.m_features,
+ $2.m_numConstants + $4.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0),
+ mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
+ mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
+ $2.m_features | $7.m_features | CatchFeature,
+ $2.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
+ $2.m_features | $7.m_features | $9.m_features | CatchFeature,
+ $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+;
+
+DebuggerStatement:
+ DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+;
+
+FunctionDeclaration:
+ FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node));
+ }
+;
+
+FunctionExpr:
+ FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, LEXER->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); DBG($5, @4, @6); }
+ | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, LEXER->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0);
+ if ($3.m_features & ArgumentsFeature)
+ $6->setUsesArguments();
+ DBG($6, @5, @7);
+ }
+ | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ }
+;
+
+FormalParameterList:
+ IDENT { $$.m_node.head = new ParameterNode(GLOBAL_DATA, *$1);
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_node.tail = $$.m_node.head; }
+ | FormalParameterList ',' IDENT { $$.m_node.head = $1.m_node.head;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_node.tail = new ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); }
+;
+
+FunctionBody:
+ /* not in spec */ { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
+ | SourceElements_NoNode { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
+;
+
+Program:
+ /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); }
+ | SourceElements { GLOBAL_DATA->parser->didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, $1.m_features,
+ @1.last_line, $1.m_numConstants); }
+;
+
+SourceElements:
+ Statement { $$.m_node = new SourceElements(GLOBAL_DATA);
+ $$.m_node->append($1.m_node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ $$.m_funcDeclarations = $1.m_funcDeclarations;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | SourceElements Statement { $$.m_node->append($2.m_node);
+ $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
+ $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
+ $$.m_features = $1.m_features | $2.m_features;
+ $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
+ }
+;
+
+// Start NoNodes
+
+Literal_NoNode:
+ NULLTOKEN
+ | TRUETOKEN
+ | FALSETOKEN
+ | NUMBER { }
+ | STRING { }
+ | '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+ | DIVEQUAL /* regexp with /= */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+;
+
+Property_NoNode:
+ IDENT ':' AssignmentExpr_NoNode { }
+ | STRING ':' AssignmentExpr_NoNode { }
+ | NUMBER ':' AssignmentExpr_NoNode { }
+ | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
+ | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
+;
+
+PropertyList_NoNode:
+ Property_NoNode
+ | PropertyList_NoNode ',' Property_NoNode
+;
+
+PrimaryExpr_NoNode:
+ PrimaryExprNoBrace_NoNode
+ | OPENBRACE CLOSEBRACE { }
+ | OPENBRACE PropertyList_NoNode CLOSEBRACE { }
+ /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
+ | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE { }
+;
+
+PrimaryExprNoBrace_NoNode:
+ THISTOKEN
+ | Literal_NoNode
+ | ArrayLiteral_NoNode
+ | IDENT { }
+ | '(' Expr_NoNode ')'
+;
+
+ArrayLiteral_NoNode:
+ '[' ElisionOpt_NoNode ']'
+ | '[' ElementList_NoNode ']'
+ | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']'
+;
+
+ElementList_NoNode:
+ ElisionOpt_NoNode AssignmentExpr_NoNode
+ | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode
+;
+
+ElisionOpt_NoNode:
+ /* nothing */
+ | Elision_NoNode
+;
+
+Elision_NoNode:
+ ','
+ | Elision_NoNode ','
+;
+
+MemberExpr_NoNode:
+ PrimaryExpr_NoNode
+ | FunctionExpr_NoNode
+ | MemberExpr_NoNode '[' Expr_NoNode ']'
+ | MemberExpr_NoNode '.' IDENT
+ | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+MemberExprNoBF_NoNode:
+ PrimaryExprNoBrace_NoNode
+ | MemberExprNoBF_NoNode '[' Expr_NoNode ']'
+ | MemberExprNoBF_NoNode '.' IDENT
+ | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+NewExpr_NoNode:
+ MemberExpr_NoNode
+ | NEW NewExpr_NoNode
+;
+
+NewExprNoBF_NoNode:
+ MemberExprNoBF_NoNode
+ | NEW NewExpr_NoNode
+;
+
+CallExpr_NoNode:
+ MemberExpr_NoNode Arguments_NoNode
+ | CallExpr_NoNode Arguments_NoNode
+ | CallExpr_NoNode '[' Expr_NoNode ']'
+ | CallExpr_NoNode '.' IDENT
+;
+
+CallExprNoBF_NoNode:
+ MemberExprNoBF_NoNode Arguments_NoNode
+ | CallExprNoBF_NoNode Arguments_NoNode
+ | CallExprNoBF_NoNode '[' Expr_NoNode ']'
+ | CallExprNoBF_NoNode '.' IDENT
+;
+
+Arguments_NoNode:
+ '(' ')'
+ | '(' ArgumentList_NoNode ')'
+;
+
+ArgumentList_NoNode:
+ AssignmentExpr_NoNode
+ | ArgumentList_NoNode ',' AssignmentExpr_NoNode
+;
+
+LeftHandSideExpr_NoNode:
+ NewExpr_NoNode
+ | CallExpr_NoNode
+;
+
+LeftHandSideExprNoBF_NoNode:
+ NewExprNoBF_NoNode
+ | CallExprNoBF_NoNode
+;
+
+PostfixExpr_NoNode:
+ LeftHandSideExpr_NoNode
+ | LeftHandSideExpr_NoNode PLUSPLUS
+ | LeftHandSideExpr_NoNode MINUSMINUS
+;
+
+PostfixExprNoBF_NoNode:
+ LeftHandSideExprNoBF_NoNode
+ | LeftHandSideExprNoBF_NoNode PLUSPLUS
+ | LeftHandSideExprNoBF_NoNode MINUSMINUS
+;
+
+UnaryExprCommon_NoNode:
+ DELETETOKEN UnaryExpr_NoNode
+ | VOIDTOKEN UnaryExpr_NoNode
+ | TYPEOF UnaryExpr_NoNode
+ | PLUSPLUS UnaryExpr_NoNode
+ | AUTOPLUSPLUS UnaryExpr_NoNode
+ | MINUSMINUS UnaryExpr_NoNode
+ | AUTOMINUSMINUS UnaryExpr_NoNode
+ | '+' UnaryExpr_NoNode
+ | '-' UnaryExpr_NoNode
+ | '~' UnaryExpr_NoNode
+ | '!' UnaryExpr_NoNode
+
+UnaryExpr_NoNode:
+ PostfixExpr_NoNode
+ | UnaryExprCommon_NoNode
+;
+
+UnaryExprNoBF_NoNode:
+ PostfixExprNoBF_NoNode
+ | UnaryExprCommon_NoNode
+;
+
+MultiplicativeExpr_NoNode:
+ UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode
+;
+
+MultiplicativeExprNoBF_NoNode:
+ UnaryExprNoBF_NoNode
+ | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode
+ | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode
+ | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode
+;
+
+AdditiveExpr_NoNode:
+ MultiplicativeExpr_NoNode
+ | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode
+ | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+AdditiveExprNoBF_NoNode:
+ MultiplicativeExprNoBF_NoNode
+ | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode
+ | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+ShiftExpr_NoNode:
+ AdditiveExpr_NoNode
+ | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode
+ | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode
+ | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+ShiftExprNoBF_NoNode:
+ AdditiveExprNoBF_NoNode
+ | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode
+ | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode
+ | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+RelationalExpr_NoNode:
+ ShiftExpr_NoNode
+ | RelationalExpr_NoNode '<' ShiftExpr_NoNode
+ | RelationalExpr_NoNode '>' ShiftExpr_NoNode
+ | RelationalExpr_NoNode LE ShiftExpr_NoNode
+ | RelationalExpr_NoNode GE ShiftExpr_NoNode
+ | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode
+ | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+RelationalExprNoIn_NoNode:
+ ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode
+;
+
+RelationalExprNoBF_NoNode:
+ ShiftExprNoBF_NoNode
+ | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+EqualityExpr_NoNode:
+ RelationalExpr_NoNode
+ | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode
+ | EqualityExpr_NoNode NE RelationalExpr_NoNode
+ | EqualityExpr_NoNode STREQ RelationalExpr_NoNode
+ | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+EqualityExprNoIn_NoNode:
+ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode
+;
+
+EqualityExprNoBF_NoNode:
+ RelationalExprNoBF_NoNode
+ | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+BitwiseANDExpr_NoNode:
+ EqualityExpr_NoNode
+ | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode
+;
+
+BitwiseANDExprNoIn_NoNode:
+ EqualityExprNoIn_NoNode
+ | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode
+;
+
+BitwiseANDExprNoBF_NoNode:
+ EqualityExprNoBF_NoNode
+ | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode
+;
+
+BitwiseXORExpr_NoNode:
+ BitwiseANDExpr_NoNode
+ | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseXORExprNoIn_NoNode:
+ BitwiseANDExprNoIn_NoNode
+ | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode
+;
+
+BitwiseXORExprNoBF_NoNode:
+ BitwiseANDExprNoBF_NoNode
+ | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseORExpr_NoNode:
+ BitwiseXORExpr_NoNode
+ | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+BitwiseORExprNoIn_NoNode:
+ BitwiseXORExprNoIn_NoNode
+ | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode
+;
+
+BitwiseORExprNoBF_NoNode:
+ BitwiseXORExprNoBF_NoNode
+ | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+LogicalANDExpr_NoNode:
+ BitwiseORExpr_NoNode
+ | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalANDExprNoIn_NoNode:
+ BitwiseORExprNoIn_NoNode
+ | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode
+;
+
+LogicalANDExprNoBF_NoNode:
+ BitwiseORExprNoBF_NoNode
+ | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalORExpr_NoNode:
+ LogicalANDExpr_NoNode
+ | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode
+;
+
+LogicalORExprNoIn_NoNode:
+ LogicalANDExprNoIn_NoNode
+ | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode
+;
+
+LogicalORExprNoBF_NoNode:
+ LogicalANDExprNoBF_NoNode
+ | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode
+;
+
+ConditionalExpr_NoNode:
+ LogicalORExpr_NoNode
+ | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+ConditionalExprNoIn_NoNode:
+ LogicalORExprNoIn_NoNode
+ | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode
+;
+
+ConditionalExprNoBF_NoNode:
+ LogicalORExprNoBF_NoNode
+ | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+AssignmentExpr_NoNode:
+ ConditionalExpr_NoNode
+ | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentExprNoIn_NoNode:
+ ConditionalExprNoIn_NoNode
+ | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode
+;
+
+AssignmentExprNoBF_NoNode:
+ ConditionalExprNoBF_NoNode
+ | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentOperator_NoNode:
+ '='
+ | PLUSEQUAL
+ | MINUSEQUAL
+ | MULTEQUAL
+ | DIVEQUAL
+ | LSHIFTEQUAL
+ | RSHIFTEQUAL
+ | URSHIFTEQUAL
+ | ANDEQUAL
+ | XOREQUAL
+ | OREQUAL
+ | MODEQUAL
+;
+
+Expr_NoNode:
+ AssignmentExpr_NoNode
+ | Expr_NoNode ',' AssignmentExpr_NoNode
+;
+
+ExprNoIn_NoNode:
+ AssignmentExprNoIn_NoNode
+ | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode
+;
+
+ExprNoBF_NoNode:
+ AssignmentExprNoBF_NoNode
+ | ExprNoBF_NoNode ',' AssignmentExpr_NoNode
+;
+
+Statement_NoNode:
+ Block_NoNode
+ | VariableStatement_NoNode
+ | ConstStatement_NoNode
+ | FunctionDeclaration_NoNode
+ | EmptyStatement_NoNode
+ | ExprStatement_NoNode
+ | IfStatement_NoNode
+ | IterationStatement_NoNode
+ | ContinueStatement_NoNode
+ | BreakStatement_NoNode
+ | ReturnStatement_NoNode
+ | WithStatement_NoNode
+ | SwitchStatement_NoNode
+ | LabelledStatement_NoNode
+ | ThrowStatement_NoNode
+ | TryStatement_NoNode
+ | DebuggerStatement_NoNode
+;
+
+Block_NoNode:
+ OPENBRACE CLOSEBRACE { }
+ | OPENBRACE SourceElements_NoNode CLOSEBRACE { }
+;
+
+VariableStatement_NoNode:
+ VAR VariableDeclarationList_NoNode ';'
+ | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+VariableDeclarationList_NoNode:
+ IDENT { }
+ | IDENT Initializer_NoNode { }
+ | VariableDeclarationList_NoNode ',' IDENT
+ | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode
+;
+
+VariableDeclarationListNoIn_NoNode:
+ IDENT { }
+ | IDENT InitializerNoIn_NoNode { }
+ | VariableDeclarationListNoIn_NoNode ',' IDENT
+ | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode
+;
+
+ConstStatement_NoNode:
+ CONSTTOKEN ConstDeclarationList_NoNode ';'
+ | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+ConstDeclarationList_NoNode:
+ ConstDeclaration_NoNode
+ | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode
+;
+
+ConstDeclaration_NoNode:
+ IDENT { }
+ | IDENT Initializer_NoNode { }
+;
+
+Initializer_NoNode:
+ '=' AssignmentExpr_NoNode
+;
+
+InitializerNoIn_NoNode:
+ '=' AssignmentExprNoIn_NoNode
+;
+
+EmptyStatement_NoNode:
+ ';'
+;
+
+ExprStatement_NoNode:
+ ExprNoBF_NoNode ';'
+ | ExprNoBF_NoNode error { AUTO_SEMICOLON; }
+;
+
+IfStatement_NoNode:
+ IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE
+ | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode
+;
+
+IterationStatement_NoNode:
+ DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';'
+ | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion
+ | WHILE '(' Expr_NoNode ')' Statement_NoNode
+ | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+ | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+ | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+ | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode
+ | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+;
+
+ExprOpt_NoNode:
+ /* nothing */
+ | Expr_NoNode
+;
+
+ExprNoInOpt_NoNode:
+ /* nothing */
+ | ExprNoIn_NoNode
+;
+
+ContinueStatement_NoNode:
+ CONTINUE ';'
+ | CONTINUE error { AUTO_SEMICOLON; }
+ | CONTINUE IDENT ';'
+ | CONTINUE IDENT error { AUTO_SEMICOLON; }
+;
+
+BreakStatement_NoNode:
+ BREAK ';'
+ | BREAK error { AUTO_SEMICOLON; }
+ | BREAK IDENT ';'
+ | BREAK IDENT error { AUTO_SEMICOLON; }
+;
+
+ReturnStatement_NoNode:
+ RETURN ';'
+ | RETURN error { AUTO_SEMICOLON; }
+ | RETURN Expr_NoNode ';'
+ | RETURN Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+WithStatement_NoNode:
+ WITH '(' Expr_NoNode ')' Statement_NoNode
+;
+
+SwitchStatement_NoNode:
+ SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode
+;
+
+CaseBlock_NoNode:
+ OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE { }
+ | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE { }
+;
+
+CaseClausesOpt_NoNode:
+ /* nothing */
+ | CaseClauses_NoNode
+;
+
+CaseClauses_NoNode:
+ CaseClause_NoNode
+ | CaseClauses_NoNode CaseClause_NoNode
+;
+
+CaseClause_NoNode:
+ CASE Expr_NoNode ':'
+ | CASE Expr_NoNode ':' SourceElements_NoNode
+;
+
+DefaultClause_NoNode:
+ DEFAULT ':'
+ | DEFAULT ':' SourceElements_NoNode
+;
+
+LabelledStatement_NoNode:
+ IDENT ':' Statement_NoNode { }
+;
+
+ThrowStatement_NoNode:
+ THROW Expr_NoNode ';'
+ | THROW Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+TryStatement_NoNode:
+ TRY Block_NoNode FINALLY Block_NoNode
+ | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode
+ | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode
+;
+
+DebuggerStatement_NoNode:
+ DEBUGGER ';'
+ | DEBUGGER error { AUTO_SEMICOLON; }
+;
+
+FunctionDeclaration_NoNode:
+ FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FunctionExpr_NoNode:
+ FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FormalParameterList_NoNode:
+ IDENT { }
+ | FormalParameterList_NoNode ',' IDENT
+;
+
+FunctionBody_NoNode:
+ /* not in spec */
+ | SourceElements_NoNode
+;
+
+SourceElements_NoNode:
+ Statement_NoNode
+ | SourceElements_NoNode Statement_NoNode
+;
+
+// End NoNodes
+
+%%
+
+static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+{
+ if (!loc->isLocation())
+ return new AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot);
+
+ if (loc->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(loc);
+ if (op == OpEqual) {
+ AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments);
+ SET_EXCEPTION_LOCATION(node, start, divot, end);
+ return node;
+ } else
+ return new ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ }
+ if (loc->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
+ if (op == OpEqual)
+ return new AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+ else {
+ ReadModifyBracketNode* node = new ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return node;
+ }
+ }
+ ASSERT(loc->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
+ if (op == OpEqual)
+ return new AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+
+ ReadModifyDotNode* node = new ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PrefixBracketNode* node = new PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
+ return node;
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ PrefixDotNode* node = new PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->startOffset());
+ return node;
+}
+
+static ExpressionNode* makePostfixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PostfixBracketNode* node = new PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return node;
+
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ PostfixDotNode* node = new PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+static ExpressionNodeInfo makeFunctionCallNode(void* globalPtr, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
+{
+ CodeFeatures features = func.m_features | args.m_features;
+ int numConstants = func.m_numConstants + args.m_numConstants;
+ if (!func.m_node->isLocation())
+ return createNodeInfo<ExpressionNode*>(new FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
+ if (func.m_node->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
+ const Identifier& identifier = resolve->identifier();
+ if (identifier == GLOBAL_DATA->propertyNames->eval)
+ return createNodeInfo<ExpressionNode*>(new EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
+ return createNodeInfo<ExpressionNode*>(new FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
+ }
+ if (func.m_node->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
+ FunctionCallBracketNode* node = new FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return createNodeInfo<ExpressionNode*>(node, features, numConstants);
+ }
+ ASSERT(func.m_node->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
+ FunctionCallDotNode* node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return createNodeInfo<ExpressionNode*>(node, features, numConstants);
+}
+
+static ExpressionNode* makeTypeOfNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
+ }
+ return new TypeOfValueNode(GLOBAL_DATA, expr);
+}
+
+static ExpressionNode* makeDeleteNode(void* globalPtr, ExpressionNode* expr, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new DeleteValueNode(GLOBAL_DATA, expr);
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ return new DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ return new DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot);
+}
+
+static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
+{
+ PropertyNode::Type type;
+ if (getOrSet == "get")
+ type = PropertyNode::Getter;
+ else if (getOrSet == "set")
+ type = PropertyNode::Setter;
+ else
+ return 0;
+ return new PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
+}
+
+static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
+{
+ if (n->isNumber()) {
+ NumberNode* number = static_cast<NumberNode*>(n);
+
+ if (number->value() > 0.0) {
+ number->setValue(-number->value());
+ return number;
+ }
+ }
+
+ return new NegateNode(GLOBAL_DATA, n);
+}
+
+static NumberNode* makeNumberNode(void* globalPtr, double d)
+{
+ return new NumberNode(GLOBAL_DATA, d);
+}
+
+static ExpressionNode* makeBitwiseNotNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (expr->isNumber())
+ return makeNumberNode(globalPtr, ~toInt32(static_cast<NumberNode*>(expr)->value()));
+ return new BitwiseNotNode(GLOBAL_DATA, expr);
+}
+
+static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+
+ if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
+ return new UnaryPlusNode(GLOBAL_DATA, expr2);
+
+ if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
+ return new UnaryPlusNode(GLOBAL_DATA, expr1);
+
+ return new MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+ return new DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeAddNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+ return new AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+ return new SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeLeftShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeRightShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+/* called by yyparse on error */
+int yyerror(const char *)
+{
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
+{
+ return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
+}
+
+static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* list, AssignResolveNode* init)
+{
+ if (!list)
+ return init;
+ return new VarDeclCommaNode(GLOBAL_DATA, list, init);
+}
+
+// We turn variable declarations into either assignments or empty
+// statements (which later get stripped out), because the actual
+// declaration work is hoisted up to the start of the function body
+static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (!expr)
+ return new EmptyStatementNode(GLOBAL_DATA);
+ return new VarStatementNode(GLOBAL_DATA, expr);
+}
+
+#undef GLOBAL_DATA
--- /dev/null
+# main keywords
+@begin mainTable 41
+
+# types
+null NULLTOKEN
+true TRUETOKEN
+false FALSETOKEN
+
+# keywords
+break BREAK
+case CASE
+catch CATCH
+const CONSTTOKEN
+default DEFAULT
+finally FINALLY
+for FOR
+instanceof INSTANCEOF
+new NEW
+var VAR
+continue CONTINUE
+function FUNCTION
+return RETURN
+void VOIDTOKEN
+delete DELETETOKEN
+if IF
+this THISTOKEN
+do DO
+while WHILE
+else ELSE
+in INTOKEN
+switch SWITCH
+throw THROW
+try TRY
+typeof TYPEOF
+with WITH
+debugger DEBUGGER
+
+# reserved for future use
+class RESERVED
+enum RESERVED
+export RESERVED
+extends RESERVED
+import RESERVED
+super RESERVED
+
+# these words are reserved for future use in the ECMA spec, but not in WinIE
+# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
+# abstract RESERVED
+# boolean RESERVED
+# byte RESERVED
+# char RESERVED
+# double RESERVED
+# final RESERVED
+# float RESERVED
+# goto RESERVED
+# implements RESERVED
+# int RESERVED
+# interface RESERVED
+# long RESERVED
+# native RESERVED
+# package RESERVED
+# private RESERVED
+# protected RESERVED
+# public RESERVED
+# short RESERVED
+# static RESERVED
+# synchronized RESERVED
+# throws RESERVED
+# transient RESERVED
+# volatile RESERVED
+@end
+
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Lexer.h"
+
+#include "JSFunction.h"
+#include "JSGlobalObjectFunctions.h"
+#include "NodeInfo.h"
+#include "Nodes.h"
+#include "dtoa.h"
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/unicode/Unicode.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+// we can't specify the namespace in yacc's C output, so do it here
+using namespace JSC;
+
+#ifndef KDE_USE_FINAL
+#include "Grammar.h"
+#endif
+
+#include "Lookup.h"
+#include "Lexer.lut.h"
+
+// a bridge for yacc from the C world to C++
+int jscyylex(void* lvalp, void* llocp, void* globalData)
+{
+ return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
+}
+
+namespace JSC {
+
+static bool isDecimalDigit(int);
+
+Lexer::Lexer(JSGlobalData* globalData)
+ : yylineno(1)
+ , m_restrKeyword(false)
+ , m_eatNextIdentifier(false)
+ , m_stackToken(-1)
+ , m_lastToken(-1)
+ , m_position(0)
+ , m_code(0)
+ , m_length(0)
+ , m_isReparsing(false)
+ , m_atLineStart(true)
+ , m_current(0)
+ , m_next1(0)
+ , m_next2(0)
+ , m_next3(0)
+ , m_currentOffset(0)
+ , m_nextOffset1(0)
+ , m_nextOffset2(0)
+ , m_nextOffset3(0)
+ , m_globalData(globalData)
+ , m_mainTable(JSC::mainTable)
+{
+ m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
+ m_buffer16.reserveInitialCapacity(initialReadBufferCapacity);
+}
+
+Lexer::~Lexer()
+{
+ m_mainTable.deleteTable();
+}
+
+void Lexer::setCode(const SourceCode& source)
+{
+ yylineno = source.firstLine();
+ m_restrKeyword = false;
+ m_delimited = false;
+ m_eatNextIdentifier = false;
+ m_stackToken = -1;
+ m_lastToken = -1;
+
+ m_position = source.startOffset();
+ m_source = &source;
+ m_code = source.provider()->data();
+ m_length = source.endOffset();
+ m_skipLF = false;
+ m_skipCR = false;
+ m_error = false;
+ m_atLineStart = true;
+
+ // read first characters
+ shift(4);
+}
+
+void Lexer::shift(unsigned p)
+{
+ // ECMA-262 calls for stripping Cf characters here, but we only do this for BOM,
+ // see <https://bugs.webkit.org/show_bug.cgi?id=4931>.
+
+ while (p--) {
+ m_current = m_next1;
+ m_next1 = m_next2;
+ m_next2 = m_next3;
+ m_currentOffset = m_nextOffset1;
+ m_nextOffset1 = m_nextOffset2;
+ m_nextOffset2 = m_nextOffset3;
+ do {
+ if (m_position >= m_length) {
+ m_nextOffset3 = m_position;
+ m_position++;
+ m_next3 = -1;
+ break;
+ }
+ m_nextOffset3 = m_position;
+ m_next3 = m_code[m_position++];
+ } while (m_next3 == 0xFEFF);
+ }
+}
+
+// called on each new line
+void Lexer::nextLine()
+{
+ yylineno++;
+ m_atLineStart = true;
+}
+
+void Lexer::setDone(State s)
+{
+ m_state = s;
+ m_done = true;
+}
+
+int Lexer::lex(void* p1, void* p2)
+{
+ YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
+ YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
+ int token = 0;
+ m_state = Start;
+ unsigned short stringType = 0; // either single or double quotes
+ m_buffer8.clear();
+ m_buffer16.clear();
+ m_done = false;
+ m_terminator = false;
+ m_skipLF = false;
+ m_skipCR = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (m_stackToken >= 0) {
+ setDone(Other);
+ token = m_stackToken;
+ m_stackToken = 0;
+ }
+ int startOffset = m_currentOffset;
+ while (!m_done) {
+ if (m_skipLF && m_current != '\n') // found \r but not \n afterwards
+ m_skipLF = false;
+ if (m_skipCR && m_current != '\r') // found \n but not \r afterwards
+ m_skipCR = false;
+ if (m_skipLF || m_skipCR) { // found \r\n or \n\r -> eat the second one
+ m_skipLF = false;
+ m_skipCR = false;
+ shift(1);
+ }
+ switch (m_state) {
+ case Start:
+ startOffset = m_currentOffset;
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (m_current == '/' && m_next1 == '/') {
+ shift(1);
+ m_state = InSingleLineComment;
+ } else if (m_current == '/' && m_next1 == '*') {
+ shift(1);
+ m_state = InMultiLineComment;
+ } else if (m_current == -1) {
+ if (!m_terminator && !m_delimited && !m_isReparsing) {
+ // automatic semicolon insertion if program incomplete
+ token = ';';
+ m_stackToken = 0;
+ setDone(Other);
+ } else
+ setDone(Eof);
+ } else if (isLineTerminator()) {
+ nextLine();
+ m_terminator = true;
+ if (m_restrKeyword) {
+ token = ';';
+ setDone(Other);
+ }
+ } else if (m_current == '"' || m_current == '\'') {
+ m_state = InString;
+ stringType = static_cast<unsigned short>(m_current);
+ } else if (isIdentStart(m_current)) {
+ record16(m_current);
+ m_state = InIdentifierOrKeyword;
+ } else if (m_current == '\\')
+ m_state = InIdentifierStartUnicodeEscapeStart;
+ else if (m_current == '0') {
+ record8(m_current);
+ m_state = InNum0;
+ } else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InNum;
+ } else if (m_current == '.' && isDecimalDigit(m_next1)) {
+ record8(m_current);
+ m_state = InDecimal;
+ // <!-- marks the beginning of a line comment (for www usage)
+ } else if (m_current == '<' && m_next1 == '!' && m_next2 == '-' && m_next3 == '-') {
+ shift(3);
+ m_state = InSingleLineComment;
+ // same for -->
+ } else if (m_atLineStart && m_current == '-' && m_next1 == '-' && m_next2 == '>') {
+ shift(2);
+ m_state = InSingleLineComment;
+ } else {
+ token = matchPunctuator(lvalp->intValue, m_current, m_next1, m_next2, m_next3);
+ if (token != -1)
+ setDone(Other);
+ else
+ setDone(Bad);
+ }
+ break;
+ case InString:
+ if (m_current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator() || m_current == -1)
+ setDone(Bad);
+ else if (m_current == '\\')
+ m_state = InEscapeSequence;
+ else
+ record16(m_current);
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(m_current)) {
+ if (m_current >= '0' && m_current <= '3' &&
+ isOctalDigit(m_next1) && isOctalDigit(m_next2)) {
+ record16(convertOctal(m_current, m_next1, m_next2));
+ shift(2);
+ m_state = InString;
+ } else if (isOctalDigit(m_current) && isOctalDigit(m_next1)) {
+ record16(convertOctal('0', m_current, m_next1));
+ shift(1);
+ m_state = InString;
+ } else if (isOctalDigit(m_current)) {
+ record16(convertOctal('0', '0', m_current));
+ m_state = InString;
+ } else
+ setDone(Bad);
+ } else if (m_current == 'x')
+ m_state = InHexEscape;
+ else if (m_current == 'u')
+ m_state = InUnicodeEscape;
+ else if (isLineTerminator()) {
+ nextLine();
+ m_state = InString;
+ } else {
+ record16(singleEscape(static_cast<unsigned short>(m_current)));
+ m_state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(m_current) && isHexDigit(m_next1)) {
+ m_state = InString;
+ record16(convertHex(m_current, m_next1));
+ shift(1);
+ } else if (m_current == stringType) {
+ record16('x');
+ shift(1);
+ setDone(String);
+ } else {
+ record16('x');
+ record16(m_current);
+ m_state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(m_current) && isHexDigit(m_next1) && isHexDigit(m_next2) && isHexDigit(m_next3)) {
+ record16(convertUnicode(m_current, m_next1, m_next2, m_next3));
+ shift(3);
+ m_state = InString;
+ } else if (m_current == stringType) {
+ record16('u');
+ shift(1);
+ setDone(String);
+ } else
+ setDone(Bad);
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ nextLine();
+ m_terminator = true;
+ if (m_restrKeyword) {
+ token = ';';
+ setDone(Other);
+ } else
+ m_state = Start;
+ } else if (m_current == -1)
+ setDone(Eof);
+ break;
+ case InMultiLineComment:
+ if (m_current == -1)
+ setDone(Bad);
+ else if (isLineTerminator())
+ nextLine();
+ else if (m_current == '*' && m_next1 == '/') {
+ m_state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifierOrKeyword:
+ case InIdentifier:
+ if (isIdentPart(m_current))
+ record16(m_current);
+ else if (m_current == '\\')
+ m_state = InIdentifierPartUnicodeEscapeStart;
+ else
+ setDone(m_state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
+ break;
+ case InNum0:
+ if (m_current == 'x' || m_current == 'X') {
+ record8(m_current);
+ m_state = InHex;
+ } else if (m_current == '.') {
+ record8(m_current);
+ m_state = InDecimal;
+ } else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else if (isOctalDigit(m_current)) {
+ record8(m_current);
+ m_state = InOctal;
+ } else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InDecimal;
+ } else
+ setDone(Number);
+ break;
+ case InHex:
+ if (isHexDigit(m_current))
+ record8(m_current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(m_current))
+ record8(m_current);
+ else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InDecimal;
+ } else
+ setDone(Octal);
+ break;
+ case InNum:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else if (m_current == '.') {
+ record8(m_current);
+ m_state = InDecimal;
+ } else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InDecimal:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InExponentIndicator:
+ if (m_current == '+' || m_current == '-')
+ record8(m_current);
+ else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InExponent;
+ } else
+ setDone(Bad);
+ break;
+ case InExponent:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else
+ setDone(Number);
+ break;
+ case InIdentifierStartUnicodeEscapeStart:
+ if (m_current == 'u')
+ m_state = InIdentifierStartUnicodeEscape;
+ else
+ setDone(Bad);
+ break;
+ case InIdentifierPartUnicodeEscapeStart:
+ if (m_current == 'u')
+ m_state = InIdentifierPartUnicodeEscape;
+ else
+ setDone(Bad);
+ break;
+ case InIdentifierStartUnicodeEscape:
+ if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
+ setDone(Bad);
+ break;
+ }
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ shift(3);
+ if (!isIdentStart(token)) {
+ setDone(Bad);
+ break;
+ }
+ record16(token);
+ m_state = InIdentifier;
+ break;
+ case InIdentifierPartUnicodeEscape:
+ if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
+ setDone(Bad);
+ break;
+ }
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ shift(3);
+ if (!isIdentPart(token)) {
+ setDone(Bad);
+ break;
+ }
+ record16(token);
+ m_state = InIdentifier;
+ break;
+ default:
+ ASSERT(!"Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!m_done)
+ shift(1);
+ if (m_state != Start && m_state != InSingleLineComment)
+ m_atLineStart = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((m_state == Number || m_state == Octal || m_state == Hex) && isIdentStart(m_current))
+ m_state = Bad;
+
+ // terminate string
+ m_buffer8.append('\0');
+
+#ifdef JSC_DEBUG_LEX
+ fprintf(stderr, "line: %d ", lineNo());
+ fprintf(stderr, "yytext (%x): ", m_buffer8[0]);
+ fprintf(stderr, "%s ", m_buffer8.data());
+#endif
+
+ double dval = 0;
+ if (m_state == Number)
+ dval = WTF::strtod(m_buffer8.data(), 0L);
+ else if (m_state == Hex) { // scan hex numbers
+ const char* p = m_buffer8.data() + 2;
+ while (char c = *p++) {
+ dval *= 16;
+ dval += convertHex(c);
+ }
+
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16);
+
+ m_state = Number;
+ } else if (m_state == Octal) { // scan octal number
+ const char* p = m_buffer8.data() + 1;
+ while (char c = *p++) {
+ dval *= 8;
+ dval += c - '0';
+ }
+
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8);
+
+ m_state = Number;
+ }
+
+#ifdef JSC_DEBUG_LEX
+ switch (m_state) {
+ case Eof:
+ printf("(EOF)\n");
+ break;
+ case Other:
+ printf("(Other)\n");
+ break;
+ case Identifier:
+ printf("(Identifier)/(Keyword)\n");
+ break;
+ case String:
+ printf("(String)\n");
+ break;
+ case Number:
+ printf("(Number)\n");
+ break;
+ default:
+ printf("(unknown)");
+ }
+#endif
+
+ if (m_state != Identifier)
+ m_eatNextIdentifier = false;
+
+ m_restrKeyword = false;
+ m_delimited = false;
+ llocp->first_line = yylineno;
+ llocp->last_line = yylineno;
+ llocp->first_column = startOffset;
+ llocp->last_column = m_currentOffset;
+ switch (m_state) {
+ case Eof:
+ token = 0;
+ break;
+ case Other:
+ if (token == '}' || token == ';')
+ m_delimited = true;
+ break;
+ case Identifier:
+ // Apply anonymous-function hack below (eat the identifier).
+ if (m_eatNextIdentifier) {
+ m_eatNextIdentifier = false;
+ token = lex(lvalp, llocp);
+ break;
+ }
+ lvalp->ident = makeIdentifier(m_buffer16);
+ token = IDENT;
+ break;
+ case IdentifierOrKeyword: {
+ lvalp->ident = makeIdentifier(m_buffer16);
+ const HashEntry* entry = m_mainTable.entry(m_globalData, *lvalp->ident);
+ if (!entry) {
+ // Lookup for keyword failed, means this is an identifier.
+ token = IDENT;
+ break;
+ }
+ token = entry->lexerValue();
+ // Hack for "f = function somename() { ... }"; too hard to get into the grammar.
+ m_eatNextIdentifier = token == FUNCTION && m_lastToken == '=';
+ if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW)
+ m_restrKeyword = true;
+ break;
+ }
+ case String:
+ // Atomize constant strings in case they're later used in property lookup.
+ lvalp->ident = makeIdentifier(m_buffer16);
+ token = STRING;
+ break;
+ case Number:
+ lvalp->doubleValue = dval;
+ token = NUMBER;
+ break;
+ case Bad:
+#ifdef JSC_DEBUG_LEX
+ fprintf(stderr, "yylex: ERROR.\n");
+#endif
+ m_error = true;
+ return -1;
+ default:
+ ASSERT(!"unhandled numeration value in switch");
+ m_error = true;
+ return -1;
+ }
+ m_lastToken = token;
+ return token;
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return m_current == '\t' || m_current == 0x0b || m_current == 0x0c || isSeparatorSpace(m_current);
+}
+
+bool Lexer::isLineTerminator()
+{
+ bool cr = (m_current == '\r');
+ bool lf = (m_current == '\n');
+ if (cr)
+ m_skipLF = true;
+ else if (lf)
+ m_skipCR = true;
+ return cr || lf || m_current == 0x2028 || m_current == 0x2029;
+}
+
+bool Lexer::isIdentStart(int c)
+{
+ return isASCIIAlpha(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)));
+}
+
+bool Lexer::isIdentPart(int c)
+{
+ return isASCIIAlphanumeric(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
+ | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)));
+}
+
+static bool isDecimalDigit(int c)
+{
+ return isASCIIDigit(c);
+}
+
+bool Lexer::isHexDigit(int c)
+{
+ return isASCIIHexDigit(c);
+}
+
+bool Lexer::isOctalDigit(int c)
+{
+ return isASCIIOctalDigit(c);
+}
+
+int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return URSHIFTEQUAL;
+ }
+ if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STREQ;
+ }
+ if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STRNEQ;
+ }
+ if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return URSHIFT;
+ }
+ if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return LSHIFTEQUAL;
+ }
+ if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return RSHIFTEQUAL;
+ }
+ if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return LE;
+ }
+ if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return GE;
+ }
+ if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return NE;
+ }
+ if (c1 == '+' && c2 == '+') {
+ shift(2);
+ if (m_terminator)
+ return AUTOPLUSPLUS;
+ return PLUSPLUS;
+ }
+ if (c1 == '-' && c2 == '-') {
+ shift(2);
+ if (m_terminator)
+ return AUTOMINUSMINUS;
+ return MINUSMINUS;
+ }
+ if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return EQEQ;
+ }
+ if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return PLUSEQUAL;
+ }
+ if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return MINUSEQUAL;
+ }
+ if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return MULTEQUAL;
+ }
+ if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return DIVEQUAL;
+ }
+ if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return ANDEQUAL;
+ }
+ if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return XOREQUAL;
+ }
+ if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return MODEQUAL;
+ }
+ if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return OREQUAL;
+ }
+ if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return LSHIFT;
+ }
+ if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return RSHIFT;
+ }
+ if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return AND;
+ }
+ if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return OR;
+ }
+
+ switch (c1) {
+ case '=':
+ case '>':
+ case '<':
+ case ',':
+ case '!':
+ case '~':
+ case '?':
+ case ':':
+ case '.':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '&':
+ case '|':
+ case '^':
+ case '%':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case ';':
+ shift(1);
+ return static_cast<int>(c1);
+ case '{':
+ charPos = m_currentOffset;
+ shift(1);
+ return OPENBRACE;
+ case '}':
+ charPos = m_currentOffset;
+ shift(1);
+ return CLOSEBRACE;
+ default:
+ return -1;
+ }
+}
+
+unsigned short Lexer::singleEscape(unsigned short c)
+{
+ switch (c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+unsigned short Lexer::convertOctal(int c1, int c2, int c3)
+{
+ return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(int c)
+{
+ if (c >= '0' && c <= '9')
+ return static_cast<unsigned char>(c - '0');
+ if (c >= 'a' && c <= 'f')
+ return static_cast<unsigned char>(c - 'a' + 10);
+ return static_cast<unsigned char>(c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(int c1, int c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
+{
+ unsigned char highByte = (convertHex(c1) << 4) + convertHex(c2);
+ unsigned char lowByte = (convertHex(c3) << 4) + convertHex(c4);
+ return (highByte << 8 | lowByte);
+}
+
+void Lexer::record8(int c)
+{
+ ASSERT(c >= 0);
+ ASSERT(c <= 0xff);
+ m_buffer8.append(static_cast<char>(c));
+}
+
+void Lexer::record16(int c)
+{
+ ASSERT(c >= 0);
+ ASSERT(c <= USHRT_MAX);
+ record16(UChar(static_cast<unsigned short>(c)));
+}
+
+void Lexer::record16(UChar c)
+{
+ m_buffer16.append(c);
+}
+
+bool Lexer::scanRegExp()
+{
+ m_buffer16.clear();
+ bool lastWasEscape = false;
+ bool inBrackets = false;
+
+ while (1) {
+ if (isLineTerminator() || m_current == -1)
+ return false;
+ else if (m_current != '/' || lastWasEscape == true || inBrackets == true) {
+ // 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);
+ m_buffer16.clear();
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ while (isIdentPart(m_current)) {
+ record16(m_current);
+ shift(1);
+ }
+ m_flags = UString(m_buffer16);
+
+ return true;
+}
+
+void Lexer::clear()
+{
+ m_identifiers.clear();
+
+ Vector<char> newBuffer8;
+ newBuffer8.reserveInitialCapacity(initialReadBufferCapacity);
+ m_buffer8.swap(newBuffer8);
+
+ Vector<UChar> newBuffer16;
+ newBuffer16.reserveInitialCapacity(initialReadBufferCapacity);
+ m_buffer16.swap(newBuffer16);
+
+ m_isReparsing = false;
+
+ m_pattern = 0;
+ m_flags = 0;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Lexer_h
+#define Lexer_h
+
+#include "Identifier.h"
+#include "Lookup.h"
+#include "SegmentedVector.h"
+#include "SourceCode.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class RegExp;
+
+ class Lexer : Noncopyable {
+ public:
+ void setCode(const SourceCode&);
+ void setIsReparsing() { m_isReparsing = true; }
+ int lex(void* lvalp, void* llocp);
+
+ int lineNo() const { return yylineno; }
+
+ bool prevTerminator() const { return m_terminator; }
+
+ enum State {
+ Start,
+ IdentifierOrKeyword,
+ Identifier,
+ InIdentifierOrKeyword,
+ InIdentifier,
+ InIdentifierStartUnicodeEscapeStart,
+ InIdentifierStartUnicodeEscape,
+ InIdentifierPartUnicodeEscapeStart,
+ InIdentifierPartUnicodeEscape,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad
+ };
+
+ bool scanRegExp();
+ const UString& pattern() const { return m_pattern; }
+ const UString& flags() const { return m_flags; }
+
+ static unsigned char convertHex(int);
+ static unsigned char convertHex(int c1, int c2);
+ static UChar convertUnicode(int c1, int c2, int c3, int c4);
+ static bool isIdentStart(int);
+ static bool isIdentPart(int);
+ static bool isHexDigit(int);
+
+ bool sawError() const { return m_error; }
+
+ void clear();
+ SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); }
+
+ private:
+ friend class JSGlobalData;
+ Lexer(JSGlobalData*);
+ ~Lexer();
+
+ void setDone(State);
+ void shift(unsigned int p);
+ void nextLine();
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator();
+ static bool isOctalDigit(int);
+
+ ALWAYS_INLINE int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);
+ static unsigned short singleEscape(unsigned short);
+ static unsigned short convertOctal(int c1, int c2, int c3);
+
+ void record8(int);
+ void record16(int);
+ void record16(UChar);
+
+ JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer)
+ {
+ m_identifiers.append(JSC::Identifier(m_globalData, buffer.data(), buffer.size()));
+ return &m_identifiers.last();
+ }
+
+ static const size_t initialReadBufferCapacity = 32;
+ static const size_t initialIdentifierTableCapacity = 64;
+
+ int yylineno;
+ int yycolumn;
+
+ bool m_done;
+ Vector<char> m_buffer8;
+ Vector<UChar> m_buffer16;
+ bool m_terminator;
+ bool m_restrKeyword;
+ bool m_delimited; // encountered delimiter like "'" and "}" on last run
+ bool m_skipLF;
+ bool m_skipCR;
+ bool m_eatNextIdentifier;
+ int m_stackToken;
+ int m_lastToken;
+
+ State m_state;
+ unsigned int m_position;
+ const SourceCode* m_source;
+ const UChar* m_code;
+ unsigned int m_length;
+ bool m_isReparsing;
+ int m_atLineStart;
+ bool m_error;
+
+ // current and following unicode characters (int to allow for -1 for end-of-file marker)
+ int m_current;
+ int m_next1;
+ int m_next2;
+ int m_next3;
+
+ int m_currentOffset;
+ int m_nextOffset1;
+ int m_nextOffset2;
+ int m_nextOffset3;
+
+ SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
+
+ JSGlobalData* m_globalData;
+
+ UString m_pattern;
+ UString m_flags;
+
+ const HashTable m_mainTable;
+ };
+
+} // namespace JSC
+
+#endif // Lexer_h
--- /dev/null
+/*
+ * Copyright (C) 2007 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NodeInfo_h
+#define NodeInfo_h
+
+#include "Nodes.h"
+#include "Parser.h"
+
+namespace JSC {
+
+ template <typename T> struct NodeInfo {
+ T m_node;
+ CodeFeatures m_features;
+ int m_numConstants;
+ };
+
+ typedef NodeInfo<FuncDeclNode*> FuncDeclNodeInfo;
+ typedef NodeInfo<FuncExprNode*> FuncExprNodeInfo;
+ typedef NodeInfo<ExpressionNode*> ExpressionNodeInfo;
+ typedef NodeInfo<ArgumentsNode*> ArgumentsNodeInfo;
+ typedef NodeInfo<ConstDeclNode*> ConstDeclNodeInfo;
+ typedef NodeInfo<PropertyNode*> PropertyNodeInfo;
+ typedef NodeInfo<PropertyList> PropertyListInfo;
+ typedef NodeInfo<ElementList> ElementListInfo;
+ typedef NodeInfo<ArgumentList> ArgumentListInfo;
+
+ template <typename T> struct NodeDeclarationInfo {
+ T m_node;
+ ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ CodeFeatures m_features;
+ int m_numConstants;
+ };
+
+ typedef NodeDeclarationInfo<StatementNode*> StatementNodeInfo;
+ typedef NodeDeclarationInfo<CaseBlockNode*> CaseBlockNodeInfo;
+ typedef NodeDeclarationInfo<CaseClauseNode*> CaseClauseNodeInfo;
+ typedef NodeDeclarationInfo<SourceElements*> SourceElementsInfo;
+ typedef NodeDeclarationInfo<ClauseList> ClauseListInfo;
+ typedef NodeDeclarationInfo<ExpressionNode*> VarDeclListInfo;
+ typedef NodeDeclarationInfo<ConstDeclList> ConstDeclListInfo;
+ typedef NodeDeclarationInfo<ParameterList> ParameterListInfo;
+
+} // namespace JSC
+
+#endif // NodeInfo_h
--- /dev/null
+/*
+* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+* Copyright (C) 2001 Peter Kelly (pmk@post.com)
+* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+* Copyright (C) 2007 Maks Orlovich
+* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public License
+* along with this library; see the file COPYING.LIB. If not, write to
+* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+* Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "config.h"
+#include "Nodes.h"
+
+#include "BytecodeGenerator.h"
+#include "CallFrame.h"
+#include "JSGlobalObject.h"
+#include "JSStaticScopeObject.h"
+#include "LabelScope.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "RegExpObject.h"
+#include "SamplingTool.h"
+#include "Debugger.h"
+#include "Lexer.h"
+#include "Operations.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/Threading.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
+
+// ------------------------------ NodeReleaser --------------------------------
+
+class NodeReleaser : Noncopyable {
+public:
+ // Call this function inside the destructor of a class derived from Node.
+ // This will traverse the tree below this node, destroying all of those nodes,
+ // but without relying on recursion.
+ static void releaseAllNodes(ParserRefCounted* root);
+
+ // Call this on each node in a the releaseNodes virtual function.
+ // It gives the node to the NodeReleaser, which will then release the
+ // node later at the end of the releaseAllNodes process.
+ template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); }
+ void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); }
+
+private:
+ NodeReleaser() { }
+ ~NodeReleaser() { }
+
+ void adopt(PassRefPtr<ParserRefCounted>);
+ void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&);
+
+ typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector;
+ OwnPtr<NodeReleaseVector> m_vector;
+};
+
+void NodeReleaser::releaseAllNodes(ParserRefCounted* root)
+{
+ ASSERT(root);
+ NodeReleaser releaser;
+ root->releaseNodes(releaser);
+ if (!releaser.m_vector)
+ return;
+ // Note: The call to release.m_vector->size() is intentionally inside
+ // the loop, since calls to releaseNodes are expected to increase the size.
+ for (size_t i = 0; i < releaser.m_vector->size(); ++i) {
+ ParserRefCounted* node = (*releaser.m_vector)[i].get();
+ if (node->hasOneRef())
+ node->releaseNodes(releaser);
+ }
+}
+
+void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node)
+{
+ ASSERT(node);
+ if (!node->hasOneRef())
+ return;
+ if (!m_vector)
+ m_vector.set(new NodeReleaseVector);
+ m_vector->append(node);
+}
+
+void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode)
+{
+ // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode>
+ // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode
+ // and ParserRefCounted) unbalanced. It would be nice to fix this problem in
+ // a cleaner way -- perhaps we could remove the FunctionBodyNode reference
+ // count at some point.
+ RefPtr<Node> node = functionBodyNode;
+ functionBodyNode = 0;
+ adopt(node.release());
+}
+
+// ------------------------------ ParserRefCounted -----------------------------------------
+
+#ifndef NDEBUG
+static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
+#endif
+
+ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
+ : m_globalData(globalData)
+{
+#ifndef NDEBUG
+ parserRefCountedCounter.increment();
+#endif
+ if (!m_globalData->newParserObjects)
+ m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
+ m_globalData->newParserObjects->add(this);
+ ASSERT(m_globalData->newParserObjects->contains(this));
+}
+
+ParserRefCounted::~ParserRefCounted()
+{
+#ifndef NDEBUG
+ parserRefCountedCounter.decrement();
+#endif
+}
+
+void ParserRefCounted::releaseNodes(NodeReleaser&)
+{
+}
+
+void ParserRefCounted::ref()
+{
+ // bumping from 0 to 1 is just removing from the new nodes set
+ if (m_globalData->newParserObjects) {
+ HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
+ if (it != m_globalData->newParserObjects->end()) {
+ m_globalData->newParserObjects->remove(it);
+ ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
+ return;
+ }
+ }
+
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts)
+ m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
+ m_globalData->parserObjectExtraRefCounts->add(this);
+}
+
+void ParserRefCounted::deref()
+{
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts) {
+ delete this;
+ return;
+ }
+
+ HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
+ if (it == m_globalData->parserObjectExtraRefCounts->end())
+ delete this;
+ else
+ m_globalData->parserObjectExtraRefCounts->remove(it);
+}
+
+bool ParserRefCounted::hasOneRef()
+{
+ if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
+ ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
+ return false;
+ }
+
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts)
+ return true;
+
+ return !m_globalData->parserObjectExtraRefCounts->contains(this);
+}
+
+void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
+{
+ if (!globalData->newParserObjects)
+ return;
+
+#ifndef NDEBUG
+ HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
+ for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
+ ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
+#endif
+ deleteAllValues(*globalData->newParserObjects);
+ delete globalData->newParserObjects;
+ globalData->newParserObjects = 0;
+}
+
+// ------------------------------ Node --------------------------------
+
+Node::Node(JSGlobalData* globalData)
+ : ParserRefCounted(globalData)
+{
+ m_line = globalData->lexer->lineNo();
+}
+
+// ------------------------------ ThrowableExpressionData --------------------------------
+
+static void substitute(UString& string, const UString& substring)
+{
+ int position = string.find("%s");
+ ASSERT(position != -1);
+ UString newString = string.substr(0, position);
+ newString.append(substring);
+ newString.append(string.substr(position + 2));
+ string = newString;
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg)
+{
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
+ generator.emitThrow(exception);
+ return exception;
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
+{
+ UString message = msg;
+ substitute(message, label.ustring());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
+ generator.emitThrow(exception);
+ return exception;
+}
+
+// ------------------------------ StatementNode --------------------------------
+
+StatementNode::StatementNode(JSGlobalData* globalData)
+ : Node(globalData)
+ , m_lastLine(-1)
+{
+}
+
+void StatementNode::setLoc(int firstLine, int lastLine)
+{
+ m_line = firstLine;
+ m_lastLine = lastLine;
+}
+
+// ------------------------------ SourceElements --------------------------------
+
+void SourceElements::append(PassRefPtr<StatementNode> statement)
+{
+ if (statement->isEmptyStatement())
+ return;
+
+ m_statements.append(statement);
+}
+
+// ------------------------------ NullNode -------------------------------------
+
+RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, jsNull());
+}
+
+// ------------------------------ BooleanNode ----------------------------------
+
+RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ NumberNode -----------------------------------
+
+RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_double);
+}
+
+// ------------------------------ StringNode -----------------------------------
+
+RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ RegExpNode -----------------------------------
+
+RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
+ if (!regExp->isValid())
+ return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
+}
+
+// ------------------------------ ThisNode -------------------------------------
+
+RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
+}
+
+// ------------------------------ ResolveNode ----------------------------------
+
+bool ResolveNode::isPure(BytecodeGenerator& generator) const
+{
+ return generator.isLocal(m_ident);
+}
+
+RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
+ return generator.emitResolve(generator.finalDestination(dst), m_ident);
+}
+
+// ------------------------------ ElementNode ------------------------------------
+
+ElementNode::~ElementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ElementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_node);
+}
+
+// ------------------------------ ArrayNode ------------------------------------
+
+ArrayNode::~ArrayNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArrayNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_element);
+}
+
+RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ // FIXME: Should we put all of this code into emitNewArray?
+
+ unsigned length = 0;
+ ElementNode* firstPutElement;
+ for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
+ if (firstPutElement->elision())
+ break;
+ ++length;
+ }
+
+ if (!firstPutElement && !m_elision)
+ return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
+
+ RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
+
+ for (ElementNode* n = firstPutElement; n; n = n->next()) {
+ RegisterID* value = generator.emitNode(n->value());
+ length += n->elision();
+ generator.emitPutByIndex(array.get(), length++, value);
+ }
+
+ if (m_elision) {
+ RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
+ generator.emitPutById(array.get(), generator.propertyNames().length, value);
+ }
+
+ return generator.moveToDestinationIfNeeded(dst, array.get());
+}
+
+// ------------------------------ PropertyNode ----------------------------
+
+PropertyNode::~PropertyNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PropertyNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_assign);
+}
+
+// ------------------------------ ObjectLiteralNode ----------------------------
+
+ObjectLiteralNode::~ObjectLiteralNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_list);
+}
+
+RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (!m_list) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitNewObject(generator.finalDestination(dst));
+ }
+ return generator.emitNode(dst, m_list.get());
+}
+
+// ------------------------------ PropertyListNode -----------------------------
+
+PropertyListNode::~PropertyListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PropertyListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_node);
+ releaser.release(m_next);
+}
+
+RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newObj = generator.tempDestination(dst);
+
+ generator.emitNewObject(newObj.get());
+
+ for (PropertyListNode* p = this; p; p = p->m_next.get()) {
+ RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
+
+ switch (p->m_node->m_type) {
+ case PropertyNode::Constant: {
+ generator.emitPutById(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Getter: {
+ generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Setter: {
+ generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ return generator.moveToDestinationIfNeeded(dst, newObj.get());
+}
+
+// ------------------------------ BracketAccessorNode --------------------------------
+
+BracketAccessorNode::~BracketAccessorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BracketAccessorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
+ RegisterID* property = generator.emitNode(m_subscript.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
+}
+
+// ------------------------------ DotAccessorNode --------------------------------
+
+DotAccessorNode::~DotAccessorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DotAccessorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* base = generator.emitNode(m_base.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
+}
+
+// ------------------------------ ArgumentListNode -----------------------------
+
+ArgumentListNode::~ArgumentListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArgumentListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_expr);
+}
+
+RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+// ------------------------------ ArgumentsNode -----------------------------
+
+ArgumentsNode::~ArgumentsNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArgumentsNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_listNode);
+}
+
+// ------------------------------ NewExprNode ----------------------------------
+
+NewExprNode::~NewExprNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void NewExprNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_args);
+}
+
+RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ EvalFunctionCallNode ----------------------------------
+
+EvalFunctionCallNode::~EvalFunctionCallNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_args);
+}
+
+RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.tempDestination(dst);
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
+ generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
+ return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallValueNode ----------------------------------
+
+FunctionCallValueNode::~FunctionCallValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallResolveNode ----------------------------------
+
+FunctionCallResolveNode::~FunctionCallResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+ }
+
+ RefPtr<RegisterID> func = generator.tempDestination(dst);
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ int identifierStart = divot() - startOffset();
+ generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
+ generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallBracketNode ----------------------------------
+
+FunctionCallBracketNode::~FunctionCallBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RegisterID* property = generator.emitNode(m_subscript.get());
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallDotNode ----------------------------------
+
+FunctionCallDotNode::~FunctionCallDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ PostfixResolveNode ----------------------------------
+
+static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
+{
+ return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
+}
+
+static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
+{
+ return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
+}
+
+RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitToJSNumber(generator.finalDestination(dst), local);
+ }
+
+ if (dst == generator.ignoredResult())
+ return emitPreIncOrDec(generator, local, m_operator);
+ return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ emitPreIncOrDec(generator, value.get(), m_operator);
+ } else {
+ oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+ }
+ generator.emitPutScopedVar(depth, index, value.get(), globalObject);
+ return oldValue;
+ }
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RefPtr<RegisterID> value = generator.newTemporary();
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ emitPreIncOrDec(generator, value.get(), m_operator);
+ } else {
+ oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+ }
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixBracketNode ----------------------------------
+
+PostfixBracketNode::~PostfixBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value.get());
+ else
+ generator.emitPreDec(value.get());
+ } else {
+ oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+ }
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixDotNode ----------------------------------
+
+PostfixDotNode::~PostfixDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value.get());
+ else
+ generator.emitPreDec(value.get());
+ } else {
+ oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+ }
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixErrorNode -----------------------------------
+
+PostfixErrorNode::~PostfixErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ DeleteResolveNode -----------------------------------
+
+RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.registerFor(m_ident))
+ return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
+}
+
+// ------------------------------ DeleteBracketNode -----------------------------------
+
+DeleteBracketNode::~DeleteBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
+ RegisterID* r1 = generator.emitNode(m_subscript.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
+}
+
+// ------------------------------ DeleteDotNode -----------------------------------
+
+DeleteDotNode::~DeleteDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* r0 = generator.emitNode(m_base.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
+}
+
+// ------------------------------ DeleteValueNode -----------------------------------
+
+DeleteValueNode::~DeleteValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+
+ // delete on a non-location expression ignores the value and returns true
+ return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
+}
+
+// ------------------------------ VoidNode -------------------------------------
+
+VoidNode::~VoidNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void VoidNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult()) {
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+ return 0;
+ }
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ return generator.emitLoad(dst, jsUndefined());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitTypeOf(generator.finalDestination(dst), local);
+ }
+
+ RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ generator.emitGetById(scratch.get(), scratch.get(), m_ident);
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+TypeOfValueNode::~TypeOfValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void TypeOfValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult()) {
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+ return 0;
+ }
+ RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
+ return generator.emitTypeOf(generator.finalDestination(dst), src.get());
+}
+
+// ------------------------------ PrefixResolveNode ----------------------------------
+
+RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
+ return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
+ }
+
+ emitPreIncOrDec(generator, local, m_operator);
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ emitPreIncOrDec(generator, propDst.get(), m_operator);
+ generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+ }
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+ emitPreIncOrDec(generator, propDst.get(), m_operator);
+ generator.emitPutById(base.get(), m_ident, propDst.get());
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixBracketNode ----------------------------------
+
+PrefixBracketNode::~PrefixBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+ generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+ RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value);
+ else
+ generator.emitPreDec(value);
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixDotNode ----------------------------------
+
+PrefixDotNode::~PrefixDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+ generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+ RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value);
+ else
+ generator.emitPreDec(value);
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixErrorNode -----------------------------------
+
+PrefixErrorNode::~PrefixErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ Unary Operation Nodes -----------------------------------
+
+UnaryOpNode::~UnaryOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void UnaryOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
+}
+
+// ------------------------------ Binary Operation Nodes -----------------------------------
+
+BinaryOpNode::~BinaryOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ OpcodeID opcodeID = this->opcodeID();
+ if (opcodeID == op_neq) {
+ if (m_expr1->isNull() || m_expr2->isNull()) {
+ RefPtr<RegisterID> src = generator.tempDestination(dst);
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
+ return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
+ }
+ }
+
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (m_expr1->isNull() || m_expr2->isNull()) {
+ RefPtr<RegisterID> src = generator.tempDestination(dst);
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
+ return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
+ }
+
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
+}
+
+RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitGetByIdExceptionInfo(op_instanceof);
+ RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
+}
+
+// ------------------------------ LogicalOpNode ----------------------------
+
+LogicalOpNode::~LogicalOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void LogicalOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> temp = generator.tempDestination(dst);
+ RefPtr<Label> target = generator.newLabel();
+
+ generator.emitNode(temp.get(), m_expr1.get());
+ if (m_operator == OpLogicalAnd)
+ generator.emitJumpIfFalse(temp.get(), target.get());
+ else
+ generator.emitJumpIfTrue(temp.get(), target.get());
+ generator.emitNode(temp.get(), m_expr2.get());
+ generator.emitLabel(target.get());
+
+ return generator.moveToDestinationIfNeeded(dst, temp.get());
+}
+
+// ------------------------------ ConditionalNode ------------------------------
+
+ConditionalNode::~ConditionalNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConditionalNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_logical);
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newDst = generator.finalDestination(dst);
+ RefPtr<Label> beforeElse = generator.newLabel();
+ RefPtr<Label> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_logical.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ generator.emitNode(newDst.get(), m_expr1.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+ generator.emitNode(newDst.get(), m_expr2.get());
+
+ generator.emitLabel(afterElse.get());
+
+ return newDst.get();
+}
+
+// ------------------------------ ReadModifyResolveNode -----------------------------------
+
+ReadModifyResolveNode::~ReadModifyResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_right);
+}
+
+// FIXME: should this be moved to be a method on BytecodeGenerator?
+static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
+{
+ OpcodeID opcodeID;
+ switch (oper) {
+ case OpMultEq:
+ opcodeID = op_mul;
+ break;
+ case OpDivEq:
+ opcodeID = op_div;
+ break;
+ case OpPlusEq:
+ opcodeID = op_add;
+ break;
+ case OpMinusEq:
+ opcodeID = op_sub;
+ break;
+ case OpLShift:
+ opcodeID = op_lshift;
+ break;
+ case OpRShift:
+ opcodeID = op_rshift;
+ break;
+ case OpURShift:
+ opcodeID = op_urshift;
+ break;
+ case OpAndEq:
+ opcodeID = op_bitand;
+ break;
+ case OpXOrEq:
+ opcodeID = op_bitxor;
+ break;
+ case OpOrEq:
+ opcodeID = op_bitor;
+ break;
+ case OpModEq:
+ opcodeID = op_mod;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return dst;
+ }
+
+ return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
+}
+
+RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ }
+
+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
+ RefPtr<RegisterID> result = generator.newTemporary();
+ generator.emitMove(result.get(), local);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ generator.emitMove(local, result.get());
+ return generator.moveToDestinationIfNeeded(dst, result.get());
+ }
+
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ generator.emitPutScopedVar(depth, index, result, globalObject);
+ return result;
+ }
+
+ RefPtr<RegisterID> src1 = generator.tempDestination(dst);
+ generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ return generator.emitPutById(base.get(), m_ident, result);
+}
+
+// ------------------------------ AssignResolveNode -----------------------------------
+
+AssignResolveNode::~AssignResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_right);
+}
+
+RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident))
+ return generator.emitNode(dst, m_right.get());
+
+ RegisterID* result = generator.emitNode(local, m_right.get());
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ generator.emitPutScopedVar(depth, index, value, globalObject);
+ return value;
+ }
+
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+// ------------------------------ AssignDotNode -----------------------------------
+
+AssignDotNode::~AssignDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyDotNode -----------------------------------
+
+ReadModifyDotNode::~ReadModifyDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_right);
+}
+
+RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitPutById(base.get(), m_ident, updatedValue);
+}
+
+// ------------------------------ AssignErrorNode -----------------------------------
+
+AssignErrorNode::~AssignErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_left);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
+}
+
+// ------------------------------ AssignBracketNode -----------------------------------
+
+AssignBracketNode::~AssignBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyBracketNode -----------------------------------
+
+ReadModifyBracketNode::~ReadModifyBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_right);
+}
+
+RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), updatedValue);
+
+ return updatedValue;
+}
+
+// ------------------------------ CommaNode ------------------------------------
+
+CommaNode::~CommaNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CommaNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(generator.ignoredResult(), m_expr1.get());
+ return generator.emitNode(dst, m_expr2.get());
+}
+
+// ------------------------------ ConstDeclNode ------------------------------------
+
+ConstDeclNode::~ConstDeclNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConstDeclNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_init);
+}
+
+ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_init(init)
+{
+}
+
+RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
+{
+ if (RegisterID* local = generator.constRegisterFor(m_ident)) {
+ if (!m_init)
+ return local;
+
+ return generator.emitNode(local, m_init.get());
+ }
+
+ // FIXME: While this code should only be hit in eval code, it will potentially
+ // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ RegisterID* result = 0;
+ for (ConstDeclNode* n = this; n; n = n->m_next.get())
+ result = n->emitCodeSingle(generator);
+
+ return result;
+}
+
+// ------------------------------ ConstStatementNode -----------------------------
+
+ConstStatementNode::~ConstStatementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConstStatementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+}
+
+RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return generator.emitNode(m_next.get());
+}
+
+// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
+
+static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst)
+{
+ StatementVector::const_iterator end = statements.end();
+ for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) {
+ StatementNode* n = it->get();
+ if (!n->isLoop())
+ generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
+ generator.emitNode(dst, n);
+ }
+ return 0;
+}
+
+// ------------------------------ BlockNode ------------------------------------
+
+BlockNode::~BlockNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BlockNode::releaseNodes(NodeReleaser& releaser)
+{
+ size_t size = m_children.size();
+ for (size_t i = 0; i < size; ++i)
+ releaser.release(m_children[i]);
+}
+
+BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
+ : StatementNode(globalData)
+{
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+}
+
+RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ return statementListEmitCode(m_children, generator, dst);
+}
+
+// ------------------------------ EmptyStatementNode ---------------------------
+
+RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst)
+{
+ return dst;
+}
+
+// ------------------------------ DebuggerStatementNode ---------------------------
+
+RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
+ return dst;
+}
+
+// ------------------------------ ExprStatementNode ----------------------------
+
+RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+// ------------------------------ VarStatementNode ----------------------------
+
+VarStatementNode::~VarStatementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void VarStatementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(m_expr.get());
+}
+
+// ------------------------------ IfNode ---------------------------------------
+
+IfNode::~IfNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void IfNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_condition);
+ releaser.release(m_ifBlock);
+}
+
+RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> afterThen = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, afterThen.get());
+
+ if (!m_ifBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitLabel(afterThen.get());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+ return 0;
+}
+
+// ------------------------------ IfElseNode ---------------------------------------
+
+IfElseNode::~IfElseNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void IfElseNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_elseBlock);
+ IfNode::releaseNodes(releaser);
+}
+
+RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> beforeElse = generator.newLabel();
+ RefPtr<Label> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ if (!m_ifBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+
+ if (!m_elseBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
+
+ generator.emitNode(dst, m_elseBlock.get());
+
+ generator.emitLabel(afterElse.get());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+ return 0;
+}
+
+// ------------------------------ DoWhileNode ----------------------------------
+
+DoWhileNode::~DoWhileNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DoWhileNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_statement);
+ releaser.release(m_expr);
+}
+
+RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return result.get();
+}
+
+// ------------------------------ WhileNode ------------------------------------
+
+WhileNode::~WhileNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void WhileNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ generator.emitJump(scope->continueTarget());
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+
+ generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion
+ return 0;
+}
+
+// ------------------------------ ForNode --------------------------------------
+
+ForNode::~ForNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ForNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+ releaser.release(m_expr3);
+ releaser.release(m_statement);
+}
+
+RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (m_expr1)
+ generator.emitNode(generator.ignoredResult(), m_expr1.get());
+
+ RefPtr<Label> condition = generator.newLabel();
+ generator.emitJump(condition.get());
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ if (m_expr3)
+ generator.emitNode(generator.ignoredResult(), m_expr3.get());
+
+ generator.emitLabel(condition.get());
+ if (m_expr2) {
+ RegisterID* cond = generator.emitNode(m_expr2.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+ } else
+ generator.emitJump(topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return result.get();
+}
+
+// ------------------------------ ForInNode ------------------------------------
+
+ForInNode::~ForInNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ForInNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_init);
+ releaser.release(m_lexpr);
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
+ : StatementNode(globalData)
+ , m_init(0L)
+ , m_lexpr(l)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(false)
+{
+}
+
+ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
+ : StatementNode(globalData)
+ , m_ident(ident)
+ , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(true)
+{
+ if (in) {
+ AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
+ node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
+ m_init = node;
+ }
+ // for( var foo = bar in baz )
+}
+
+RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ if (!m_lexpr->isLocation())
+ return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
+
+ RefPtr<Label> continueTarget = generator.newLabel();
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (m_init)
+ generator.emitNode(generator.ignoredResult(), m_init.get());
+ RegisterID* forInBase = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
+ generator.emitJump(scope->continueTarget());
+
+ RefPtr<Label> loopStart = generator.newLabel();
+ generator.emitLabel(loopStart.get());
+
+ RegisterID* propertyName;
+ if (m_lexpr->isResolveNode()) {
+ const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
+ propertyName = generator.registerFor(ident);
+ if (!propertyName) {
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base, ident, propertyName);
+ }
+ } else if (m_lexpr->isDotAccessorNode()) {
+ DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
+ const Identifier& ident = assignNode->identifier();
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitNode(assignNode->base());
+
+ generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+ generator.emitPutById(base, ident, propertyName);
+ } else {
+ ASSERT(m_lexpr->isBracketAccessorNode());
+ BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
+ RegisterID* subscript = generator.emitNode(assignNode->subscript());
+
+ generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+ generator.emitPutByVal(base.get(), subscript, propertyName);
+ }
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+ generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
+ generator.emitLabel(scope->breakTarget());
+ return dst;
+}
+
+// ------------------------------ ContinueNode ---------------------------------
+
+// ECMA 12.7
+RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ LabelScope* scope = generator.continueTarget(m_ident);
+
+ if (!scope)
+ return m_ident.isEmpty()
+ ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
+ : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+ generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
+ return dst;
+}
+
+// ------------------------------ BreakNode ------------------------------------
+
+// ECMA 12.8
+RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ LabelScope* scope = generator.breakTarget(m_ident);
+
+ if (!scope)
+ return m_ident.isEmpty()
+ ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
+ : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+ generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
+ return dst;
+}
+
+// ------------------------------ ReturnNode -----------------------------------
+
+ReturnNode::~ReturnNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReturnNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_value);
+}
+
+RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.codeType() != FunctionCode)
+ return emitThrowError(generator, SyntaxError, "Invalid return statement.");
+
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
+ RefPtr<RegisterID> returnRegister;
+ if (generator.scopeDepth()) {
+ RefPtr<Label> l0 = generator.newLabel();
+ if (generator.hasFinaliser() && !r0->isTemporary()) {
+ returnRegister = generator.emitMove(generator.newTemporary(), r0);
+ r0 = returnRegister.get();
+ }
+ generator.emitJumpScopes(l0.get(), 0);
+ generator.emitLabel(l0.get());
+ }
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ return generator.emitReturn(r0);
+}
+
+// ------------------------------ WithNode -------------------------------------
+
+WithNode::~WithNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void WithNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> scope = generator.newTemporary();
+ generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped
+ generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
+ generator.emitPushScope(scope.get());
+ RegisterID* result = generator.emitNode(dst, m_statement.get());
+ generator.emitPopScope();
+ return result;
+}
+
+// ------------------------------ CaseClauseNode --------------------------------
+
+CaseClauseNode::~CaseClauseNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CaseClauseNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+// ------------------------------ ClauseListNode --------------------------------
+
+ClauseListNode::~ClauseListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ClauseListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_clause);
+ releaser.release(m_next);
+}
+
+// ------------------------------ CaseBlockNode --------------------------------
+
+CaseBlockNode::~CaseBlockNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CaseBlockNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_list1);
+ releaser.release(m_defaultClause);
+ releaser.release(m_list2);
+}
+
+enum SwitchKind {
+ SwitchUnset = 0,
+ SwitchNumber = 1,
+ SwitchString = 2,
+ SwitchNeither = 3
+};
+
+static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
+{
+ for (; list; list = list->getNext()) {
+ ExpressionNode* clauseExpression = list->getClause()->expr();
+ literalVector.append(clauseExpression);
+ if (clauseExpression->isNumber()) {
+ double value = static_cast<NumberNode*>(clauseExpression)->value();
+ JSValuePtr jsValue = JSValuePtr::makeInt32Fast(static_cast<int32_t>(value));
+ if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) {
+ typeForTable = SwitchNeither;
+ break;
+ }
+ int32_t intVal = static_cast<int32_t>(value);
+ ASSERT(intVal == value);
+ if (intVal < min_num)
+ min_num = intVal;
+ if (intVal > max_num)
+ max_num = intVal;
+ typeForTable = SwitchNumber;
+ continue;
+ }
+ if (clauseExpression->isString()) {
+ if (typeForTable & ~SwitchString) {
+ typeForTable = SwitchNeither;
+ break;
+ }
+ const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
+ if (singleCharacterSwitch &= value.size() == 1) {
+ int32_t intVal = value.rep()->data()[0];
+ if (intVal < min_num)
+ min_num = intVal;
+ if (intVal > max_num)
+ max_num = intVal;
+ }
+ typeForTable = SwitchString;
+ continue;
+ }
+ typeForTable = SwitchNeither;
+ break;
+ }
+}
+
+SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
+{
+ SwitchKind typeForTable = SwitchUnset;
+ bool singleCharacterSwitch = true;
+
+ processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+ processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+
+ if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
+ return SwitchInfo::SwitchNone;
+
+ if (typeForTable == SwitchNumber) {
+ int32_t range = max_num - min_num;
+ if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+ return SwitchInfo::SwitchImmediate;
+ return SwitchInfo::SwitchNone;
+ }
+
+ ASSERT(typeForTable == SwitchString);
+
+ if (singleCharacterSwitch) {
+ int32_t range = max_num - min_num;
+ if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+ return SwitchInfo::SwitchCharacter;
+ }
+
+ return SwitchInfo::SwitchString;
+}
+
+RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
+{
+ RefPtr<Label> defaultLabel;
+ Vector<RefPtr<Label>, 8> labelVector;
+ Vector<ExpressionNode*, 8> literalVector;
+ int32_t min_num = std::numeric_limits<int32_t>::max();
+ int32_t max_num = std::numeric_limits<int32_t>::min();
+ SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
+
+ if (switchType != SwitchInfo::SwitchNone) {
+ // Prepare the various labels
+ for (uint32_t i = 0; i < literalVector.size(); i++)
+ labelVector.append(generator.newLabel());
+ defaultLabel = generator.newLabel();
+ generator.beginSwitch(switchExpression, switchType);
+ } else {
+ // Setup jumps
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ RefPtr<RegisterID> clauseVal = generator.newTemporary();
+ generator.emitNode(clauseVal.get(), list->getClause()->expr());
+ generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ RefPtr<RegisterID> clauseVal = generator.newTemporary();
+ generator.emitNode(clauseVal.get(), list->getClause()->expr());
+ generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+ }
+ defaultLabel = generator.newLabel();
+ generator.emitJump(defaultLabel.get());
+ }
+
+ RegisterID* result = 0;
+
+ size_t i = 0;
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+
+ if (m_defaultClause) {
+ generator.emitLabel(defaultLabel.get());
+ result = statementListEmitCode(m_defaultClause->children(), generator, dst);
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+ if (!m_defaultClause)
+ generator.emitLabel(defaultLabel.get());
+
+ ASSERT(i == labelVector.size());
+ if (switchType != SwitchInfo::SwitchNone) {
+ ASSERT(labelVector.size() == literalVector.size());
+ generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
+ }
+ return result;
+}
+
+// ------------------------------ SwitchNode -----------------------------------
+
+SwitchNode::~SwitchNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void SwitchNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_block);
+}
+
+RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
+
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
+
+ generator.emitLabel(scope->breakTarget());
+ return r1;
+}
+
+// ------------------------------ LabelNode ------------------------------------
+
+LabelNode::~LabelNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void LabelNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_statement);
+}
+
+RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.breakTarget(m_name))
+ return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
+
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
+ RegisterID* r0 = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return r0;
+}
+
+// ------------------------------ ThrowNode ------------------------------------
+
+ThrowNode::~ThrowNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ThrowNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitThrow(expr.get());
+ return dst;
+}
+
+// ------------------------------ TryNode --------------------------------------
+
+TryNode::~TryNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void TryNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_tryBlock);
+ releaser.release(m_catchBlock);
+ releaser.release(m_finallyBlock);
+}
+
+RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> tryStartLabel = generator.newLabel();
+ RefPtr<Label> tryEndLabel = generator.newLabel();
+ RefPtr<Label> finallyStart;
+ RefPtr<RegisterID> finallyReturnAddr;
+ if (m_finallyBlock) {
+ finallyStart = generator.newLabel();
+ finallyReturnAddr = generator.newTemporary();
+ generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
+ }
+ generator.emitLabel(tryStartLabel.get());
+ generator.emitNode(dst, m_tryBlock.get());
+ generator.emitLabel(tryEndLabel.get());
+
+ if (m_catchBlock) {
+ RefPtr<Label> handlerEndLabel = generator.newLabel();
+ generator.emitJump(handlerEndLabel.get());
+ RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
+ if (m_catchHasEval) {
+ RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
+ generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
+ generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
+ generator.emitPushScope(exceptionRegister.get());
+ } else
+ generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+ generator.emitNode(dst, m_catchBlock.get());
+ generator.emitPopScope();
+ generator.emitLabel(handlerEndLabel.get());
+ }
+
+ if (m_finallyBlock) {
+ generator.popFinallyContext();
+ // there may be important registers live at the time we jump
+ // to a finally block (such as for a return or throw) so we
+ // ref the highest register ever used as a conservative
+ // approach to not clobbering anything important
+ RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
+ RefPtr<Label> finallyEndLabel = generator.newLabel();
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ // Use a label to record the subtle fact that sret will return to the
+ // next instruction. sret is the only way to jump without an explicit label.
+ generator.emitLabel(generator.newLabel().get());
+ generator.emitJump(finallyEndLabel.get());
+
+ // Finally block for exception path
+ RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ // Use a label to record the subtle fact that sret will return to the
+ // next instruction. sret is the only way to jump without an explicit label.
+ generator.emitLabel(generator.newLabel().get());
+ generator.emitThrow(tempExceptionRegister.get());
+
+ // emit the finally block itself
+ generator.emitLabel(finallyStart.get());
+ generator.emitNode(dst, m_finallyBlock.get());
+ generator.emitSubroutineReturn(finallyReturnAddr.get());
+
+ generator.emitLabel(finallyEndLabel.get());
+ }
+
+ return dst;
+}
+
+// ------------------------------ ParameterNode -----------------------------
+
+ParameterNode::~ParameterNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ParameterNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+}
+
+// -----------------------------ScopeNodeData ---------------------------
+
+ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
+ : m_numConstants(numConstants)
+{
+ if (varStack)
+ m_varStack = *varStack;
+ if (funcStack)
+ m_functionStack = *funcStack;
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+}
+
+void ScopeNodeData::mark()
+{
+ FunctionStack::iterator end = m_functionStack.end();
+ for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) {
+ FunctionBodyNode* body = (*ptr)->body();
+ if (!body->isGenerated())
+ continue;
+ body->generatedBytecode().mark();
+ }
+}
+
+// ------------------------------ ScopeNode -----------------------------
+
+ScopeNode::ScopeNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ , m_features(NoFeatures)
+{
+#if ENABLE(OPCODE_SAMPLING)
+ globalData->interpreter->sampler()->notifyOfScope(this);
+#endif
+}
+
+ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
+ : StatementNode(globalData)
+ , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants))
+ , m_features(features)
+ , m_source(source)
+{
+#if ENABLE(OPCODE_SAMPLING)
+ globalData->interpreter->sampler()->notifyOfScope(this);
+#endif
+}
+
+ScopeNode::~ScopeNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ScopeNode::releaseNodes(NodeReleaser& releaser)
+{
+ if (!m_data)
+ return;
+ size_t size = m_data->m_children.size();
+ for (size_t i = 0; i < size; ++i)
+ releaser.release(m_data->m_children[i]);
+}
+
+// ------------------------------ ProgramNode -----------------------------
+
+ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+{
+}
+
+ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+{
+ return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
+}
+
+RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(children(), generator, dstRegister.get());
+
+ generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get());
+ generator.generate();
+
+ destroyData();
+}
+
+// ------------------------------ EvalNode -----------------------------
+
+EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+{
+}
+
+EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+{
+ return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
+}
+
+RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(children(), generator, dstRegister.get());
+
+ generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.generate();
+
+ // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
+ // so the entire ScopeNodeData cannot be destoyed.
+ children().clear();
+}
+
+EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator.generate();
+
+ return *m_code;
+}
+
+void EvalNode::mark()
+{
+ // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
+ data()->mark();
+}
+
+// ------------------------------ FunctionBodyNode -----------------------------
+
+FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
+ : ScopeNode(globalData)
+ , m_parameters(0)
+ , m_parameterCount(0)
+ , m_refCount(0)
+{
+}
+
+FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
+ , m_parameters(0)
+ , m_parameterCount(0)
+ , m_refCount(0)
+{
+}
+
+FunctionBodyNode::~FunctionBodyNode()
+{
+ ASSERT(!m_refCount);
+ for (size_t i = 0; i < m_parameterCount; ++i)
+ m_parameters[i].~Identifier();
+ fastFree(m_parameters);
+}
+
+void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
+{
+ Vector<Identifier> parameters;
+ for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
+ parameters.append(parameter->ident());
+ size_t count = parameters.size();
+
+ setSource(source);
+ finishParsing(parameters.releaseBuffer(), count);
+}
+
+void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
+{
+ ASSERT(!source().isNull());
+ m_parameters = parameters;
+ m_parameterCount = parameterCount;
+}
+
+void FunctionBodyNode::mark()
+{
+ if (m_code)
+ m_code->mark();
+}
+
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
+{
+ return new FunctionBodyNode(globalData);
+}
+
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+{
+ return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
+}
+
+void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
+ // calling Parser::parse<FunctionBodyNode>().
+ if (!data())
+ scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
+ ASSERT(data());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.generate();
+
+ destroyData();
+}
+
+CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator.generate();
+
+ return *m_code;
+}
+
+RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
+ statementListEmitCode(children(), generator, generator.ignoredResult());
+ if (children().size() && children().last()->isBlock()) {
+ BlockNode* blockNode = static_cast<BlockNode*>(children().last().get());
+ if (blockNode->children().size() && blockNode->children().last()->isReturnNode())
+ return 0;
+ }
+
+ RegisterID* r0 = generator.emitLoad(0, jsUndefined());
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ generator.emitReturn(r0);
+ return 0;
+}
+
+UString FunctionBodyNode::paramString() const
+{
+ UString s("");
+ for (size_t pos = 0; pos < m_parameterCount; ++pos) {
+ if (!s.isEmpty())
+ s += ", ";
+ s += parameters()[pos].ustring();
+ }
+
+ return s;
+}
+
+Identifier* FunctionBodyNode::copyParameters()
+{
+ Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
+ VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
+ return parameters;
+}
+
+// ------------------------------ FuncDeclNode ---------------------------------
+
+FuncDeclNode::~FuncDeclNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FuncDeclNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_parameter);
+ releaser.release(m_body);
+}
+
+JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+}
+
+RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ return dst;
+}
+
+// ------------------------------ FuncExprNode ---------------------------------
+
+FuncExprNode::~FuncExprNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FuncExprNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_parameter);
+ releaser.release(m_body);
+}
+
+RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
+}
+
+JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+
+ /*
+ The Identifier in a FunctionExpression can be referenced from inside
+ the FunctionExpression's FunctionBody to allow the function to call
+ itself recursively. However, unlike in a FunctionDeclaration, the
+ Identifier in a FunctionExpression cannot be referenced from and
+ does not affect the scope enclosing the FunctionExpression.
+ */
+
+ if (!m_ident.isNull()) {
+ JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
+ func->scope().push(functionScopeObject);
+ }
+
+ return func;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NODES_H_
+#define NODES_H_
+
+#include "Error.h"
+#include "Opcode.h"
+#include "ResultType.h"
+#include "SourceCode.h"
+#include "SymbolTable.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(X86) && COMPILER(GCC)
+#define JSC_FAST_CALL __attribute__((regparm(3)))
+#else
+#define JSC_FAST_CALL
+#endif
+
+namespace JSC {
+
+ class CodeBlock;
+ class BytecodeGenerator;
+ class FuncDeclNode;
+ class EvalCodeBlock;
+ class JSFunction;
+ class NodeReleaser;
+ class ProgramCodeBlock;
+ class PropertyListNode;
+ class RegisterID;
+ class ScopeChainNode;
+
+ typedef unsigned CodeFeatures;
+
+ const CodeFeatures NoFeatures = 0;
+ const CodeFeatures EvalFeature = 1 << 0;
+ const CodeFeatures ClosureFeature = 1 << 1;
+ const CodeFeatures AssignFeature = 1 << 2;
+ const CodeFeatures ArgumentsFeature = 1 << 3;
+ const CodeFeatures WithFeature = 1 << 4;
+ const CodeFeatures CatchFeature = 1 << 5;
+ const CodeFeatures ThisFeature = 1 << 6;
+ const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature;
+
+ enum Operator {
+ OpEqual,
+ OpPlusEq,
+ OpMinusEq,
+ OpMultEq,
+ OpDivEq,
+ OpPlusPlus,
+ OpMinusMinus,
+ OpAndEq,
+ OpXOrEq,
+ OpOrEq,
+ OpModEq,
+ OpLShift,
+ OpRShift,
+ OpURShift
+ };
+
+ enum LogicalOperator {
+ OpLogicalAnd,
+ OpLogicalOr
+ };
+
+ namespace DeclarationStacks {
+ enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
+ typedef Vector<std::pair<Identifier, unsigned> > VarStack;
+ typedef Vector<RefPtr<FuncDeclNode> > FunctionStack;
+ }
+
+ struct SwitchInfo {
+ enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString };
+ uint32_t bytecodeOffset;
+ SwitchType switchType;
+ };
+
+ class ParserRefCounted : Noncopyable {
+ protected:
+ ParserRefCounted(JSGlobalData*) JSC_FAST_CALL;
+
+ public:
+ virtual ~ParserRefCounted();
+
+ // Nonrecursive destruction.
+ virtual void releaseNodes(NodeReleaser&);
+
+ void ref() JSC_FAST_CALL;
+ void deref() JSC_FAST_CALL;
+ bool hasOneRef() JSC_FAST_CALL;
+
+ static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL;
+
+ private:
+ JSGlobalData* m_globalData;
+ };
+
+ class Node : public ParserRefCounted {
+ public:
+ Node(JSGlobalData*) JSC_FAST_CALL;
+
+ /*
+ Return value: The register holding the production's value.
+ dst: An optional parameter specifying the most efficient
+ destination at which to store the production's value.
+ The callee must honor dst.
+
+ dst provides for a crude form of copy propagation. For example,
+
+ x = 1
+
+ becomes
+
+ load r[x], 1
+
+ instead of
+
+ load r0, 1
+ mov r[x], r0
+
+ because the assignment node, "x =", passes r[x] as dst to the number
+ node, "1".
+ */
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL = 0;
+
+ int lineNo() const { return m_line; }
+
+ protected:
+ int m_line;
+ };
+
+ class ExpressionNode : public Node {
+ public:
+ ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknownType()) JSC_FAST_CALL
+ : Node(globalData)
+ , m_resultDesc(resultDesc)
+ {
+ }
+
+ virtual bool isNumber() const JSC_FAST_CALL { return false; }
+ virtual bool isString() const JSC_FAST_CALL { return false; }
+ virtual bool isNull() const JSC_FAST_CALL { return false; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; }
+ virtual bool isLocation() const JSC_FAST_CALL { return false; }
+ virtual bool isResolveNode() const JSC_FAST_CALL { return false; }
+ virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; }
+ virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; }
+ virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; }
+
+ virtual ExpressionNode* stripUnaryPlus() { return this; }
+
+ ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; }
+
+ // This needs to be in public in order to compile using GCC 3.x
+ typedef enum { EvalOperator, FunctionCall } CallerType;
+
+ private:
+ ResultType m_resultDesc;
+ };
+
+ class StatementNode : public Node {
+ public:
+ StatementNode(JSGlobalData*) JSC_FAST_CALL;
+ void setLoc(int line0, int line1) JSC_FAST_CALL;
+ int firstLine() const JSC_FAST_CALL { return lineNo(); }
+ int lastLine() const JSC_FAST_CALL { return m_lastLine; }
+
+ virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; }
+ virtual bool isReturnNode() const JSC_FAST_CALL { return false; }
+ virtual bool isExprStatement() const JSC_FAST_CALL { return false; }
+
+ virtual bool isBlock() const JSC_FAST_CALL { return false; }
+ virtual bool isLoop() const JSC_FAST_CALL { return false; }
+
+ private:
+ int m_lastLine;
+ };
+
+ class NullNode : public ExpressionNode {
+ public:
+ NullNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::nullType())
+ {
+ }
+
+ virtual bool isNull() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class BooleanNode : public ExpressionNode {
+ public:
+ BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::booleanType())
+ , m_value(value)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+
+ private:
+ bool m_value;
+ };
+
+ class NumberNode : public ExpressionNode {
+ public:
+ NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::numberType())
+ , m_double(v)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isNumber() const JSC_FAST_CALL { return true; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+ double value() const JSC_FAST_CALL { return m_double; }
+ void setValue(double d) JSC_FAST_CALL { m_double = d; }
+
+ private:
+ double m_double;
+ };
+
+ class StringNode : public ExpressionNode {
+ public:
+ StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_value(v)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isString() const JSC_FAST_CALL { return true; }
+ const Identifier& value() { return m_value; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+
+ private:
+ Identifier m_value;
+ };
+
+ class ThrowableExpressionData {
+ public:
+ ThrowableExpressionData()
+ : m_divot(static_cast<uint32_t>(-1))
+ , m_startOffset(static_cast<uint16_t>(-1))
+ , m_endOffset(static_cast<uint16_t>(-1))
+ {
+ }
+
+ ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : m_divot(divot)
+ , m_startOffset(startOffset)
+ , m_endOffset(endOffset)
+ {
+ }
+
+ void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset)
+ {
+ m_divot = divot;
+ m_startOffset = startOffset;
+ m_endOffset = endOffset;
+ }
+
+ uint32_t divot() const { return m_divot; }
+ uint16_t startOffset() const { return m_startOffset; }
+ uint16_t endOffset() const { return m_endOffset; }
+
+ protected:
+ RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg);
+ RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&);
+
+ private:
+ uint32_t m_divot;
+ uint16_t m_startOffset;
+ uint16_t m_endOffset;
+ };
+
+ class ThrowableSubExpressionData : public ThrowableExpressionData {
+ public:
+ ThrowableSubExpressionData()
+ : ThrowableExpressionData()
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionEndOffset(0)
+ {
+ }
+
+ ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionEndOffset(0)
+ {
+ }
+
+ void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset)
+ {
+ ASSERT(subexpressionDivot <= divot());
+ if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
+ return;
+ m_subexpressionDivotOffset = divot() - subexpressionDivot;
+ m_subexpressionEndOffset = subexpressionOffset;
+ }
+
+ protected:
+ uint16_t m_subexpressionDivotOffset;
+ uint16_t m_subexpressionEndOffset;
+ };
+
+ class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData {
+ public:
+ ThrowablePrefixedSubExpressionData()
+ : ThrowableExpressionData()
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionStartOffset(0)
+ {
+ }
+
+ ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionStartOffset(0)
+ {
+ }
+
+ void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset)
+ {
+ ASSERT(subexpressionDivot >= divot());
+ if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
+ return;
+ m_subexpressionDivotOffset = subexpressionDivot - divot();
+ m_subexpressionStartOffset = subexpressionOffset;
+ }
+
+ protected:
+ uint16_t m_subexpressionDivotOffset;
+ uint16_t m_subexpressionStartOffset;
+ };
+
+ class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_pattern(pattern)
+ , m_flags(flags)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ UString m_pattern;
+ UString m_flags;
+ };
+
+ class ThisNode : public ExpressionNode {
+ public:
+ ThisNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class ResolveNode : public ExpressionNode {
+ public:
+ ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_startOffset(startOffset)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL;
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isResolveNode() const JSC_FAST_CALL { return true; }
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ Identifier m_ident;
+ int32_t m_startOffset;
+ };
+
+ class ElementNode : public ParserRefCounted {
+ public:
+ ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ }
+
+ ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ l->m_next = this;
+ }
+
+ virtual ~ElementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ int elision() const { return m_elision; }
+ ExpressionNode* value() { return m_node.get(); }
+
+ ElementNode* next() { return m_next.get(); }
+
+ private:
+ RefPtr<ElementNode> m_next;
+ int m_elision;
+ RefPtr<ExpressionNode> m_node;
+ };
+
+ class ArrayNode : public ExpressionNode {
+ public:
+ ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(0)
+ , m_optional(false)
+ {
+ }
+
+ ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ virtual ~ArrayNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ElementNode> m_element;
+ int m_elision;
+ bool m_optional;
+ };
+
+ class PropertyNode : public ParserRefCounted {
+ public:
+ enum Type { Constant, Getter, Setter };
+
+ PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_name(name)
+ , m_assign(assign)
+ , m_type(type)
+ {
+ }
+
+ virtual ~PropertyNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ const Identifier& name() const { return m_name; }
+
+ private:
+ friend class PropertyListNode;
+ Identifier m_name;
+ RefPtr<ExpressionNode> m_assign;
+ Type m_type;
+ };
+
+ class PropertyListNode : public Node {
+ public:
+ PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL
+ : Node(globalData)
+ , m_node(node)
+ {
+ }
+
+ PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL
+ : Node(globalData)
+ , m_node(node)
+ {
+ list->m_next = this;
+ }
+
+ virtual ~PropertyListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<PropertyNode> m_node;
+ RefPtr<PropertyListNode> m_next;
+ };
+
+ class ObjectLiteralNode : public ExpressionNode {
+ public:
+ ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ {
+ }
+
+ ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_list(list)
+ {
+ }
+
+ virtual ~ObjectLiteralNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<PropertyListNode> m_list;
+ };
+
+ class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ {
+ }
+
+ virtual ~BracketAccessorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; }
+ ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); }
+ ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); }
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ bool m_subscriptHasAssignments;
+ };
+
+ class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ virtual ~DotAccessorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; }
+ ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); }
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ };
+
+ class ArgumentListNode : public Node {
+ public:
+ ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : Node(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL
+ : Node(globalData)
+ , m_expr(expr)
+ {
+ listNode->m_next = this;
+ }
+
+ virtual ~ArgumentListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ RefPtr<ArgumentListNode> m_next;
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class ArgumentsNode : public ParserRefCounted {
+ public:
+ ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ {
+ }
+
+ ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_listNode(listNode)
+ {
+ }
+
+ virtual ~ArgumentsNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ RefPtr<ArgumentListNode> m_listNode;
+ };
+
+ class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ virtual ~NewExprNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_args(args)
+ {
+ }
+
+ virtual ~EvalFunctionCallNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<ArgumentsNode> m_args;
+ size_t m_index; // Used by LocalVarFunctionCallNode.
+ size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode
+ };
+
+ class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre?
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ protected:
+ Identifier m_ident;
+ };
+
+ class PostfixResolveNode : public PrePostResolveNode {
+ public:
+ PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Operator m_operator;
+ };
+
+ class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ Operator m_operator;
+ };
+
+ class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ Operator m_operator;
+ };
+
+ class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ Operator m_operator;
+ };
+
+ class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ {
+ }
+
+ virtual ~DeleteBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ };
+
+ class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ virtual ~DeleteDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ };
+
+ class DeleteValueNode : public ExpressionNode {
+ public:
+ DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~DeleteValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class VoidNode : public ExpressionNode {
+ public:
+ VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~VoidNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class TypeOfResolveNode : public ExpressionNode {
+ public:
+ TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ Identifier m_ident;
+ };
+
+ class TypeOfValueNode : public ExpressionNode {
+ public:
+ TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~TypeOfValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class PrefixResolveNode : public PrePostResolveNode {
+ public:
+ PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Operator m_operator;
+ };
+
+ class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ Operator m_operator;
+ };
+
+ class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ Operator m_operator;
+ };
+
+ class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ Operator m_operator;
+ };
+
+ class UnaryOpNode : public ExpressionNode {
+ public:
+ UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr)
+ : ExpressionNode(globalData, type)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~UnaryOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+
+ protected:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class UnaryPlusNode : public UnaryOpNode {
+ public:
+ UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::numberType(), expr)
+ {
+ }
+
+ virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; }
+ };
+
+ class NegateNode : public UnaryOpNode {
+ public:
+ NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; }
+ };
+
+ class BitwiseNotNode : public UnaryOpNode {
+ public:
+ BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::forBitOp(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; }
+ };
+
+ class LogicalNotNode : public UnaryOpNode {
+ public:
+ LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::booleanType(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; }
+ };
+
+ class BinaryOpNode : public ExpressionNode {
+ public:
+ BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ExpressionNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ExpressionNode(globalData, type)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~BinaryOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+
+ protected:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ bool m_rightHasAssignments;
+ };
+
+ class ReverseBinaryOpNode : public BinaryOpNode {
+ public:
+ ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class MultNode : public BinaryOpNode {
+ public:
+ MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; }
+ };
+
+ class DivNode : public BinaryOpNode {
+ public:
+ DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; }
+ };
+
+ class ModNode : public BinaryOpNode {
+ public:
+ ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; }
+ };
+
+ class AddNode : public BinaryOpNode {
+ public:
+ AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; }
+ };
+
+ class SubNode : public BinaryOpNode {
+ public:
+ SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; }
+ };
+
+ class LeftShiftNode : public BinaryOpNode {
+ public:
+ LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; }
+ };
+
+ class RightShiftNode : public BinaryOpNode {
+ public:
+ RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; }
+ };
+
+ class UnsignedRightShiftNode : public BinaryOpNode {
+ public:
+ UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; }
+ };
+
+ class LessNode : public BinaryOpNode {
+ public:
+ LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; }
+ };
+
+ class GreaterNode : public ReverseBinaryOpNode {
+ public:
+ GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; }
+ };
+
+ class LessEqNode : public BinaryOpNode {
+ public:
+ LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; }
+ };
+
+ class GreaterEqNode : public ReverseBinaryOpNode {
+ public:
+ GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; }
+ };
+
+ class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
+ public:
+ ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments)
+ {
+ }
+ ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class InstanceOfNode : public ThrowableBinaryOpNode {
+ public:
+ InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class InNode : public ThrowableBinaryOpNode {
+ public:
+ InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; }
+ };
+
+ class EqualNode : public BinaryOpNode {
+ public:
+ EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; }
+ };
+
+ class NotEqualNode : public BinaryOpNode {
+ public:
+ NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; }
+ };
+
+ class StrictEqualNode : public BinaryOpNode {
+ public:
+ StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; }
+ };
+
+ class NotStrictEqualNode : public BinaryOpNode {
+ public:
+ NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; }
+ };
+
+ class BitAndNode : public BinaryOpNode {
+ public:
+ BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; }
+ };
+
+ class BitOrNode : public BinaryOpNode {
+ public:
+ BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; }
+ };
+
+ class BitXOrNode : public BinaryOpNode {
+ public:
+ BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; }
+ };
+
+ /**
+ * m_expr1 && m_expr2, m_expr1 || m_expr2
+ */
+ class LogicalOpNode : public ExpressionNode {
+ public:
+ LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::booleanType())
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~LogicalOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ LogicalOperator m_operator;
+ };
+
+ /**
+ * The ternary operator, "m_logical ? m_expr1 : m_expr2"
+ */
+ class ConditionalNode : public ExpressionNode {
+ public:
+ ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_logical(logical)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ {
+ }
+
+ virtual ~ConditionalNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_logical;
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ };
+
+ class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_operator(oper)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 30;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ExpressionNode> m_right;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_left(left)
+ , m_operator(oper)
+ , m_right(right)
+ {
+ }
+
+ virtual ~AssignErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_left;
+ Operator m_operator;
+ RefPtr<ExpressionNode> m_right;
+ };
+
+ class CommaNode : public ExpressionNode {
+ public:
+ CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ {
+ }
+
+ virtual ~CommaNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ };
+
+ class VarDeclCommaNode : public CommaNode {
+ public:
+ VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : CommaNode(globalData, expr1, expr2)
+ {
+ }
+ };
+
+ class ConstDeclNode : public ExpressionNode {
+ public:
+ ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL;
+
+ virtual ~ConstDeclNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ Identifier m_ident;
+ RefPtr<ConstDeclNode> m_next;
+ RefPtr<ExpressionNode> m_init;
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL;
+ };
+
+ class ConstStatementNode : public StatementNode {
+ public:
+ ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_next(next)
+ {
+ }
+
+ virtual ~ConstStatementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ConstDeclNode> m_next;
+ };
+
+ typedef Vector<RefPtr<StatementNode> > StatementVector;
+
+ class SourceElements : public ParserRefCounted {
+ public:
+ SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {}
+
+ void append(PassRefPtr<StatementNode>);
+ void releaseContentsIntoVector(StatementVector& destination)
+ {
+ ASSERT(destination.isEmpty());
+ m_statements.swap(destination);
+ destination.shrinkToFit();
+ }
+
+ private:
+ StatementVector m_statements;
+ };
+
+ class BlockNode : public StatementNode {
+ public:
+ BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL;
+
+ virtual ~BlockNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ StatementVector& children() { return m_children; }
+
+ virtual bool isBlock() const JSC_FAST_CALL { return true; }
+
+ private:
+ StatementVector m_children;
+ };
+
+ class EmptyStatementNode : public StatementNode {
+ public:
+ EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug
+ : StatementNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; }
+ };
+
+ class DebuggerStatementNode : public StatementNode {
+ public:
+ DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class ExprStatementNode : public StatementNode {
+ public:
+ ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual bool isExprStatement() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ ExpressionNode* expr() const { return m_expr.get(); }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class VarStatementNode : public StatementNode {
+ public:
+ VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~VarStatementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class IfNode : public StatementNode {
+ public:
+ IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_condition(condition)
+ , m_ifBlock(ifBlock)
+ {
+ }
+
+ virtual ~IfNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ protected:
+ RefPtr<ExpressionNode> m_condition;
+ RefPtr<StatementNode> m_ifBlock;
+ };
+
+ class IfElseNode : public IfNode {
+ public:
+ IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL
+ : IfNode(globalData, condition, ifBlock)
+ , m_elseBlock(elseBlock)
+ {
+ }
+
+ virtual ~IfElseNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<StatementNode> m_elseBlock;
+ };
+
+ class DoWhileNode : public StatementNode {
+ public:
+ DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_statement(statement)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~DoWhileNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<StatementNode> m_statement;
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class WhileNode : public StatementNode {
+ public:
+ WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ {
+ }
+
+ virtual ~WhileNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ };
+
+ class ForNode : public StatementNode {
+ public:
+ ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_expr3(expr3)
+ , m_statement(statement)
+ , m_expr1WasVarDecl(expr1 && expr1WasVarDecl)
+ {
+ ASSERT(statement);
+ }
+
+ virtual ~ForNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ RefPtr<ExpressionNode> m_expr3;
+ RefPtr<StatementNode> m_statement;
+ bool m_expr1WasVarDecl;
+ };
+
+ class ForInNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL;
+ ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL;
+
+ virtual ~ForInNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_init;
+ RefPtr<ExpressionNode> m_lexpr;
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ bool m_identIsVarDecl;
+ };
+
+ class ContinueNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class BreakNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ BreakNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class ReturnNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_value(value)
+ {
+ }
+
+ virtual ~ReturnNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual bool isReturnNode() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_value;
+ };
+
+ class WithNode : public StatementNode {
+ public:
+ WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_divot(divot)
+ , m_expressionLength(expressionLength)
+ {
+ }
+
+ virtual ~WithNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ uint32_t m_divot;
+ uint32_t m_expressionLength;
+ };
+
+ class LabelNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_name(name)
+ , m_statement(statement)
+ {
+ }
+
+ virtual ~LabelNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_name;
+ RefPtr<StatementNode> m_statement;
+ };
+
+ class ThrowNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~ThrowNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class TryNode : public StatementNode {
+ public:
+ TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_tryBlock(tryBlock)
+ , m_exceptionIdent(exceptionIdent)
+ , m_catchBlock(catchBlock)
+ , m_finallyBlock(finallyBlock)
+ , m_catchHasEval(catchHasEval)
+ {
+ }
+
+ virtual ~TryNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<StatementNode> m_tryBlock;
+ Identifier m_exceptionIdent;
+ RefPtr<StatementNode> m_catchBlock;
+ RefPtr<StatementNode> m_finallyBlock;
+ bool m_catchHasEval;
+ };
+
+ class ParameterNode : public ParserRefCounted {
+ public:
+ ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_ident(ident)
+ {
+ l->m_next = this;
+ }
+
+ virtual ~ParameterNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ const Identifier& ident() const JSC_FAST_CALL { return m_ident; }
+ ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ParameterNode> m_next;
+ };
+
+ struct ScopeNodeData {
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants);
+
+ VarStack m_varStack;
+ FunctionStack m_functionStack;
+ int m_numConstants;
+ StatementVector m_children;
+
+ void mark();
+ };
+
+ class ScopeNode : public StatementNode {
+ public:
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNode(JSGlobalData*) JSC_FAST_CALL;
+ ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ virtual ~ScopeNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); }
+ ScopeNodeData* data() const { return m_data.get(); }
+ void destroyData() { m_data.clear(); }
+
+ const SourceCode& source() const { return m_source; }
+ const UString& sourceURL() const JSC_FAST_CALL { return m_source.provider()->url(); }
+ intptr_t sourceID() const { return m_source.provider()->asID(); }
+
+ void setFeatures(CodeFeatures features) { m_features = features; }
+ CodeFeatures features() { return m_features; }
+
+ bool usesEval() const { return m_features & EvalFeature; }
+ bool usesArguments() const { return m_features & ArgumentsFeature; }
+ void setUsesArguments() { m_features |= ArgumentsFeature; }
+ bool usesThis() const { return m_features & ThisFeature; }
+ bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+
+ VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
+ FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
+
+ StatementVector& children() { ASSERT(m_data); return m_data->m_children; }
+
+ int neededConstants()
+ {
+ ASSERT(m_data);
+ // We may need 2 more constants than the count given by the parser,
+ // because of the various uses of jsUndefined() and jsNull().
+ return m_data->m_numConstants + 2;
+ }
+
+ virtual void mark() { }
+
+ protected:
+ void setSource(const SourceCode& source) { m_source = source; }
+
+ private:
+ OwnPtr<ScopeNodeData> m_data;
+ CodeFeatures m_features;
+ SourceCode m_source;
+ };
+
+ class ProgramNode : public ScopeNode {
+ public:
+ static ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ private:
+ ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ OwnPtr<ProgramCodeBlock> m_code;
+ };
+
+ class EvalNode : public ScopeNode {
+ public:
+ static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL;
+
+ virtual void mark();
+
+ private:
+ EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ OwnPtr<EvalCodeBlock> m_code;
+ };
+
+ class FunctionBodyNode : public ScopeNode {
+ friend class JIT;
+ public:
+ static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL;
+ static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ virtual ~FunctionBodyNode();
+
+ const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; }
+ size_t parameterCount() const { return m_parameterCount; }
+ UString paramString() const JSC_FAST_CALL;
+ Identifier* copyParameters();
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ ASSERT(scopeChain);
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ CodeBlock& generatedBytecode() JSC_FAST_CALL
+ {
+ ASSERT(m_code);
+ return *m_code;
+ }
+
+ bool isGenerated() JSC_FAST_CALL
+ {
+ return m_code;
+ }
+
+ virtual void mark();
+
+ void finishParsing(const SourceCode&, ParameterNode*);
+ void finishParsing(Identifier* parameters, size_t parameterCount);
+
+ UString toSourceString() const JSC_FAST_CALL { return source().toString(); }
+
+ // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref.
+ // If the virtual machine changes so this doesn't happen as much we can change back.
+ void ref()
+ {
+ if (++m_refCount == 1)
+ ScopeNode::ref();
+ }
+ void deref()
+ {
+ ASSERT(m_refCount);
+ if (!--m_refCount)
+ ScopeNode::deref();
+ }
+
+ CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL;
+
+ private:
+ FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL;
+ FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+
+ Identifier* m_parameters;
+ size_t m_parameterCount;
+ OwnPtr<CodeBlock> m_code;
+ unsigned m_refCount;
+ };
+
+ class FuncExprNode : public ExpressionNode {
+ public:
+ FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_parameter(parameter)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, m_parameter.get());
+ }
+
+ virtual ~FuncExprNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
+
+ FunctionBodyNode* body() { return m_body.get(); }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ParameterNode> m_parameter;
+ RefPtr<FunctionBodyNode> m_body;
+ };
+
+ class FuncDeclNode : public StatementNode {
+ public:
+ FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ , m_parameter(parameter)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, m_parameter.get());
+ }
+
+ virtual ~FuncDeclNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
+
+ Identifier m_ident;
+
+ FunctionBodyNode* body() { return m_body.get(); }
+
+ private:
+ RefPtr<ParameterNode> m_parameter;
+ RefPtr<FunctionBodyNode> m_body;
+ };
+
+ class CaseClauseNode : public ParserRefCounted {
+ public:
+ CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_expr(expr)
+ {
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+ }
+
+ virtual ~CaseClauseNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ ExpressionNode* expr() const { return m_expr.get(); }
+ StatementVector& children() { return m_children; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ StatementVector m_children;
+ };
+
+ class ClauseListNode : public ParserRefCounted {
+ public:
+ ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_clause(clause)
+ {
+ }
+
+ ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_clause(clause)
+ {
+ clauseList->m_next = this;
+ }
+
+ virtual ~ClauseListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); }
+ ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); }
+
+ private:
+ RefPtr<CaseClauseNode> m_clause;
+ RefPtr<ClauseListNode> m_next;
+ };
+
+ class CaseBlockNode : public ParserRefCounted {
+ public:
+ CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_list1(list1)
+ , m_defaultClause(defaultClause)
+ , m_list2(list2)
+ {
+ }
+
+ virtual ~CaseBlockNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL;
+
+ private:
+ SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
+ RefPtr<ClauseListNode> m_list1;
+ RefPtr<CaseClauseNode> m_defaultClause;
+ RefPtr<ClauseListNode> m_list2;
+ };
+
+ class SwitchNode : public StatementNode {
+ public:
+ SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_block(block)
+ {
+ }
+
+ virtual ~SwitchNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<CaseBlockNode> m_block;
+ };
+
+ struct ElementList {
+ ElementNode* head;
+ ElementNode* tail;
+ };
+
+ struct PropertyList {
+ PropertyListNode* head;
+ PropertyListNode* tail;
+ };
+
+ struct ArgumentList {
+ ArgumentListNode* head;
+ ArgumentListNode* tail;
+ };
+
+ struct ConstDeclList {
+ ConstDeclNode* head;
+ ConstDeclNode* tail;
+ };
+
+ struct ParameterList {
+ ParameterNode* head;
+ ParameterNode* tail;
+ };
+
+ struct ClauseList {
+ ClauseListNode* head;
+ ClauseListNode* tail;
+ };
+
+} // namespace JSC
+
+#endif // NODES_H_
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Parser.h"
+
+#include "Debugger.h"
+#include "Lexer.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+#include <memory>
+
+using std::auto_ptr;
+
+#ifndef yyparse
+extern int jscyyparse(void*);
+#endif
+
+namespace JSC {
+
+void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
+{
+ ASSERT(!m_sourceElements);
+
+ int defaultErrLine;
+ UString defaultErrMsg;
+
+ if (!errLine)
+ errLine = &defaultErrLine;
+ if (!errMsg)
+ errMsg = &defaultErrMsg;
+
+ *errLine = -1;
+ *errMsg = 0;
+
+ Lexer& lexer = *globalData->lexer;
+ lexer.setCode(*m_source);
+
+ int parseError = jscyyparse(globalData);
+ bool lexError = lexer.sawError();
+ lexer.clear();
+
+ ParserRefCounted::deleteNewObjects(globalData);
+
+ if (parseError || lexError) {
+ *errLine = lexer.lineNo();
+ *errMsg = "Parse error";
+ m_sourceElements.clear();
+ }
+}
+
+void Parser::reparseInPlace(JSGlobalData* globalData, FunctionBodyNode* functionBodyNode)
+{
+ ASSERT(!functionBodyNode->data());
+
+ m_source = &functionBodyNode->source();
+ globalData->lexer->setIsReparsing();
+ parse(globalData, 0, 0);
+ ASSERT(m_sourceElements);
+
+ functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ m_numConstants)));
+ bool usesArguments = functionBodyNode->usesArguments();
+ functionBodyNode->setFeatures(m_features);
+ if (usesArguments && !functionBodyNode->usesArguments())
+ functionBodyNode->setUsesArguments();
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+}
+
+void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
+{
+ m_sourceElements = sourceElements;
+ m_varDeclarations = varStack;
+ m_funcDeclarations = funcStack;
+ m_features = features;
+ m_lastLine = lastLine;
+ m_numConstants = numConstants;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Parser_h
+#define Parser_h
+
+#include "SourceProvider.h"
+#include "Debugger.h"
+#include "Nodes.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class FunctionBodyNode;
+ class ProgramNode;
+ class UString;
+
+ template <typename T>
+ struct ParserRefCountedData : ParserRefCounted {
+ ParserRefCountedData(JSGlobalData* globalData)
+ : ParserRefCounted(globalData)
+ {
+ }
+
+ T data;
+ };
+
+ class Parser : Noncopyable {
+ public:
+ template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+ template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*);
+ void reparseInPlace(JSGlobalData*, FunctionBodyNode*);
+
+ void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
+
+ private:
+ void parse(JSGlobalData*, int* errLine, UString* errMsg);
+
+ const SourceCode* m_source;
+ RefPtr<SourceElements> m_sourceElements;
+ RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
+ RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
+ CodeFeatures m_features;
+ int m_lastLine;
+ int m_numConstants;
+ };
+
+ template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+ {
+ m_source = &source;
+ parse(&exec->globalData(), errLine, errMsg);
+ RefPtr<ParsedNode> result;
+ if (m_sourceElements) {
+ result = ParsedNode::create(&exec->globalData(),
+ m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ *m_source,
+ m_features,
+ m_numConstants);
+ result->setLoc(m_source->firstLine(), m_lastLine);
+ }
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+
+ if (debugger)
+ debugger->sourceParsed(exec, source, *errLine, *errMsg);
+ return result.release();
+ }
+
+ template <class ParsedNode> PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode)
+ {
+ m_source = &oldParsedNode->source();
+ parse(globalData, 0, 0);
+ RefPtr<ParsedNode> result;
+ if (m_sourceElements) {
+ result = ParsedNode::create(globalData,
+ m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ *m_source,
+ oldParsedNode->features(),
+ m_numConstants);
+ result->setLoc(m_source->firstLine(), m_lastLine);
+ }
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+
+ return result.release();
+ }
+
+} // namespace JSC
+
+#endif // Parser_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ResultType_h
+#define ResultType_h
+
+namespace JSC {
+
+ struct ResultType {
+ friend struct OperandTypes;
+
+ typedef char Type;
+ static const Type TypeReusable = 1;
+ static const Type TypeInt32 = 2;
+
+ static const Type TypeMaybeNumber = 0x04;
+ static const Type TypeMaybeString = 0x08;
+ static const Type TypeMaybeNull = 0x10;
+ static const Type TypeMaybeBool = 0x20;
+ static const Type TypeMaybeOther = 0x40;
+
+ static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther;
+
+ explicit ResultType(Type type)
+ : m_type(type)
+ {
+ }
+
+ bool isReusable()
+ {
+ return m_type & TypeReusable;
+ }
+
+ bool isInt32()
+ {
+ return m_type & TypeInt32;
+ }
+
+ bool definitelyIsNumber()
+ {
+ return (m_type & TypeBits) == TypeMaybeNumber;
+ }
+
+ bool mightBeNumber()
+ {
+ return m_type & TypeMaybeNumber;
+ }
+
+ bool isNotNumber()
+ {
+ return !mightBeNumber();
+ }
+
+ static ResultType nullType()
+ {
+ return ResultType(TypeMaybeNull);
+ }
+
+ static ResultType booleanType()
+ {
+ return ResultType(TypeMaybeBool);
+ }
+
+ static ResultType numberType()
+ {
+ return ResultType(TypeMaybeNumber);
+ }
+
+ static ResultType numberTypeCanReuse()
+ {
+ return ResultType(TypeReusable | TypeMaybeNumber);
+ }
+
+ static ResultType numberTypeCanReuseIsInt32()
+ {
+ return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber);
+ }
+
+ static ResultType stringOrNumberTypeCanReuse()
+ {
+ return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString);
+ }
+
+ static ResultType stringType()
+ {
+ return ResultType(TypeMaybeString);
+ }
+
+ static ResultType unknownType()
+ {
+ return ResultType(TypeBits);
+ }
+
+ static ResultType forAdd(ResultType op1, ResultType op2)
+ {
+ if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
+ return numberTypeCanReuse();
+ if (op1.isNotNumber() || op2.isNotNumber())
+ return stringType();
+ return stringOrNumberTypeCanReuse();
+ }
+
+ static ResultType forBitOp()
+ {
+ return numberTypeCanReuseIsInt32();
+ }
+
+ private:
+ Type m_type;
+ };
+
+ struct OperandTypes
+ {
+ OperandTypes(ResultType first = ResultType::unknownType(), ResultType second = ResultType::unknownType())
+ {
+ // We have to initialize one of the int to ensure that
+ // the entire struct is initialized.
+ m_u.i = 0;
+ m_u.rds.first = first.m_type;
+ m_u.rds.second = second.m_type;
+ }
+
+ union {
+ struct {
+ ResultType::Type first;
+ ResultType::Type second;
+ } rds;
+ int i;
+ } m_u;
+
+ ResultType first()
+ {
+ return ResultType(m_u.rds.first);
+ }
+
+ ResultType second()
+ {
+ return ResultType(m_u.rds.second);
+ }
+
+ int toInt()
+ {
+ return m_u.i;
+ }
+ static OperandTypes fromInt(int value)
+ {
+ OperandTypes types;
+ types.m_u.i = value;
+ return types;
+ }
+ };
+
+} // namespace JSC
+
+#endif // ResultType_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceCode_h
+#define SourceCode_h
+
+#include "SourceProvider.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class SourceCode {
+ public:
+ SourceCode()
+ : m_startChar(0)
+ , m_endChar(0)
+ , m_firstLine(0)
+ {
+ }
+
+ SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1)
+ : m_provider(provider)
+ , m_startChar(0)
+ , m_endChar(m_provider->length())
+ , m_firstLine(std::max(firstLine, 1))
+ {
+ }
+
+ SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine)
+ : m_provider(provider)
+ , m_startChar(start)
+ , m_endChar(end)
+ , m_firstLine(std::max(firstLine, 1))
+ {
+ }
+
+ UString toString() const
+ {
+ if (!m_provider)
+ return UString();
+ return m_provider->getRange(m_startChar, m_endChar);
+ }
+
+ bool isNull() const { return !m_provider; }
+ SourceProvider* provider() const { return m_provider.get(); }
+ int firstLine() const { return m_firstLine; }
+ int startOffset() const { return m_startChar; }
+ int endOffset() const { return m_endChar; }
+ const UChar* data() const { return m_provider->data() + m_startChar; }
+ int length() const { return m_endChar - m_startChar; }
+
+ private:
+ RefPtr<SourceProvider> m_provider;
+ int m_startChar;
+ int m_endChar;
+ int m_firstLine;
+ };
+
+ inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 1)
+ {
+ return SourceCode(UStringSourceProvider::create(source, url), firstLine);
+ }
+
+} // namespace JSC
+
+#endif // SourceCode_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceProvider_h
+#define SourceProvider_h
+
+#include "UString.h"
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+ class SourceProvider : public RefCounted<SourceProvider> {
+ public:
+ SourceProvider(const UString& url)
+ : m_url(url)
+ {
+ }
+ virtual ~SourceProvider() { }
+
+ virtual UString getRange(int start, int end) const = 0;
+ virtual const UChar* data() const = 0;
+ virtual int length() const = 0;
+
+ const UString& url() { return m_url; }
+ intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
+
+ private:
+ UString m_url;
+ };
+
+ class UStringSourceProvider : public SourceProvider {
+ public:
+ static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url)
+ {
+ return adoptRef(new UStringSourceProvider(source, url));
+ }
+
+ UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
+ const UChar* data() const { return m_source.data(); }
+ int length() const { return m_source.size(); }
+
+ private:
+ UStringSourceProvider(const UString& source, const UString& url)
+ : SourceProvider(url)
+ , m_source(source)
+ {
+ }
+
+ UString m_source;
+ };
+
+} // namespace JSC
+
+#endif // SourceProvider_h
#
# Originally written by Philip Hazel
# Copyright (c) 1997-2006 University of Cambridge
-# Copyright (C) 2002, 2004, 2006, 2007, 2008 Apple Inc. All rights reserved.
+# Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
#
# -----------------------------------------------------------------------------
# Redistribution and use in source and binary forms, with or without
use File::Basename;
use File::Spec;
-use File::Temp;
+use File::Temp qw(tempfile);
+use Getopt::Long;
sub readHeaderValues();
my %pcre_internal;
-if (scalar(@ARGV) != 1) {
- print STDERR "Usage: ", basename($0), " output-file\n";
+if (scalar(@ARGV) < 1) {
+ print STDERR "Usage: ", basename($0), " [--preprocessor=program] output-file\n";
exit 1;
}
-my $outputFile = shift @ARGV;
+my $outputFile;
+my $preprocessor;
+GetOptions('preprocessor=s' => \$preprocessor);
+if (not $preprocessor) {
+ $preprocessor = "cpp";
+}
+
+$outputFile = $ARGV[0];
+die('Must specify output file.') unless defined($outputFile);
readHeaderValues();
"This file contains the default tables for characters with codes less than\n" .
"128 (ASCII characters). These tables are used when no external tables are\n" .
"passed to PCRE. */\n\n" .
- "const unsigned char kjs_pcre_default_tables[%d] = {\n\n" .
+ "const unsigned char jsc_pcre_default_tables[%d] = {\n\n" .
"/* This table is a lower casing table. */\n\n", $pcre_internal{tables_length});
if ($pcre_internal{lcc_offset} != 0) {
local $/ = undef;
my $headerPath = File::Spec->catfile(dirname($0), "pcre_internal.h");
-
- my $fh = new File::Temp(
+
+ my ($fh, $tempFile) = tempfile(
+ basename($0) . "-XXXXXXXX",
DIR => ($ENV{'TMPDIR'} || "/tmp"),
SUFFIX => ".in",
- TEMPLATE => basename($0) . "-XXXXXXXX",
UNLINK => 0,
);
- my $tempFile = $fh->filename();
print $fh "#define DFTABLES\n\n";
close($fh);
- open(CPP, "cpp '$tempFile' |") or die "$!";
+ open(CPP, "$preprocessor \"$tempFile\" |") or die "$!";
my $content = <CPP>;
close(CPP);
-
+
eval $content;
die "$@" if $@;
}
const int JSRegExpErrorNoMemory = -3;
const int JSRegExpErrorInternal = -4;
-JSRegExp* jsRegExpCompile(const ::UChar* pattern, int patternLength,
+JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
JSRegExpIgnoreCaseOption, JSRegExpMultilineOption,
unsigned* numSubpatterns, const char** errorMessage);
int jsRegExpExecute(const JSRegExp*,
- const ::UChar* subject, int subjectLength, int startOffset,
+ const UChar* subject, int subjectLength, int startOffset,
int* offsetsVector, int offsetsVectorLength);
void jsRegExpFree(JSRegExp*);
# Perl Compatible Regular Expressions - Qt4 build info
VPATH += $$PWD
-INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/kjs/tmp
+INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp
DEPENDPATH += $$PWD
isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
}
# GENERATOR: "chartables.c": compile and execute the chartables generator (and add it to sources)
+win32-msvc*|wince*: PREPROCESSOR = "--preprocessor=\"$$QMAKE_CC /E\""
DFTABLES = $$PWD/dftables
ctgen.input = DFTABLES
ctgen.output = $$GENERATED_SOURCES_DIR/chartables.c
-ctgen.commands = perl $$DFTABLES ${QMAKE_FILE_OUT}
+ctgen.commands = perl $$DFTABLES ${QMAKE_FILE_OUT} $$PREPROCESSOR
ctgen.CONFIG += target_predeps no_link
ctgen.variable_out = GENERATED_SOURCES
ctgen.dependency_type = TYPE_C
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-----------------------------------------------------------------------------
struct CompileData {
CompileData() {
- top_backref = 0;
+ topBackref = 0;
backrefMap = 0;
- req_varyopt = 0;
+ reqVaryOpt = 0;
needOuterBracket = false;
numCapturingBrackets = 0;
}
- int top_backref; /* Maximum back reference */
+ int topBackref; /* Maximum back reference */
unsigned backrefMap; /* Bitmap of low back refs */
- int req_varyopt; /* "After variable item" flag for reqbyte */
+ int reqVaryOpt; /* "After variable item" flag for reqByte */
bool needOuterBracket;
int numCapturingBrackets;
};
the \. On exit, it is on the final character of the escape sequence.
Arguments:
- ptrptr points to the pattern position pointer
- errorcodeptr points to the errorcode variable
+ ptrPtr points to the pattern position pointer
+ errorCodePtr points to the errorcode variable
bracount number of previous extracting brackets
options the options bits
- isclass true if inside a character class
+ isClass true if inside a character class
Returns: zero or positive => a data character
negative => a special escape sequence
- on error, errorptr is set
+ on error, errorPtr is set
*/
-static int checkEscape(const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int bracount, bool isclass)
+static int checkEscape(const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int bracount, bool isClass)
{
- const UChar* ptr = *ptrptr + 1;
+ const UChar* ptr = *ptrPtr + 1;
/* If backslash is at the end of the pattern, it's an error. */
if (ptr == patternEnd) {
- *errorcodeptr = ERR1;
- *ptrptr = ptr;
+ *errorCodePtr = ERR1;
+ *ptrPtr = ptr;
return 0;
}
if (c < '0' || c > 'z') { /* Not alphameric */
} else if (int escapeValue = escapes[c - '0']) {
c = escapeValue;
- if (isclass) {
+ if (isClass) {
if (-c == ESC_b)
c = '\b'; /* \b is backslash in a class */
else if (-c == ESC_B)
escape sequences. Those sequences end on the first non-octal character
or when we overflow 0-255, whichever comes first. */
- if (!isclass) {
+ if (!isClass) {
const UChar* oldptr = ptr;
c -= '0';
while ((ptr + 1 < patternEnd) && isASCIIDigit(ptr[1]) && c <= bracount)
/* Handle an octal number following \. If the first digit is 8 or 9,
this is not octal. */
- if ((c = *ptr) >= '8')
+ if ((c = *ptr) >= '8') {
+ c = '\\';
+ ptr -= 1;
break;
+ }
/* \0 always starts an octal number, but we may drop through to here with a
larger first octal digit. */
case 'c':
if (++ptr == patternEnd) {
- *errorcodeptr = ERR2;
+ *errorCodePtr = ERR2;
return 0;
}
- c = *ptr;
+ c = *ptr;
+
+ /* To match Firefox, inside a character class, we also accept
+ numbers and '_' as control characters */
+ if ((!isClass && !isASCIIAlpha(c)) || (!isASCIIAlphanumeric(c) && c != '_')) {
+ c = '\\';
+ ptr -= 2;
+ break;
+ }
+
/* A letter is upper-cased; then the 0x40 bit is flipped. This coding
is ASCII-specific, but then the whole concept of \cx is ASCII-specific. */
c = toASCIIUpper(c) ^ 0x40;
}
}
- *ptrptr = ptr;
+ *ptrPtr = ptr;
return c;
}
minp pointer to int for min
maxp pointer to int for max
returned as -1 if no max
- errorcodeptr points to error code variable
+ errorCodePtr points to error code variable
Returns: pointer to '}' on success;
- current ptr on error, with errorcodeptr set non-zero
+ current ptr on error, with errorCodePtr set non-zero
*/
-static const UChar* readRepeatCounts(const UChar* p, int* minp, int* maxp, ErrorCode* errorcodeptr)
+static const UChar* readRepeatCounts(const UChar* p, int* minp, int* maxp, ErrorCode* errorCodePtr)
{
int min = 0;
int max = -1;
while (isASCIIDigit(*p))
min = min * 10 + *p++ - '0';
if (min < 0 || min > 65535) {
- *errorcodeptr = ERR5;
+ *errorCodePtr = ERR5;
return p;
}
while (isASCIIDigit(*p))
max = max * 10 + *p++ - '0';
if (max < 0 || max > 65535) {
- *errorcodeptr = ERR5;
+ *errorCodePtr = ERR5;
return p;
}
if (max < min) {
- *errorcodeptr = ERR4;
+ *errorCodePtr = ERR4;
return p;
}
}
int c, othercase = 0;
for (c = *cptr; c <= d; c++) {
- if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0)
+ if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0)
break;
}
int next = othercase + 1;
for (++c; c <= d; c++) {
- if (kjs_pcre_ucp_othercase(c) != next)
+ if (jsc_pcre_ucp_othercase(c) != next)
break;
next++;
}
static int encodeUTF8(int cvalue, unsigned char *buffer)
{
int i;
- for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
- if (cvalue <= kjs_pcre_utf8_table1[i])
+ for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
+ if (cvalue <= jsc_pcre_utf8_table1[i])
break;
buffer += i;
for (int j = i; j > 0; j--) {
*buffer-- = 0x80 | (cvalue & 0x3f);
cvalue >>= 6;
}
- *buffer = kjs_pcre_utf8_table2[i] | cvalue;
+ *buffer = jsc_pcre_utf8_table2[i] | cvalue;
return i + 1;
}
Arguments:
options the option bits
brackets points to number of extracting brackets used
- codeptr points to the pointer to the current code point
- ptrptr points to the current pattern pointer
- errorcodeptr points to error code variable
+ codePtr points to the pointer to the current code point
+ ptrPtr points to the current pattern pointer
+ errorCodePtr points to error code variable
firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
reqbyteptr set to the last literal character required, else < 0
cd contains pointers to tables etc.
Returns: true on success
- false, with *errorcodeptr set non-zero on error
+ false, with *errorCodePtr set non-zero on error
*/
static inline bool safelyCheckNextChar(const UChar* ptr, const UChar* patternEnd, UChar expected)
}
static bool
-compileBranch(int options, int* brackets, unsigned char** codeptr,
- const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int *firstbyteptr,
+compileBranch(int options, int* brackets, unsigned char** codePtr,
+ const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int *firstbyteptr,
int* reqbyteptr, CompileData& cd)
{
- int repeat_type, op_type;
- int repeat_min = 0, repeat_max = 0; /* To please picky compilers */
+ int repeatType, opType;
+ int repeatMin = 0, repeat_max = 0; /* To please picky compilers */
int bravalue = 0;
int reqvary, tempreqvary;
int c;
- unsigned char* code = *codeptr;
+ unsigned char* code = *codePtr;
unsigned char* tempcode;
- bool groupsetfirstbyte = false;
- const UChar* ptr = *ptrptr;
+ bool didGroupSetFirstByte = false;
+ const UChar* ptr = *ptrPtr;
const UChar* tempptr;
unsigned char* previous = NULL;
unsigned char classbits[32];
/* Initialize no first byte, no required byte. REQ_UNSET means "no char
matching encountered yet". It gets changed to REQ_NONE if we hit something that
- matches a non-fixed char first char; reqbyte just remains unset if we never
+ matches a non-fixed char first char; reqByte just remains unset if we never
find one.
When we hit a repeat whose minimum is zero, we may have to adjust these values
to take the zero repeat into account. This is implemented by setting them to
- zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual
+ zeroFirstByte and zeroReqByte when such a repeat is encountered. The individual
item types that can be repeated set these backoff variables appropriately. */
- int firstbyte = REQ_UNSET;
- int reqbyte = REQ_UNSET;
- int zeroreqbyte = REQ_UNSET;
- int zerofirstbyte = REQ_UNSET;
+ int firstByte = REQ_UNSET;
+ int reqByte = REQ_UNSET;
+ int zeroReqByte = REQ_UNSET;
+ int zeroFirstByte = REQ_UNSET;
- /* The variable req_caseopt contains either the REQ_IGNORE_CASE value or zero,
+ /* The variable reqCaseOpt contains either the REQ_IGNORE_CASE value or zero,
according to the current setting of the ignores-case flag. REQ_IGNORE_CASE is a bit
- value > 255. It is added into the firstbyte or reqbyte variables to record the
+ value > 255. It is added into the firstByte or reqByte variables to record the
case status of the value. This is used only for ASCII characters. */
- int req_caseopt = (options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0;
+ int reqCaseOpt = (options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0;
/* Switch on next character until the end of the branch */
for (;; ptr++) {
- bool negate_class;
- bool should_flip_negation; /* If a negative special such as \S is used, we should negate the whole class to properly support Unicode. */
- int class_charcount;
- int class_lastchar;
- int skipbytes;
- int subreqbyte;
- int subfirstbyte;
- int mclength;
+ bool negateClass;
+ bool shouldFlipNegation; /* If a negative special such as \S is used, we should negate the whole class to properly support Unicode. */
+ int classCharCount;
+ int classLastChar;
+ int skipBytes;
+ int subReqByte;
+ int subFirstByte;
+ int mcLength;
unsigned char mcbuffer[8];
/* Next byte in the pattern */
/* Fill in length of a previous callout, except when the next thing is
a quantifier. */
- bool is_quantifier = c == '*' || c == '+' || c == '?' || (c == '{' && isCountedRepeat(ptr + 1, patternEnd));
+ bool isQuantifier = c == '*' || c == '+' || c == '?' || (c == '{' && isCountedRepeat(ptr + 1, patternEnd));
switch (c) {
/* The branch terminates at end of string, |, or ). */
// End of string; fall through
case '|':
case ')':
- *firstbyteptr = firstbyte;
- *reqbyteptr = reqbyte;
- *codeptr = code;
- *ptrptr = ptr;
+ *firstbyteptr = firstByte;
+ *reqbyteptr = reqByte;
+ *codePtr = code;
+ *ptrPtr = ptr;
return true;
/* Handle single-character metacharacters. In multiline mode, ^ disables
the setting of any following char as a first character. */
-
+
case '^':
if (options & MatchAcrossMultipleLinesOption) {
- if (firstbyte == REQ_UNSET)
- firstbyte = REQ_NONE;
- }
+ if (firstByte == REQ_UNSET)
+ firstByte = REQ_NONE;
+ *code++ = OP_BOL;
+ } else
+ *code++ = OP_CIRC;
previous = NULL;
- *code++ = OP_CIRC;
break;
-
+
case '$':
previous = NULL;
- *code++ = OP_DOLL;
+ if (options & MatchAcrossMultipleLinesOption)
+ *code++ = OP_EOL;
+ else
+ *code++ = OP_DOLL;
break;
-
+
/* There can never be a first char if '.' is first, whatever happens about
- repeats. The value of reqbyte doesn't change either. */
-
+ repeats. The value of reqByte doesn't change either. */
+
case '.':
- if (firstbyte == REQ_UNSET)
- firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
+ if (firstByte == REQ_UNSET)
+ firstByte = REQ_NONE;
+ zeroFirstByte = firstByte;
+ zeroReqByte = reqByte;
previous = code;
*code++ = OP_NOT_NEWLINE;
break;
case '[': {
previous = code;
- should_flip_negation = false;
+ shouldFlipNegation = false;
/* PCRE supports POSIX class stuff inside a class. Perl gives an error if
they are encountered at the top level, so we'll do that too. */
/* If the first character is '^', set the negation flag and skip it. */
if (ptr + 1 >= patternEnd) {
- *errorcodeptr = ERR6;
+ *errorCodePtr = ERR6;
return false;
}
if (ptr[1] == '^') {
- negate_class = true;
+ negateClass = true;
++ptr;
} else
- negate_class = false;
+ negateClass = false;
/* Keep a count of chars with values < 256 so that we can optimize the case
of just a single character (as long as it's < 256). For higher valued UTF-8
characters, we don't yet do any optimization. */
- class_charcount = 0;
- class_lastchar = -1;
+ classCharCount = 0;
+ classLastChar = -1;
class_utf8 = false; /* No chars >= 256 */
class_utf8data = code + LINK_SIZE + 34; /* For UTF-8 items */
Inside a class (and only there) it is treated as backspace. Elsewhere
it marks a word boundary. Other escapes have preset maps ready to
or into the one we are building. We assume they have more than one
- character in them, so set class_charcount bigger than one. */
+ character in them, so set classCharCount bigger than one. */
if (c == '\\') {
- c = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, true);
+ c = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, true);
if (c < 0) {
- class_charcount += 2; /* Greater than 1 is what matters */
+ classCharCount += 2; /* Greater than 1 is what matters */
switch (-c) {
case ESC_d:
for (c = 0; c < 32; c++)
continue;
case ESC_D:
- should_flip_negation = true;
+ shouldFlipNegation = true;
for (c = 0; c < 32; c++)
classbits[c] |= ~classBitmapForChar(c + cbit_digit);
continue;
continue;
case ESC_W:
- should_flip_negation = true;
+ shouldFlipNegation = true;
for (c = 0; c < 32; c++)
classbits[c] |= ~classBitmapForChar(c + cbit_word);
continue;
continue;
case ESC_S:
- should_flip_negation = true;
+ shouldFlipNegation = true;
for (c = 0; c < 32; c++)
classbits[c] |= ~classBitmapForChar(c + cbit_space);
continue;
default:
c = *ptr; /* The final character */
- class_charcount -= 2; /* Undo the default count from above */
+ classCharCount -= 2; /* Undo the default count from above */
}
}
if (d == '\\') {
const UChar* oldptr = ptr;
- d = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, true);
+ d = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, true);
/* \X is literal X; any other special means the '-' was literal */
if (d < 0) {
int uc = flipCase(c);
classbits[uc/8] |= (1 << (uc&7));
}
- class_charcount++; /* in case a one-char range */
- class_lastchar = c;
+ classCharCount++; /* in case a one-char range */
+ classLastChar = c;
}
continue; /* Go get the next char in the class */
if (options & IgnoreCaseOption) {
int othercase;
- if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0) {
+ if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0) {
*class_utf8data++ = XCL_SINGLE;
class_utf8data += encodeUTF8(othercase, class_utf8data);
}
c = flipCase(c);
classbits[c/8] |= (1 << (c&7));
}
- class_charcount++;
- class_lastchar = c;
+ classCharCount++;
+ classLastChar = c;
}
}
- /* If class_charcount is 1, we saw precisely one character whose value is
+ /* If classCharCount is 1, we saw precisely one character whose value is
less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we
can optimize the negative case only if there were no characters >= 128
because OP_NOT and the related opcodes like OP_NOTSTAR operate on
The optimization throws away the bit map. We turn the item into a
1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
that OP_NOT does not support multibyte characters. In the positive case, it
- can cause firstbyte to be set. Otherwise, there can be no first char if
+ can cause firstByte to be set. Otherwise, there can be no first char if
this item is first, whatever repeat count may follow. In the case of
- reqbyte, save the previous value for reinstating. */
+ reqByte, save the previous value for reinstating. */
- if (class_charcount == 1 && (!class_utf8 && (!negate_class || class_lastchar < 128))) {
- zeroreqbyte = reqbyte;
+ if (classCharCount == 1 && (!class_utf8 && (!negateClass || classLastChar < 128))) {
+ zeroReqByte = reqByte;
/* The OP_NOT opcode works on one-byte characters only. */
- if (negate_class) {
- if (firstbyte == REQ_UNSET)
- firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
+ if (negateClass) {
+ if (firstByte == REQ_UNSET)
+ firstByte = REQ_NONE;
+ zeroFirstByte = firstByte;
*code++ = OP_NOT;
- *code++ = class_lastchar;
+ *code++ = classLastChar;
break;
}
/* For a single, positive character, get the value into c, and
then we can handle this with the normal one-character code. */
- c = class_lastchar;
+ c = classLastChar;
goto NORMAL_CHAR;
} /* End of 1-char optimization */
/* The general case - not the one-char optimization. If this is the first
thing in the branch, there can be no first char setting, whatever the
- repeat count. Any reqbyte setting must remain unchanged after any kind of
+ repeat count. Any reqByte setting must remain unchanged after any kind of
repeat. */
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
+ if (firstByte == REQ_UNSET) firstByte = REQ_NONE;
+ zeroFirstByte = firstByte;
+ zeroReqByte = reqByte;
/* If there are characters with values > 255, we have to compile an
extended class, with its own opcode. If there are no characters < 256,
we can omit the bitmap. */
- if (class_utf8 && !should_flip_negation) {
+ if (class_utf8 && !shouldFlipNegation) {
*class_utf8data++ = XCL_END; /* Marks the end of extra data */
*code++ = OP_XCLASS;
code += LINK_SIZE;
- *code = negate_class? XCL_NOT : 0;
+ *code = negateClass? XCL_NOT : 0;
/* If the map is required, install it, and move on to the end of
the extra data */
- if (class_charcount > 0) {
+ if (classCharCount > 0) {
*code++ |= XCL_MAP;
memcpy(code, classbits, 32);
code = class_utf8data;
/* If there are no characters > 255, negate the 32-byte map if necessary,
and copy it into the code vector. If this is the first thing in the branch,
- there can be no first char setting, whatever the repeat count. Any reqbyte
+ there can be no first char setting, whatever the repeat count. Any reqByte
setting must remain unchanged after any kind of repeat. */
- *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
- if (negate_class)
+ *code++ = (negateClass == shouldFlipNegation) ? OP_CLASS : OP_NCLASS;
+ if (negateClass)
for (c = 0; c < 32; c++)
code[c] = ~classbits[c];
else
has been tested above. */
case '{':
- if (!is_quantifier)
+ if (!isQuantifier)
goto NORMAL_CHAR;
- ptr = readRepeatCounts(ptr + 1, &repeat_min, &repeat_max, errorcodeptr);
- if (*errorcodeptr)
+ ptr = readRepeatCounts(ptr + 1, &repeatMin, &repeat_max, errorCodePtr);
+ if (*errorCodePtr)
goto FAILED;
goto REPEAT;
case '*':
- repeat_min = 0;
+ repeatMin = 0;
repeat_max = -1;
goto REPEAT;
case '+':
- repeat_min = 1;
+ repeatMin = 1;
repeat_max = -1;
goto REPEAT;
case '?':
- repeat_min = 0;
+ repeatMin = 0;
repeat_max = 1;
REPEAT:
if (!previous) {
- *errorcodeptr = ERR9;
+ *errorCodePtr = ERR9;
goto FAILED;
}
- if (repeat_min == 0) {
- firstbyte = zerofirstbyte; /* Adjust for zero repeat */
- reqbyte = zeroreqbyte; /* Ditto */
+ if (repeatMin == 0) {
+ firstByte = zeroFirstByte; /* Adjust for zero repeat */
+ reqByte = zeroReqByte; /* Ditto */
}
/* Remember whether this is a variable length repeat */
- reqvary = (repeat_min == repeat_max) ? 0 : REQ_VARY;
+ reqvary = (repeatMin == repeat_max) ? 0 : REQ_VARY;
- op_type = 0; /* Default single-char op codes */
+ opType = 0; /* Default single-char op codes */
/* Save start of previous item, in case we have to move it up to make space
for an inserted OP_ONCE for the additional '+' extension. */
repeat type to the non-default. */
if (safelyCheckNextChar(ptr, patternEnd, '?')) {
- repeat_type = 1;
+ repeatType = 1;
ptr++;
} else
- repeat_type = 0;
+ repeatType = 0;
/* If previous was a character match, abolish the item and generate a
repeat item instead. If a char item has a minumum of more than one, ensure
- that it is set in reqbyte - it might not be if a sequence such as x{3} is
- the first thing in a branch because the x will have gone into firstbyte
+ that it is set in reqByte - it might not be if a sequence such as x{3} is
+ the first thing in a branch because the x will have gone into firstByte
instead. */
if (*previous == OP_CHAR || *previous == OP_CHAR_IGNORING_CASE) {
}
else {
c = code[-1];
- if (repeat_min > 1)
- reqbyte = c | req_caseopt | cd.req_varyopt;
+ if (repeatMin > 1)
+ reqByte = c | reqCaseOpt | cd.reqVaryOpt;
}
goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
else if (*previous == OP_ASCII_CHAR || *previous == OP_ASCII_LETTER_IGNORING_CASE) {
c = previous[1];
- if (repeat_min > 1)
- reqbyte = c | req_caseopt | cd.req_varyopt;
+ if (repeatMin > 1)
+ reqByte = c | reqCaseOpt | cd.reqVaryOpt;
goto OUTPUT_SINGLE_REPEAT;
}
/* If previous was a single negated character ([^a] or similar), we use
one of the special opcodes, replacing it. The code is shared with single-
character repeats by setting opt_type to add a suitable offset into
- repeat_type. OP_NOT is currently used only for single-byte chars. */
+ repeatType. OP_NOT is currently used only for single-byte chars. */
else if (*previous == OP_NOT) {
- op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
+ opType = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
c = previous[1];
goto OUTPUT_SINGLE_REPEAT;
}
/* If previous was a character type match (\d or similar), abolish it and
create a suitable repeat item. The code is shared with single-character
- repeats by setting op_type to add a suitable offset into repeat_type. */
+ repeats by setting opType to add a suitable offset into repeatType. */
else if (*previous <= OP_NOT_NEWLINE) {
- op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
+ opType = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
c = *previous;
OUTPUT_SINGLE_REPEAT:
if (repeat_max == 0)
goto END_REPEAT;
- /* Combine the op_type with the repeat_type */
+ /* Combine the opType with the repeatType */
- repeat_type += op_type;
+ repeatType += opType;
/* A minimum of zero is handled either as the special case * or ?, or as
an UPTO, with the maximum given. */
- if (repeat_min == 0) {
+ if (repeatMin == 0) {
if (repeat_max == -1)
- *code++ = OP_STAR + repeat_type;
+ *code++ = OP_STAR + repeatType;
else if (repeat_max == 1)
- *code++ = OP_QUERY + repeat_type;
+ *code++ = OP_QUERY + repeatType;
else {
- *code++ = OP_UPTO + repeat_type;
+ *code++ = OP_UPTO + repeatType;
put2ByteValueAndAdvance(code, repeat_max);
}
}
left in place and, if the maximum is greater than 1, we use OP_UPTO with
one less than the maximum. */
- else if (repeat_min == 1) {
+ else if (repeatMin == 1) {
if (repeat_max == -1)
- *code++ = OP_PLUS + repeat_type;
+ *code++ = OP_PLUS + repeatType;
else {
code = oldcode; /* leave previous item in place */
if (repeat_max == 1)
goto END_REPEAT;
- *code++ = OP_UPTO + repeat_type;
+ *code++ = OP_UPTO + repeatType;
put2ByteValueAndAdvance(code, repeat_max - 1);
}
}
handled as an EXACT followed by an UPTO. */
else {
- *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
- put2ByteValueAndAdvance(code, repeat_min);
+ *code++ = OP_EXACT + opType; /* NB EXACT doesn't have repeatType */
+ put2ByteValueAndAdvance(code, repeatMin);
/* If the maximum is unlimited, insert an OP_STAR. Before doing so,
we have to insert the character for the previous code. For a repeated
*code++ = prop_value;
}
}
- *code++ = OP_STAR + repeat_type;
+ *code++ = OP_STAR + repeatType;
}
/* Else insert an UPTO if the max is greater than the min, again
preceded by the character, for the previously inserted code. */
- else if (repeat_max != repeat_min) {
+ else if (repeat_max != repeatMin) {
if (c >= 128) {
memcpy(code, utf8_char, c & 7);
code += c & 7;
*code++ = prop_type;
*code++ = prop_value;
}
- repeat_max -= repeat_min;
- *code++ = OP_UPTO + repeat_type;
+ repeat_max -= repeatMin;
+ *code++ = OP_UPTO + repeatType;
put2ByteValueAndAdvance(code, repeat_max);
}
}
goto END_REPEAT;
}
- if (repeat_min == 0 && repeat_max == -1)
- *code++ = OP_CRSTAR + repeat_type;
- else if (repeat_min == 1 && repeat_max == -1)
- *code++ = OP_CRPLUS + repeat_type;
- else if (repeat_min == 0 && repeat_max == 1)
- *code++ = OP_CRQUERY + repeat_type;
+ if (repeatMin == 0 && repeat_max == -1)
+ *code++ = OP_CRSTAR + repeatType;
+ else if (repeatMin == 1 && repeat_max == -1)
+ *code++ = OP_CRPLUS + repeatType;
+ else if (repeatMin == 0 && repeat_max == 1)
+ *code++ = OP_CRQUERY + repeatType;
else {
- *code++ = OP_CRRANGE + repeat_type;
- put2ByteValueAndAdvance(code, repeat_min);
+ *code++ = OP_CRRANGE + repeatType;
+ put2ByteValueAndAdvance(code, repeatMin);
if (repeat_max == -1)
repeat_max = 0; /* 2-byte encoding for max */
put2ByteValueAndAdvance(code, repeat_max);
the code gets far too messy. There are several special subcases when the
minimum is zero. */
- if (repeat_min == 0) {
+ if (repeatMin == 0) {
/* If the maximum is also zero, we just omit the group from the output
altogether. */
*code = OP_END;
memmove(previous+1, previous, len);
code++;
- *previous++ = OP_BRAZERO + repeat_type;
+ *previous++ = OP_BRAZERO + repeatType;
}
/* If the maximum is greater than 1 and limited, we have to replicate
*code = OP_END;
memmove(previous + 2 + LINK_SIZE, previous, len);
code += 2 + LINK_SIZE;
- *previous++ = OP_BRAZERO + repeat_type;
+ *previous++ = OP_BRAZERO + repeatType;
*previous++ = OP_BRA;
/* We chain together the bracket offset fields that have to be
set a required char, copy the latter from the former. */
else {
- if (repeat_min > 1) {
- if (groupsetfirstbyte && reqbyte < 0)
- reqbyte = firstbyte;
- for (int i = 1; i < repeat_min; i++) {
+ if (repeatMin > 1) {
+ if (didGroupSetFirstByte && reqByte < 0)
+ reqByte = firstByte;
+ for (int i = 1; i < repeatMin; i++) {
memcpy(code, previous, len);
code += len;
}
}
if (repeat_max > 0)
- repeat_max -= repeat_min;
+ repeat_max -= repeatMin;
}
/* This code is common to both the zero and non-zero minimum cases. If
if (repeat_max >= 0) {
for (int i = repeat_max - 1; i >= 0; i--) {
- *code++ = OP_BRAZERO + repeat_type;
+ *code++ = OP_BRAZERO + repeatType;
/* All but the final copy start a new nesting, maintaining the
chain of brackets outstanding. */
correct offset was computed above. */
else
- code[-ketoffset] = OP_KETRMAX + repeat_type;
+ code[-ketoffset] = OP_KETRMAX + repeatType;
+ }
+
+ // A quantifier after an assertion is mostly meaningless, but it
+ // can nullify the assertion if it has a 0 minimum.
+ else if (*previous == OP_ASSERT || *previous == OP_ASSERT_NOT) {
+ if (repeatMin == 0) {
+ code = previous;
+ goto END_REPEAT;
+ }
}
/* Else there's some kind of shambles */
else {
- *errorcodeptr = ERR11;
+ *errorCodePtr = ERR11;
goto FAILED;
}
END_REPEAT:
previous = NULL;
- cd.req_varyopt |= reqvary;
+ cd.reqVaryOpt |= reqvary;
break;
/* Start of nested bracket sub-expression, or comment or lookahead or
check for syntax errors here. */
case '(':
- skipbytes = 0;
+ skipBytes = 0;
if (*(++ptr) == '?') {
switch (*(++ptr)) {
/* Character after (? not specially recognized */
default:
- *errorcodeptr = ERR12;
+ *errorCodePtr = ERR12;
goto FAILED;
}
}
bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
code[1 + LINK_SIZE] = OP_BRANUMBER;
put2ByteValue(code + 2 + LINK_SIZE, *brackets);
- skipbytes = 3;
+ skipBytes = 3;
}
else
bravalue = OP_BRA + *brackets;
}
- /* Process nested bracketed re. Assertions may not be repeated, but other
- kinds can be. We copy code into a non-variable in order to be able
- to pass its address because some compilers complain otherwise. Pass in a
- new setting for the ims options if they have changed. */
+ /* Process nested bracketed re. We copy code into a non-variable
+ in order to be able to pass its address because some compilers
+ complain otherwise. Pass in a new setting for the ims options
+ if they have changed. */
- previous = (bravalue >= OP_BRAZERO) ? code : 0;
+ previous = code;
*code = bravalue;
tempcode = code;
- tempreqvary = cd.req_varyopt; /* Save value before bracket */
+ tempreqvary = cd.reqVaryOpt; /* Save value before bracket */
if (!compileBracket(
options,
&tempcode, /* Where to put code (updated) */
&ptr, /* Input pointer (updated) */
patternEnd,
- errorcodeptr, /* Where to put an error message */
- skipbytes, /* Skip over OP_BRANUMBER */
- &subfirstbyte, /* For possible first char */
- &subreqbyte, /* For possible last char */
+ errorCodePtr, /* Where to put an error message */
+ skipBytes, /* Skip over OP_BRANUMBER */
+ &subFirstByte, /* For possible first char */
+ &subReqByte, /* For possible last char */
cd)) /* Tables block */
goto FAILED;
/* Handle updating of the required and first characters. Update for normal
brackets of all kinds, and conditions with two branches (see code above).
If the bracket is followed by a quantifier with zero repeat, we have to
- back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the
+ back off. Hence the definition of zeroReqByte and zeroFirstByte outside the
main loop so that they can be accessed for the back off. */
- zeroreqbyte = reqbyte;
- zerofirstbyte = firstbyte;
- groupsetfirstbyte = false;
+ zeroReqByte = reqByte;
+ zeroFirstByte = firstByte;
+ didGroupSetFirstByte = false;
if (bravalue >= OP_BRA) {
- /* If we have not yet set a firstbyte in this branch, take it from the
+ /* If we have not yet set a firstByte in this branch, take it from the
subpattern, remembering that it was set here so that a repeat of more
- than one can replicate it as reqbyte if necessary. If the subpattern has
- no firstbyte, set "none" for the whole branch. In both cases, a zero
- repeat forces firstbyte to "none". */
-
- if (firstbyte == REQ_UNSET) {
- if (subfirstbyte >= 0) {
- firstbyte = subfirstbyte;
- groupsetfirstbyte = true;
+ than one can replicate it as reqByte if necessary. If the subpattern has
+ no firstByte, set "none" for the whole branch. In both cases, a zero
+ repeat forces firstByte to "none". */
+
+ if (firstByte == REQ_UNSET) {
+ if (subFirstByte >= 0) {
+ firstByte = subFirstByte;
+ didGroupSetFirstByte = true;
}
else
- firstbyte = REQ_NONE;
- zerofirstbyte = REQ_NONE;
+ firstByte = REQ_NONE;
+ zeroFirstByte = REQ_NONE;
}
- /* If firstbyte was previously set, convert the subpattern's firstbyte
- into reqbyte if there wasn't one, using the vary flag that was in
+ /* If firstByte was previously set, convert the subpattern's firstByte
+ into reqByte if there wasn't one, using the vary flag that was in
existence beforehand. */
- else if (subfirstbyte >= 0 && subreqbyte < 0)
- subreqbyte = subfirstbyte | tempreqvary;
+ else if (subFirstByte >= 0 && subReqByte < 0)
+ subReqByte = subFirstByte | tempreqvary;
/* If the subpattern set a required byte (or set a first byte that isn't
really the first byte - see above), set it. */
- if (subreqbyte >= 0)
- reqbyte = subreqbyte;
+ if (subReqByte >= 0)
+ reqByte = subReqByte;
}
- /* For a forward assertion, we take the reqbyte, if set. This can be
+ /* For a forward assertion, we take the reqByte, if set. This can be
helpful if the pattern that follows the assertion doesn't set a different
- char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte
+ char. For example, it's useful for /(?=abcde).+/. We can't set firstByte
for an assertion, however because it leads to incorrect effect for patterns
- such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead
- of a firstbyte. This is overcome by a scan at the end if there's no
- firstbyte, looking for an asserted first char. */
+ such as /(?=a)a.+/ when the "real" "a" would then become a reqByte instead
+ of a firstByte. This is overcome by a scan at the end if there's no
+ firstByte, looking for an asserted first char. */
- else if (bravalue == OP_ASSERT && subreqbyte >= 0)
- reqbyte = subreqbyte;
+ else if (bravalue == OP_ASSERT && subReqByte >= 0)
+ reqByte = subReqByte;
/* Now update the main code pointer to the end of the group. */
/* Error if hit end of pattern */
if (ptr >= patternEnd || *ptr != ')') {
- *errorcodeptr = ERR14;
+ *errorCodePtr = ERR14;
goto FAILED;
}
break;
case '\\':
tempptr = ptr;
- c = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, false);
+ c = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, false);
/* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
are arranged to be the negation of the corresponding OP_values. For the
/* For metasequences that actually match a character, we disable the
setting of a first character if it hasn't already been set. */
- if (firstbyte == REQ_UNSET && -c > ESC_b && -c <= ESC_w)
- firstbyte = REQ_NONE;
+ if (firstByte == REQ_UNSET && -c > ESC_b && -c <= ESC_w)
+ firstByte = REQ_NONE;
/* Set values to reset to if this is followed by a zero repeat. */
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
+ zeroFirstByte = firstByte;
+ zeroReqByte = reqByte;
/* Back references are handled specially */
previous = code;
if (c < 128) {
- mclength = 1;
+ mcLength = 1;
mcbuffer[0] = c;
if ((options & IgnoreCaseOption) && (c | 0x20) >= 'a' && (c | 0x20) <= 'z') {
*code++ = c;
}
} else {
- mclength = encodeUTF8(c, mcbuffer);
+ mcLength = encodeUTF8(c, mcbuffer);
*code++ = (options & IgnoreCaseOption) ? OP_CHAR_IGNORING_CASE : OP_CHAR;
- for (c = 0; c < mclength; c++)
+ for (c = 0; c < mcLength; c++)
*code++ = mcbuffer[c];
}
/* Set the first and required bytes appropriately. If no previous first
byte, set it from this character, but revert to none on a zero repeat.
- Otherwise, leave the firstbyte value alone, and don't change it on a zero
+ Otherwise, leave the firstByte value alone, and don't change it on a zero
repeat. */
- if (firstbyte == REQ_UNSET) {
- zerofirstbyte = REQ_NONE;
- zeroreqbyte = reqbyte;
+ if (firstByte == REQ_UNSET) {
+ zeroFirstByte = REQ_NONE;
+ zeroReqByte = reqByte;
- /* If the character is more than one byte long, we can set firstbyte
+ /* If the character is more than one byte long, we can set firstByte
only if it is not to be matched caselessly. */
- if (mclength == 1 || req_caseopt == 0) {
- firstbyte = mcbuffer[0] | req_caseopt;
- if (mclength != 1)
- reqbyte = code[-1] | cd.req_varyopt;
+ if (mcLength == 1 || reqCaseOpt == 0) {
+ firstByte = mcbuffer[0] | reqCaseOpt;
+ if (mcLength != 1)
+ reqByte = code[-1] | cd.reqVaryOpt;
}
else
- firstbyte = reqbyte = REQ_NONE;
+ firstByte = reqByte = REQ_NONE;
}
- /* firstbyte was previously set; we can set reqbyte only the length is
+ /* firstByte was previously set; we can set reqByte only the length is
1 or the matching is caseful. */
else {
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
- if (mclength == 1 || req_caseopt == 0)
- reqbyte = code[-1] | req_caseopt | cd.req_varyopt;
+ zeroFirstByte = firstByte;
+ zeroReqByte = reqByte;
+ if (mcLength == 1 || reqCaseOpt == 0)
+ reqByte = code[-1] | reqCaseOpt | cd.reqVaryOpt;
}
break; /* End of literal character handling */
to the user for diagnosing the error. */
FAILED:
- *ptrptr = ptr;
+ *ptrPtr = ptr;
return false;
}
Argument:
options option bits, including any changes for this subpattern
brackets -> int containing the number of extracting brackets used
- codeptr -> the address of the current code pointer
- ptrptr -> the address of the current pattern pointer
- errorcodeptr -> pointer to error code variable
- skipbytes skip this many bytes at start (for OP_BRANUMBER)
+ codePtr -> the address of the current code pointer
+ ptrPtr -> the address of the current pattern pointer
+ errorCodePtr -> pointer to error code variable
+ skipBytes skip this many bytes at start (for OP_BRANUMBER)
firstbyteptr place to put the first required character, or a negative number
reqbyteptr place to put the last required character, or a negative number
cd points to the data block with tables pointers etc.
*/
static bool
-compileBracket(int options, int* brackets, unsigned char** codeptr,
- const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int skipbytes,
+compileBracket(int options, int* brackets, unsigned char** codePtr,
+ const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int skipBytes,
int* firstbyteptr, int* reqbyteptr, CompileData& cd)
{
- const UChar* ptr = *ptrptr;
- unsigned char* code = *codeptr;
- unsigned char* last_branch = code;
+ const UChar* ptr = *ptrPtr;
+ unsigned char* code = *codePtr;
+ unsigned char* lastBranch = code;
unsigned char* start_bracket = code;
- int firstbyte = REQ_UNSET;
- int reqbyte = REQ_UNSET;
+ int firstByte = REQ_UNSET;
+ int reqByte = REQ_UNSET;
/* Offset is set zero to mark that this bracket is still open */
putLinkValueAllowZero(code + 1, 0);
- code += 1 + LINK_SIZE + skipbytes;
+ code += 1 + LINK_SIZE + skipBytes;
/* Loop for each alternative branch */
while (true) {
/* Now compile the branch */
- int branchfirstbyte;
- int branchreqbyte;
- if (!compileBranch(options, brackets, &code, &ptr, patternEnd, errorcodeptr,
- &branchfirstbyte, &branchreqbyte, cd)) {
- *ptrptr = ptr;
+ int branchFirstByte;
+ int branchReqByte;
+ if (!compileBranch(options, brackets, &code, &ptr, patternEnd, errorCodePtr,
+ &branchFirstByte, &branchReqByte, cd)) {
+ *ptrPtr = ptr;
return false;
}
- /* If this is the first branch, the firstbyte and reqbyte values for the
+ /* If this is the first branch, the firstByte and reqByte values for the
branch become the values for the regex. */
- if (*last_branch != OP_ALT) {
- firstbyte = branchfirstbyte;
- reqbyte = branchreqbyte;
+ if (*lastBranch != OP_ALT) {
+ firstByte = branchFirstByte;
+ reqByte = branchReqByte;
}
- /* If this is not the first branch, the first char and reqbyte have to
+ /* If this is not the first branch, the first char and reqByte have to
match the values from all the previous branches, except that if the previous
- value for reqbyte didn't have REQ_VARY set, it can still match, and we set
+ value for reqByte didn't have REQ_VARY set, it can still match, and we set
REQ_VARY for the regex. */
else {
- /* If we previously had a firstbyte, but it doesn't match the new branch,
- we have to abandon the firstbyte for the regex, but if there was previously
- no reqbyte, it takes on the value of the old firstbyte. */
+ /* If we previously had a firstByte, but it doesn't match the new branch,
+ we have to abandon the firstByte for the regex, but if there was previously
+ no reqByte, it takes on the value of the old firstByte. */
- if (firstbyte >= 0 && firstbyte != branchfirstbyte) {
- if (reqbyte < 0)
- reqbyte = firstbyte;
- firstbyte = REQ_NONE;
+ if (firstByte >= 0 && firstByte != branchFirstByte) {
+ if (reqByte < 0)
+ reqByte = firstByte;
+ firstByte = REQ_NONE;
}
- /* If we (now or from before) have no firstbyte, a firstbyte from the
- branch becomes a reqbyte if there isn't a branch reqbyte. */
+ /* If we (now or from before) have no firstByte, a firstByte from the
+ branch becomes a reqByte if there isn't a branch reqByte. */
- if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0)
- branchreqbyte = branchfirstbyte;
+ if (firstByte < 0 && branchFirstByte >= 0 && branchReqByte < 0)
+ branchReqByte = branchFirstByte;
/* Now ensure that the reqbytes match */
- if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY))
- reqbyte = REQ_NONE;
+ if ((reqByte & ~REQ_VARY) != (branchReqByte & ~REQ_VARY))
+ reqByte = REQ_NONE;
else
- reqbyte |= branchreqbyte; /* To "or" REQ_VARY */
+ reqByte |= branchReqByte; /* To "or" REQ_VARY */
}
/* Reached end of expression, either ')' or end of pattern. Go back through
at the terminating char. */
if (ptr >= patternEnd || *ptr != '|') {
- int length = code - last_branch;
+ int length = code - lastBranch;
do {
- int prev_length = getLinkValueAllowZero(last_branch + 1);
- putLinkValue(last_branch + 1, length);
- length = prev_length;
- last_branch -= length;
+ int prevLength = getLinkValueAllowZero(lastBranch + 1);
+ putLinkValue(lastBranch + 1, length);
+ length = prevLength;
+ lastBranch -= length;
} while (length > 0);
/* Fill in the ket */
/* Set values to pass back */
- *codeptr = code;
- *ptrptr = ptr;
- *firstbyteptr = firstbyte;
- *reqbyteptr = reqbyte;
+ *codePtr = code;
+ *ptrPtr = ptr;
+ *firstbyteptr = firstByte;
+ *reqbyteptr = reqByte;
return true;
}
zero offset until it is closed, making it possible to detect recursion. */
*code = OP_ALT;
- putLinkValue(code + 1, code - last_branch);
- last_branch = code;
+ putLinkValue(code + 1, code - lastBranch);
+ lastBranch = code;
code += 1 + LINK_SIZE;
ptr++;
}
return scode[1] == OP_NOT_NEWLINE && !(captureMap & backrefMap);
/* Explicit ^ */
- return op == OP_CIRC;
+ return op == OP_CIRC || op == OP_BOL;
}
static bool bracketNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap)
if (c > 127) {
int i;
- for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
- if (c <= kjs_pcre_utf8_table1[i]) break;
+ for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
+ if (c <= jsc_pcre_utf8_table1[i]) break;
length += i;
lastitemlength += i;
}
if (c <= -ESC_REF) {
int refnum = -c - ESC_REF;
cd.backrefMap |= (refnum < 32) ? (1 << refnum) : 1;
- if (refnum > cd.top_backref)
- cd.top_backref = refnum;
+ if (refnum > cd.topBackref)
+ cd.topBackref = refnum;
length += 2; /* For single back reference */
if (safelyCheckNextChar(ptr, patternEnd, '{') && isCountedRepeat(ptr + 2, patternEnd)) {
ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
if (c > 127) {
int i;
- for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
- if (c <= kjs_pcre_utf8_table1[i])
+ for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
+ if (c <= jsc_pcre_utf8_table1[i])
break;
length += i;
lastitemlength += i;
Arguments:
pattern the regular expression
options various option bits
- errorcodeptr pointer to error code variable (pcre_compile2() only)
+ errorCodePtr pointer to error code variable (pcre_compile2() only)
can be NULL if you don't want a code value
- errorptr pointer to pointer to error text
+ errorPtr pointer to pointer to error text
erroroffset ptr offset in pattern where error was detected
tables pointer to character tables or NULL
Returns: pointer to compiled data block, or NULL on error,
- with errorptr and erroroffset set
+ with errorPtr and erroroffset set
*/
-static inline JSRegExp* returnError(ErrorCode errorcode, const char** errorptr)
+static inline JSRegExp* returnError(ErrorCode errorcode, const char** errorPtr)
{
- *errorptr = errorText(errorcode);
+ *errorPtr = errorText(errorcode);
return 0;
}
JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
JSRegExpIgnoreCaseOption ignoreCase, JSRegExpMultilineOption multiline,
- unsigned* numSubpatterns, const char** errorptr)
+ unsigned* numSubpatterns, const char** errorPtr)
{
- /* We can't pass back an error message if errorptr is NULL; I guess the best we
+ /* We can't pass back an error message if errorPtr is NULL; I guess the best we
can do is just return NULL, but we can set a code value if there is a code pointer. */
- if (!errorptr)
+ if (!errorPtr)
return 0;
- *errorptr = NULL;
+ *errorPtr = NULL;
CompileData cd;
/* Call it again to compute the length. */
int length = calculateCompiledPatternLength(pattern, patternLength, ignoreCase, cd, errorcode);
if (errorcode)
- return returnError(errorcode, errorptr);
+ return returnError(errorcode, errorPtr);
if (length > MAX_PATTERN_SIZE)
- return returnError(ERR16, errorptr);
+ return returnError(ERR16, errorPtr);
size_t size = length + sizeof(JSRegExp);
+#if REGEXP_HISTOGRAM
+ size_t stringOffset = (size + sizeof(UChar) - 1) / sizeof(UChar) * sizeof(UChar);
+ size = stringOffset + patternLength * sizeof(UChar);
+#endif
JSRegExp* re = reinterpret_cast<JSRegExp*>(new char[size]);
if (!re)
- return returnError(ERR13, errorptr);
+ return returnError(ERR13, errorPtr);
re->options = (ignoreCase ? IgnoreCaseOption : 0) | (multiline ? MatchAcrossMultipleLinesOption : 0);
const UChar* ptr = (const UChar*)pattern;
const UChar* patternEnd = pattern + patternLength;
- unsigned char* code = (unsigned char*)codeStart;
- int firstbyte, reqbyte;
+ unsigned char* code = const_cast<unsigned char*>(codeStart);
+ int firstByte, reqByte;
int bracketCount = 0;
if (!cd.needOuterBracket)
- compileBranch(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, &firstbyte, &reqbyte, cd);
+ compileBranch(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, &firstByte, &reqByte, cd);
else {
*code = OP_BRA;
- compileBracket(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, 0, &firstbyte, &reqbyte, cd);
+ compileBracket(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, 0, &firstByte, &reqByte, cd);
}
- re->top_bracket = bracketCount;
- re->top_backref = cd.top_backref;
+ re->topBracket = bracketCount;
+ re->topBackref = cd.topBackref;
/* If not reached end of pattern on success, there's an excess bracket. */
/* Give an error if there's back reference to a non-existent capturing
subpattern. */
- if (re->top_backref > re->top_bracket)
+ if (re->topBackref > re->topBracket)
errorcode = ERR15;
/* Failed to compile, or error while post-processing */
if (errorcode != ERR0) {
delete [] reinterpret_cast<char*>(re);
- return returnError(errorcode, errorptr);
+ return returnError(errorcode, errorPtr);
}
/* If the anchored option was not passed, set the flag if we can determine that
if (cd.needOuterBracket ? bracketIsAnchored(codeStart) : branchIsAnchored(codeStart))
re->options |= IsAnchoredOption;
else {
- if (firstbyte < 0) {
- firstbyte = (cd.needOuterBracket
+ if (firstByte < 0) {
+ firstByte = (cd.needOuterBracket
? bracketFindFirstAssertedCharacter(codeStart, false)
: branchFindFirstAssertedCharacter(codeStart, false))
| ((re->options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0);
}
- if (firstbyte >= 0) {
- int ch = firstbyte & 255;
+ if (firstByte >= 0) {
+ int ch = firstByte & 255;
if (ch < 127) {
- re->first_byte = ((firstbyte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? ch : firstbyte;
+ re->firstByte = ((firstByte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? ch : firstByte;
re->options |= UseFirstByteOptimizationOption;
}
} else {
variable length item in the regex. Remove the caseless flag for non-caseable
bytes. */
- if (reqbyte >= 0 && (!(re->options & IsAnchoredOption) || (reqbyte & REQ_VARY))) {
- int ch = reqbyte & 255;
+ if (reqByte >= 0 && (!(re->options & IsAnchoredOption) || (reqByte & REQ_VARY))) {
+ int ch = reqByte & 255;
if (ch < 127) {
- re->req_byte = ((reqbyte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? (reqbyte & ~REQ_IGNORE_CASE) : reqbyte;
+ re->reqByte = ((reqByte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? (reqByte & ~REQ_IGNORE_CASE) : reqByte;
re->options |= UseRequiredByteOptimizationOption;
}
}
+#if REGEXP_HISTOGRAM
+ re->stringOffset = stringOffset;
+ re->stringLength = patternLength;
+ memcpy(reinterpret_cast<char*>(re) + stringOffset, pattern, patternLength * 2);
+#endif
+
if (numSubpatterns)
- *numSubpatterns = re->top_bracket;
+ *numSubpatterns = re->topBracket;
return re;
}
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-----------------------------------------------------------------------------
the JavaScript specification. There are also some supporting functions. */
#include "config.h"
-
#include "pcre_internal.h"
+#include <limits.h>
#include <wtf/ASCIICType.h>
#include <wtf/Vector.h>
-#include <limits.h>
+#if REGEXP_HISTOGRAM
+#include <parser/DateMath.h>
+#include <runtime/UString.h>
+#endif
using namespace WTF;
typedef void* ReturnLocation;
#endif
+#if !REGEXP_HISTOGRAM
+
+class HistogramTimeLogger {
+public:
+ HistogramTimeLogger(const JSRegExp*) { }
+};
+
+#else
+
+using namespace JSC;
+
+class Histogram {
+public:
+ ~Histogram();
+ void add(const JSRegExp*, double);
+
+private:
+ typedef HashMap<RefPtr<UString::Rep>, double> Map;
+ Map times;
+};
+
+class HistogramTimeLogger {
+public:
+ HistogramTimeLogger(const JSRegExp*);
+ ~HistogramTimeLogger();
+
+private:
+ const JSRegExp* m_re;
+ double m_startTime;
+};
+
+#endif
+
/* Structure for building a chain of data for holding the values of
the subject pointer at the start of each bracket, used to detect when
an empty string has been matched by a bracket to break infinite loops. */
};
/* The maximum remaining length of subject we are prepared to search for a
-req_byte match. */
+reqByte match. */
#define REQ_BYTE_MAX 1000
if (md.ignoreCase) {
while (length-- > 0) {
UChar c = *p++;
- int othercase = kjs_pcre_ucp_othercase(c);
+ int othercase = jsc_pcre_ucp_othercase(c);
UChar d = *subjectPtr++;
if (c != d && othercase != d)
return false;
RECURSIVE_MATCH_COMMON(num) \
} while (0)
-#define RECURSIVE_MATCH_STARTNG_NEW_GROUP(num, ra, rb) \
+#define RECURSIVE_MATCH_NEW_GROUP(num, ra, rb) \
do { \
stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
startNewGroup(stack.currentFrame); \
(e.g. stopped by repeated call or recursion limit)
*/
-static const unsigned FRAMES_ON_STACK = 16;
+static const unsigned numFramesOnStack = 16;
struct MatchStack {
MatchStack()
- : framesEnd(frames + FRAMES_ON_STACK)
+ : framesEnd(frames + numFramesOnStack)
, currentFrame(frames)
, size(1) // match() creates accesses the first frame w/o calling pushNewFrame
{
- ASSERT((sizeof(frames) / sizeof(frames[0])) == FRAMES_ON_STACK);
+ ASSERT((sizeof(frames) / sizeof(frames[0])) == numFramesOnStack);
}
- MatchFrame frames[FRAMES_ON_STACK];
+ MatchFrame frames[numFramesOnStack];
MatchFrame* framesEnd;
MatchFrame* currentFrame;
unsigned size;
inline bool canUseStackBufferForNextFrame()
{
- return size < FRAMES_ON_STACK;
+ return size < numFramesOnStack;
}
inline MatchFrame* allocateNextFrame()
{
MatchFrame* oldFrame = currentFrame;
currentFrame = currentFrame->previousFrame;
- if (size > FRAMES_ON_STACK)
+ if (size > numFramesOnStack)
delete oldFrame;
size--;
}
{
c = *subjectPtr;
if ((c & 0xc0) == 0xc0) {
- int gcaa = kjs_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
+ int gcaa = jsc_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
int gcss = 6 * gcaa;
- c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss;
+ c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss;
for (int gcii = 1; gcii <= gcaa; gcii++) {
gcss -= 6;
c |= (subjectPtr[gcii] & 0x3f) << gcss;
bool isMatch = false;
int min;
bool minimize = false; /* Initialization not really needed, but some compilers think so. */
- unsigned matchCount = 0;
+ unsigned remainingMatchCount = matchLimit;
MatchStack stack;
/* This is where control jumps back to to effect "recursion" */
RECURSE:
- if (++matchCount > matchLimit)
+ if (!--remainingMatchCount)
return matchError(JSRegExpErrorHitLimit, stack);
/* Now start processing the operations. */
NON_CAPTURING_BRACKET:
DPRINTF(("start bracket 0\n"));
do {
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(2, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(2, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
BEGIN_OPCODE(ASSERT):
do {
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(6, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
+ RECURSIVE_MATCH_NEW_GROUP(6, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
if (isMatch)
break;
stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
BEGIN_OPCODE(ASSERT_NOT):
do {
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(7, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
+ RECURSIVE_MATCH_NEW_GROUP(7, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
if (isMatch)
RRETURN_NO_MATCH;
stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
BEGIN_OPCODE(BRAZERO): {
stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(14, stack.currentFrame->locals.startOfRepeatingBracket, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(14, stack.currentFrame->locals.startOfRepeatingBracket, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
BEGIN_OPCODE(BRAMINZERO): {
stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(15, stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(15, stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
stack.currentFrame->args.instructionPtr++;
RECURSIVE_MATCH(16, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(17, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(17, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
} else { /* OP_KETRMAX */
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(18, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(18, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
RECURSIVE_MATCH(19, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
}
RRETURN;
- /* Start of subject, or after internal newline if multiline. */
-
+ /* Start of subject. */
+
BEGIN_OPCODE(CIRC):
- if (stack.currentFrame->args.subjectPtr != md.startSubject && (!md.multiline || !isNewline(stack.currentFrame->args.subjectPtr[-1])))
+ if (stack.currentFrame->args.subjectPtr != md.startSubject)
RRETURN_NO_MATCH;
stack.currentFrame->args.instructionPtr++;
NEXT_OPCODE;
-
- /* End of subject, or before internal newline if multiline. */
-
+
+ /* After internal newline if multiline. */
+
+ BEGIN_OPCODE(BOL):
+ if (stack.currentFrame->args.subjectPtr != md.startSubject && !isNewline(stack.currentFrame->args.subjectPtr[-1]))
+ RRETURN_NO_MATCH;
+ stack.currentFrame->args.instructionPtr++;
+ NEXT_OPCODE;
+
+ /* End of subject. */
+
BEGIN_OPCODE(DOLL):
- if (stack.currentFrame->args.subjectPtr < md.endSubject && (!md.multiline || !isNewline(*stack.currentFrame->args.subjectPtr)))
+ if (stack.currentFrame->args.subjectPtr < md.endSubject)
+ RRETURN_NO_MATCH;
+ stack.currentFrame->args.instructionPtr++;
+ NEXT_OPCODE;
+
+ /* Before internal newline if multiline. */
+
+ BEGIN_OPCODE(EOL):
+ if (stack.currentFrame->args.subjectPtr < md.endSubject && !isNewline(*stack.currentFrame->args.subjectPtr))
RRETURN_NO_MATCH;
stack.currentFrame->args.instructionPtr++;
NEXT_OPCODE;
if (stack.currentFrame->args.subjectPtr >= md.endSubject)
RRETURN_NO_MATCH;
int c = *stack.currentFrame->args.subjectPtr++;
- if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
+ if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
RRETURN_NO_MATCH;
}
if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
RRETURN;
int c = *stack.currentFrame->args.subjectPtr++;
- if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
+ if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
RRETURN;
}
/* Control never reaches here */
if (stack.currentFrame->args.subjectPtr >= md.endSubject)
break;
int c = *stack.currentFrame->args.subjectPtr;
- if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
+ if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
break;
++stack.currentFrame->args.subjectPtr;
}
if (stack.currentFrame->args.subjectPtr >= md.endSubject)
RRETURN_NO_MATCH;
int dc = *stack.currentFrame->args.subjectPtr++;
- if (stack.currentFrame->locals.fc != dc && kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc)
+ if (stack.currentFrame->locals.fc != dc && jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc)
RRETURN_NO_MATCH;
NEXT_OPCODE;
}
stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
if (stack.currentFrame->locals.fc <= 0xFFFF) {
- int othercase = md.ignoreCase ? kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
+ int othercase = md.ignoreCase ? jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
for (int i = 1; i <= min; i++) {
if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
BEGIN_OPCODE(NOT): {
if (stack.currentFrame->args.subjectPtr >= md.endSubject)
RRETURN_NO_MATCH;
- stack.currentFrame->args.instructionPtr++;
+ int b = stack.currentFrame->args.instructionPtr[1];
int c = *stack.currentFrame->args.subjectPtr++;
+ stack.currentFrame->args.instructionPtr += 2;
if (md.ignoreCase) {
if (c < 128)
c = toLowerCase(c);
- if (toLowerCase(*stack.currentFrame->args.instructionPtr++) == c)
+ if (toLowerCase(b) == c)
RRETURN_NO_MATCH;
} else {
- if (*stack.currentFrame->args.instructionPtr++ == c)
+ if (b == c)
RRETURN_NO_MATCH;
}
NEXT_OPCODE;
md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->args.subjectPtr - md.startSubject;
do {
- RECURSIVE_MATCH_STARTNG_NEW_GROUP(1, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
+ RECURSIVE_MATCH_NEW_GROUP(1, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
if (isMatch)
RRETURN;
stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
start_offset where to start in the subject string
options option bits
offsets points to a vector of ints to be filled in with offsets
- offsetcount the number of elements in the vector
+ offsetCount the number of elements in the vector
Returns: > 0 => success; value is the number of elements filled in
= 0 => success, but offsets is not big enough
< -1 => some kind of unexpected problem
*/
-static void tryFirstByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int first_byte, bool first_byte_caseless, bool useMultiLineFirstCharOptimization, const UChar* originalSubjectStart)
+static void tryFirstByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int firstByte, bool firstByteIsCaseless, bool useMultiLineFirstCharOptimization, const UChar* originalSubjectStart)
{
- // If first_byte is set, try scanning to the first instance of that byte
+ // If firstByte is set, try scanning to the first instance of that byte
// no need to try and match against any earlier part of the subject string.
- if (first_byte >= 0) {
- UChar first_char = first_byte;
- if (first_byte_caseless)
+ if (firstByte >= 0) {
+ UChar firstChar = firstByte;
+ if (firstByteIsCaseless)
while (subjectPtr < endSubject) {
int c = *subjectPtr;
if (c > 127)
break;
- if (toLowerCase(c) == first_char)
+ if (toLowerCase(c) == firstChar)
break;
subjectPtr++;
}
else {
- while (subjectPtr < endSubject && *subjectPtr != first_char)
+ while (subjectPtr < endSubject && *subjectPtr != firstChar)
subjectPtr++;
}
} else if (useMultiLineFirstCharOptimization) {
}
}
-static bool tryRequiredByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int req_byte, int req_byte2, bool req_byte_caseless, bool hasFirstByte, const UChar*& reqBytePtr)
+static bool tryRequiredByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int reqByte, int reqByte2, bool reqByteIsCaseless, bool hasFirstByte, const UChar*& reqBytePtr)
{
- /* If req_byte is set, we know that that character must appear in the subject
- for the match to succeed. If the first character is set, req_byte must be
+ /* If reqByte is set, we know that that character must appear in the subject
+ for the match to succeed. If the first character is set, reqByte must be
later in the subject; otherwise the test starts at the match point. This
optimization can save a huge amount of backtracking in patterns with nested
unlimited repeats that aren't going to match. Writing separate code for
don't do this when the string is sufficiently long.
*/
- if (req_byte >= 0 && endSubject - subjectPtr < REQ_BYTE_MAX) {
+ if (reqByte >= 0 && endSubject - subjectPtr < REQ_BYTE_MAX) {
const UChar* p = subjectPtr + (hasFirstByte ? 1 : 0);
/* We don't need to repeat the search if we haven't yet reached the
place we found it at last time. */
if (p > reqBytePtr) {
- if (req_byte_caseless) {
+ if (reqByteIsCaseless) {
while (p < endSubject) {
int pp = *p++;
- if (pp == req_byte || pp == req_byte2) {
+ if (pp == reqByte || pp == reqByte2) {
p--;
break;
}
}
} else {
while (p < endSubject) {
- if (*p++ == req_byte) {
+ if (*p++ == reqByte) {
p--;
break;
}
int jsRegExpExecute(const JSRegExp* re,
const UChar* subject, int length, int start_offset, int* offsets,
- int offsetcount)
+ int offsetCount)
{
ASSERT(re);
- ASSERT(subject);
- ASSERT(offsetcount >= 0);
- ASSERT(offsets || offsetcount == 0);
-
+ ASSERT(subject || !length);
+ ASSERT(offsetCount >= 0);
+ ASSERT(offsets || offsetCount == 0);
+
+ HistogramTimeLogger logger(re);
+
MatchData matchBlock;
matchBlock.startSubject = subject;
matchBlock.endSubject = matchBlock.startSubject + length;
Otherwise, we can use the vector supplied, rounding down its size to a multiple
of 3. */
- int ocount = offsetcount - (offsetcount % 3);
+ int ocount = offsetCount - (offsetCount % 3);
// FIXME: This is lame that we have to second-guess our caller here.
// The API should change to either fail-hard when we don't have enough offset space
// or that we shouldn't ask our callers to pre-allocate in the first place.
- bool using_temporary_offsets = false;
- if (re->top_backref > 0 && re->top_backref >= ocount/3) {
- ocount = re->top_backref * 3 + 3;
+ bool usingTemporaryOffsets = false;
+ if (re->topBackref > 0 && re->topBackref >= ocount/3) {
+ ocount = re->topBackref * 3 + 3;
matchBlock.offsetVector = new int[ocount];
if (!matchBlock.offsetVector)
return JSRegExpErrorNoMemory;
- using_temporary_offsets = true;
+ usingTemporaryOffsets = true;
} else
matchBlock.offsetVector = offsets;
this makes a huge difference to execution time when there aren't many brackets
in the pattern. */
- int resetcount = 2 + re->top_bracket * 2;
- if (resetcount > offsetcount)
- resetcount = ocount;
+ int resetCount = 2 + re->topBracket * 2;
+ if (resetCount > offsetCount)
+ resetCount = ocount;
/* Reset the working variable associated with each extraction. These should
never be used unless previously set, but they get saved and restored, and so we
if (matchBlock.offsetVector) {
int* iptr = matchBlock.offsetVector + ocount;
- int* iend = iptr - resetcount/2 + 1;
+ int* iend = iptr - resetCount/2 + 1;
while (--iptr >= iend)
*iptr = -1;
}
- /* Set up the first character to match, if available. The first_byte value is
+ /* Set up the first character to match, if available. The firstByte value is
never set for an anchored regular expression, but the anchoring may be forced
at run time, so we have to test for anchoring. The first char may be unset for
an unanchored pattern, of course. If there's no first char and the pattern was
studied, there may be a bitmap of possible first characters. */
- bool first_byte_caseless = false;
- int first_byte = -1;
+ bool firstByteIsCaseless = false;
+ int firstByte = -1;
if (re->options & UseFirstByteOptimizationOption) {
- first_byte = re->first_byte & 255;
- if ((first_byte_caseless = (re->first_byte & REQ_IGNORE_CASE)))
- first_byte = toLowerCase(first_byte);
+ firstByte = re->firstByte & 255;
+ if ((firstByteIsCaseless = (re->firstByte & REQ_IGNORE_CASE)))
+ firstByte = toLowerCase(firstByte);
}
/* For anchored or unanchored matches, there may be a "last known required
character" set. */
- bool req_byte_caseless = false;
- int req_byte = -1;
- int req_byte2 = -1;
+ bool reqByteIsCaseless = false;
+ int reqByte = -1;
+ int reqByte2 = -1;
if (re->options & UseRequiredByteOptimizationOption) {
- req_byte = re->req_byte & 255; // FIXME: This optimization could be made to work for UTF16 chars as well...
- req_byte_caseless = (re->req_byte & REQ_IGNORE_CASE);
- req_byte2 = flipCase(req_byte);
+ reqByte = re->reqByte & 255; // FIXME: This optimization could be made to work for UTF16 chars as well...
+ reqByteIsCaseless = (re->reqByte & REQ_IGNORE_CASE);
+ reqByte2 = flipCase(reqByte);
}
/* Loop for handling unanchored repeated matching attempts; for anchored regexs
/* Reset the maximum number of extractions we might see. */
if (matchBlock.offsetVector) {
int* iptr = matchBlock.offsetVector;
- int* iend = iptr + resetcount;
+ int* iend = iptr + resetCount;
while (iptr < iend)
*iptr++ = -1;
}
- tryFirstByteOptimization(startMatch, endSubject, first_byte, first_byte_caseless, useMultiLineFirstCharOptimization, matchBlock.startSubject + start_offset);
- if (tryRequiredByteOptimization(startMatch, endSubject, req_byte, req_byte2, req_byte_caseless, first_byte >= 0, reqBytePtr))
+ tryFirstByteOptimization(startMatch, endSubject, firstByte, firstByteIsCaseless, useMultiLineFirstCharOptimization, matchBlock.startSubject + start_offset);
+ if (tryRequiredByteOptimization(startMatch, endSubject, reqByte, reqByte2, reqByteIsCaseless, firstByte >= 0, reqBytePtr))
break;
/* When a match occurs, substrings will be set for all internal extractions;
if (returnCode != 1) {
ASSERT(returnCode == JSRegExpErrorHitLimit || returnCode == JSRegExpErrorNoMemory);
- DPRINTF((">>>> error: returning %d\n", rc));
+ DPRINTF((">>>> error: returning %d\n", returnCode));
return returnCode;
}
/* We have a match! Copy the offset information from temporary store if
necessary */
- if (using_temporary_offsets) {
- if (offsetcount >= 4) {
- memcpy(offsets + 2, matchBlock.offsetVector + 2, (offsetcount - 2) * sizeof(int));
+ if (usingTemporaryOffsets) {
+ if (offsetCount >= 4) {
+ memcpy(offsets + 2, matchBlock.offsetVector + 2, (offsetCount - 2) * sizeof(int));
DPRINTF(("Copied offsets from temporary memory\n"));
}
- if (matchBlock.endOffsetTop > offsetcount)
+ if (matchBlock.endOffsetTop > offsetCount)
matchBlock.offsetOverflow = true;
DPRINTF(("Freeing temporary memory\n"));
returnCode = matchBlock.offsetOverflow ? 0 : matchBlock.endOffsetTop / 2;
- if (offsetcount < 2)
+ if (offsetCount < 2)
returnCode = 0;
else {
offsets[0] = startMatch - matchBlock.startSubject;
offsets[1] = matchBlock.endMatchPtr - matchBlock.startSubject;
}
- DPRINTF((">>>> returning %d\n", rc));
+ DPRINTF((">>>> returning %d\n", returnCode));
return returnCode;
- } while (startMatch <= endSubject);
+ } while (!(re->options & IsAnchoredOption) && startMatch <= endSubject);
- if (using_temporary_offsets) {
+ if (usingTemporaryOffsets) {
DPRINTF(("Freeing temporary memory\n"));
delete [] matchBlock.offsetVector;
}
DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
return JSRegExpErrorNoMatch;
}
+
+#if REGEXP_HISTOGRAM
+
+class CompareHistogramEntries {
+public:
+ bool operator()(const pair<UString, double>& a, const pair<UString, double>& b)
+ {
+ if (a.second == b.second)
+ return a.first < b.first;
+ return a.second < b.second;
+ }
+};
+
+Histogram::~Histogram()
+{
+ Vector<pair<UString, double> > values;
+ Map::iterator end = times.end();
+ for (Map::iterator it = times.begin(); it != end; ++it)
+ values.append(*it);
+ sort(values.begin(), values.end(), CompareHistogramEntries());
+ size_t size = values.size();
+ printf("Regular Expressions, sorted by time spent evaluating them:\n");
+ for (size_t i = 0; i < size; ++i)
+ printf(" %f - %s\n", values[size - i - 1].second, values[size - i - 1].first.UTF8String().c_str());
+}
+
+void Histogram::add(const JSRegExp* re, double elapsedTime)
+{
+ UString string(reinterpret_cast<const UChar*>(reinterpret_cast<const char*>(re) + re->stringOffset), re->stringLength);
+ if (re->options & IgnoreCaseOption && re->options & MatchAcrossMultipleLinesOption)
+ string += " (multi-line, ignore case)";
+ else {
+ if (re->options & IgnoreCaseOption)
+ string += " (ignore case)";
+ if (re->options & MatchAcrossMultipleLinesOption)
+ string += " (multi-line)";
+ }
+ pair<Map::iterator, bool> result = times.add(string.rep(), elapsedTime);
+ if (!result.second)
+ result.first->second += elapsedTime;
+}
+
+HistogramTimeLogger::HistogramTimeLogger(const JSRegExp* re)
+ : m_re(re)
+ , m_startTime(getCurrentUTCTimeWithMicroseconds())
+{
+}
+
+HistogramTimeLogger::~HistogramTimeLogger()
+{
+ static Histogram histogram;
+ histogram.add(m_re, getCurrentUTCTimeWithMicroseconds() - m_startTime);
+}
+
+#endif
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
#ifndef DFTABLES
+// Change the following to 1 to dump used regular expressions at process exit time.
+#define REGEXP_HISTOGRAM 0
+
#include "Assertions.h"
#if COMPILER(MSVC)
offsets within the compiled regex. The default is 2, which allows for compiled
patterns up to 64K long. */
-#define LINK_SIZE 2
+#define LINK_SIZE 3
/* Define DEBUG to get debugging output on stdout. */
opcodePtr[1] = value;
}
+static inline void put3ByteValue(unsigned char* opcodePtr, int value)
+{
+ ASSERT(value >= 0 && value <= 0xFFFFFF);
+ opcodePtr[0] = value >> 16;
+ opcodePtr[1] = value >> 8;
+ opcodePtr[2] = value;
+}
+
static inline int get2ByteValue(const unsigned char* opcodePtr)
{
return (opcodePtr[0] << 8) | opcodePtr[1];
}
+static inline int get3ByteValue(const unsigned char* opcodePtr)
+{
+ return (opcodePtr[0] << 16) | (opcodePtr[1] << 8) | opcodePtr[2];
+}
+
static inline void put2ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
{
put2ByteValue(opcodePtr, value);
opcodePtr += 2;
}
+static inline void put3ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
+{
+ put3ByteValue(opcodePtr, value);
+ opcodePtr += 3;
+}
+
static inline void putLinkValueAllowZero(unsigned char* opcodePtr, int value)
{
+#if LINK_SIZE == 3
+ put3ByteValue(opcodePtr, value);
+#elif LINK_SIZE == 2
put2ByteValue(opcodePtr, value);
+#else
+# error LINK_SIZE not supported.
+#endif
}
static inline int getLinkValueAllowZero(const unsigned char* opcodePtr)
{
+#if LINK_SIZE == 3
+ return get3ByteValue(opcodePtr);
+#elif LINK_SIZE == 2
return get2ByteValue(opcodePtr);
+#else
+# error LINK_SIZE not supported.
+#endif
}
-#define MAX_PATTERN_SIZE (1 << 16)
+#define MAX_PATTERN_SIZE 1024 * 1024 // Derived by empirical testing of compile time in PCRE and WREC.
+COMPILE_ASSERT(MAX_PATTERN_SIZE < (1 << (8 * LINK_SIZE)), pcre_max_pattern_fits_in_bytecode);
static inline void putLinkValue(unsigned char* opcodePtr, int value)
{
// FIXME: These are really more of a "compiled regexp state" than "regexp options"
enum RegExpOptions {
- UseFirstByteOptimizationOption = 0x40000000, /* first_byte is set */
- UseRequiredByteOptimizationOption = 0x20000000, /* req_byte is set */
+ UseFirstByteOptimizationOption = 0x40000000, /* firstByte is set */
+ UseRequiredByteOptimizationOption = 0x20000000, /* reqByte is set */
UseMultiLineFirstByteOptimizationOption = 0x10000000, /* start after \n for multiline */
IsAnchoredOption = 0x02000000, /* can't use partial with this regex */
IgnoreCaseOption = 0x00000001,
MatchAcrossMultipleLinesOption = 0x00000002
};
-/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a
+/* Flags added to firstByte or reqByte; a "non-literal" item is either a
variable-length repeat, or a anything other than literal characters. */
#define REQ_IGNORE_CASE 0x0100 /* indicates should ignore case */
-#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */
+#define REQ_VARY 0x0200 /* reqByte followed non-literal item */
/* Miscellaneous definitions */
\
macro(CIRC) \
macro(DOLL) \
+ macro(BOL) \
+ macro(EOL) \
macro(CHAR) \
macro(CHAR_IGNORING_CASE) \
macro(ASCII_CHAR) \
#define EXTRACT_BASIC_MAX 100
-/* The index of names and the
-code vector run on as long as necessary after the end. We store an explicit
-offset to the name table so that if a regex is compiled on one host, saved, and
-then run on another where the size of pointers is different, all might still
-be well. For the case of compiled-on-4 and run-on-8, we include an extra
-pointer that is always NULL.
-*/
+/* The code vector runs on as long as necessary after the end. */
struct JSRegExp {
unsigned options;
- unsigned short top_bracket;
- unsigned short top_backref;
+ unsigned short topBracket;
+ unsigned short topBackref;
- unsigned short first_byte;
- unsigned short req_byte;
+ unsigned short firstByte;
+ unsigned short reqByte;
+
+#if REGEXP_HISTOGRAM
+ size_t stringOffset;
+ size_t stringLength;
+#endif
};
/* Internal shared data tables. These are tables that are used by more than one
but are not part of the PCRE public API. The data for these tables is in the
pcre_tables.c module. */
-#define kjs_pcre_utf8_table1_size 6
+#define jsc_pcre_utf8_table1_size 6
-extern const int kjs_pcre_utf8_table1[6];
-extern const int kjs_pcre_utf8_table2[6];
-extern const int kjs_pcre_utf8_table3[6];
-extern const unsigned char kjs_pcre_utf8_table4[0x40];
+extern const int jsc_pcre_utf8_table1[6];
+extern const int jsc_pcre_utf8_table2[6];
+extern const int jsc_pcre_utf8_table3[6];
+extern const unsigned char jsc_pcre_utf8_table4[0x40];
-extern const unsigned char kjs_pcre_default_tables[tables_length];
+extern const unsigned char jsc_pcre_default_tables[tables_length];
static inline unsigned char toLowerCase(unsigned char c)
{
- static const unsigned char* lowerCaseChars = kjs_pcre_default_tables + lcc_offset;
+ static const unsigned char* lowerCaseChars = jsc_pcre_default_tables + lcc_offset;
return lowerCaseChars[c];
}
static inline unsigned char flipCase(unsigned char c)
{
- static const unsigned char* flippedCaseChars = kjs_pcre_default_tables + fcc_offset;
+ static const unsigned char* flippedCaseChars = jsc_pcre_default_tables + fcc_offset;
return flippedCaseChars[c];
}
static inline unsigned char classBitmapForChar(unsigned char c)
{
- static const unsigned char* charClassBitmaps = kjs_pcre_default_tables + cbits_offset;
+ static const unsigned char* charClassBitmaps = jsc_pcre_default_tables + cbits_offset;
return charClassBitmaps[c];
}
static inline unsigned char charTypeForChar(unsigned char c)
{
- const unsigned char* charTypeMap = kjs_pcre_default_tables + ctypes_offset;
+ const unsigned char* charTypeMap = jsc_pcre_default_tables + ctypes_offset;
return charTypeMap[c];
}
static inline bool isSpaceChar(UChar c)
{
- return c < 128 && (charTypeForChar(c) & ctype_space);
+ return (c < 128 && (charTypeForChar(c) & ctype_space)) || c == 0x00A0;
}
static inline bool isNewline(UChar nl)
that one of the source files. They have to have external linkage, but
but are not part of the public API and so not exported from the library. */
-extern int kjs_pcre_ucp_othercase(unsigned);
-extern bool kjs_pcre_xclass(int, const unsigned char*);
+extern int jsc_pcre_ucp_othercase(unsigned);
+extern bool jsc_pcre_xclass(int, const unsigned char*);
#endif
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
/* This module contains some fixed tables that are used by more than one of the
PCRE code modules. */
+#include "config.h"
#include "pcre_internal.h"
/*************************************************
/* These are the breakpoints for different numbers of bytes in a UTF-8
character. */
-const int kjs_pcre_utf8_table1[6] =
+const int jsc_pcre_utf8_table1[6] =
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
/* These are the indicator bits and the mask for the data bits to set in the
first byte of a character, indexed by the number of additional bytes. */
-const int kjs_pcre_utf8_table2[6] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-const int kjs_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+const int jsc_pcre_utf8_table2[6] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
+const int jsc_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
/* Table of the number of extra characters, indexed by the first character
masked with 0x3f. The highest number for a valid UTF-8 character is in fact
0x3d. */
-const unsigned char kjs_pcre_utf8_table4[0x40] = {
+const unsigned char jsc_pcre_utf8_table4[0x40] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
/* This module contains code for searching the table of Unicode character
properties. */
+#include "config.h"
#include "pcre_internal.h"
#include "ucpinternal.h" /* Internal table details */
Returns: the other case or -1 if none
*/
-int kjs_pcre_ucp_othercase(unsigned c)
+int jsc_pcre_ucp_othercase(unsigned c)
{
int bot = 0;
int top = sizeof(ucp_table) / sizeof(cnode);
Originally written by Philip Hazel
Copyright (c) 1997-2006 University of Cambridge
- Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
+ Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
/* This module contains an internal function that is used to match an extended
class (one that contains characters whose values are > 255). */
+#include "config.h"
#include "pcre_internal.h"
/*************************************************
{
c = *subjectPtr++;
if ((c & 0xc0) == 0xc0) {
- int gcaa = kjs_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
+ int gcaa = jsc_pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */
int gcss = 6 * gcaa;
- c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss;
+ c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss;
while (gcaa-- > 0) {
gcss -= 6;
c |= (*subjectPtr++ & 0x3f) << gcss;
}
}
-bool kjs_pcre_xclass(int c, const unsigned char* data)
+bool jsc_pcre_xclass(int c, const unsigned char* data)
{
bool negated = (*data & XCL_NOT);
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef CallIdentifier_h
+#define CallIdentifier_h
+
+#include <runtime/UString.h>
+
+namespace JSC {
+
+ struct CallIdentifier {
+ UString m_name;
+ UString m_url;
+ unsigned m_lineNumber;
+
+ CallIdentifier()
+ : m_lineNumber(0)
+ {
+ }
+
+ CallIdentifier(const UString& name, const UString& url, int lineNumber)
+ : m_name(name)
+ , m_url(url)
+ , m_lineNumber(lineNumber)
+ {
+ }
+
+ inline bool operator==(const CallIdentifier& ci) const { return ci.m_lineNumber == m_lineNumber && ci.m_name == m_name && ci.m_url == m_url; }
+ inline bool operator!=(const CallIdentifier& ci) const { return !(*this == ci); }
+
+#ifndef NDEBUG
+ operator const char*() const { return c_str(); }
+ const char* c_str() const { return m_name.UTF8String().c_str(); }
+#endif
+ };
+
+ struct CallIdentifierHash {
+ static unsigned hash(const CallIdentifier& key)
+ {
+ unsigned hashCodes[3] = {
+ key.m_name.rep()->hash(),
+ key.m_url.rep()->hash(),
+ key.m_lineNumber
+ };
+ return UString::Rep::computeHash(reinterpret_cast<char*>(hashCodes), sizeof(hashCodes));
+ }
+
+ static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+
+} // namespace JSC
+
+namespace WTF {
+
+ template<> struct DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifierHash Hash; };
+
+ template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
+ static void constructDeletedValue(JSC::CallIdentifier& slot)
+ {
+ new (&slot) JSC::CallIdentifier(JSC::UString(), JSC::UString(), std::numeric_limits<unsigned>::max());
+ }
+ static bool isDeletedValue(const JSC::CallIdentifier& value)
+ {
+ return value.m_name.isNull() && value.m_url.isNull() && value.m_lineNumber == std::numeric_limits<unsigned>::max();
+ }
+ };
+
+} // namespace WTF
+
+#endif // CallIdentifier_h
+
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HeavyProfile.h"
+
+#include "TreeProfile.h"
+
+namespace JSC {
+
+HeavyProfile::HeavyProfile(TreeProfile* treeProfile)
+ : Profile(treeProfile->title(), treeProfile->uid())
+{
+ m_treeProfile = treeProfile;
+ head()->setTotalTime(m_treeProfile->head()->actualTotalTime());
+ head()->setSelfTime(m_treeProfile->head()->actualSelfTime());
+ generateHeavyStructure();
+}
+
+void HeavyProfile::generateHeavyStructure()
+{
+ ProfileNode* treeHead = m_treeProfile->head();
+ ProfileNode* currentNode = treeHead->firstChild();
+ for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
+ currentNode = nextNode;
+
+ // For each node
+ HashMap<CallIdentifier, ProfileNode*> foundChildren;
+ while (currentNode && currentNode != treeHead) {
+ ProfileNode* child = foundChildren.get(currentNode->callIdentifier());
+ if (child) // currentNode is in the set already
+ mergeProfiles(child, currentNode);
+ else { // currentNode is not in the set
+ child = addNode(currentNode);
+ foundChildren.set(currentNode->callIdentifier(), child);
+ }
+
+ currentNode = currentNode->traverseNextNodePostOrder();
+ }
+}
+
+ProfileNode* HeavyProfile::addNode(ProfileNode* currentNode)
+{
+ RefPtr<ProfileNode> node = ProfileNode::create(head(), currentNode);
+ head()->addChild(node);
+
+ addAncestorsAsChildren(currentNode->parent(), node.get());
+ return node.get();
+}
+
+void HeavyProfile::mergeProfiles(ProfileNode* heavyProfileHead, ProfileNode* treeProfileHead)
+{
+ ASSERT_ARG(heavyProfileHead, heavyProfileHead);
+ ASSERT_ARG(treeProfileHead, treeProfileHead);
+
+ ProfileNode* currentTreeNode = treeProfileHead;
+ ProfileNode* currentHeavyNode = heavyProfileHead;
+ ProfileNode* previousHeavyNode = 0;
+
+ while (currentHeavyNode) {
+ previousHeavyNode = currentHeavyNode;
+
+ currentHeavyNode->setTotalTime(currentHeavyNode->actualTotalTime() + currentTreeNode->actualTotalTime());
+ currentHeavyNode->setSelfTime(currentHeavyNode->actualSelfTime() + currentTreeNode->actualSelfTime());
+ currentHeavyNode->setNumberOfCalls(currentHeavyNode->numberOfCalls() + currentTreeNode->numberOfCalls());
+
+ currentTreeNode = currentTreeNode->parent();
+ currentHeavyNode = currentHeavyNode->findChild(currentTreeNode);
+ }
+
+ // If currentTreeNode is null then we already have the whole tree we wanted to copy.
+ // If not we need to copy the subset of the tree that remains different between the two.
+ if (currentTreeNode)
+ addAncestorsAsChildren(currentTreeNode, previousHeavyNode);
+}
+
+void HeavyProfile::addAncestorsAsChildren(ProfileNode* getFrom, ProfileNode* addTo)
+{
+ ASSERT_ARG(getFrom, getFrom);
+ ASSERT_ARG(addTo, addTo);
+
+ if (!getFrom->head())
+ return;
+
+ RefPtr<ProfileNode> currentNode = addTo;
+ for (ProfileNode* treeAncestor = getFrom; treeAncestor && treeAncestor != getFrom->head(); treeAncestor = treeAncestor->parent()) {
+ RefPtr<ProfileNode> newChild = ProfileNode::create(currentNode->head(), treeAncestor);
+ currentNode->addChild(newChild);
+ currentNode = newChild.release();
+ }
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HeavyProfile_h
+#define HeavyProfile_h
+
+#include "Profile.h"
+#include "ProfileNode.h"
+#include "TreeProfile.h"
+
+namespace JSC {
+
+ class UString;
+
+ class HeavyProfile : public Profile {
+ public:
+ static PassRefPtr<HeavyProfile> create(TreeProfile* treeProfile)
+ {
+ return adoptRef(new HeavyProfile(treeProfile));
+ }
+
+ virtual Profile* heavyProfile() { return this; }
+ virtual Profile* treeProfile()
+ {
+ return m_treeProfile;
+ }
+
+
+ private:
+ HeavyProfile(TreeProfile*);
+ void generateHeavyStructure();
+ ProfileNode* addNode(ProfileNode*);
+ void mergeProfiles(ProfileNode* heavyProfileHead, ProfileNode* treeProfileHead);
+ void addAncestorsAsChildren(ProfileNode* getFrom, ProfileNode* addTo);
+
+ TreeProfile* m_treeProfile;
+ };
+
+} // namespace JSC
+
+#endif // HeavyProfile_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Profile.h"
+
+#include "ProfileNode.h"
+#include "TreeProfile.h"
+#include <stdio.h>
+
+namespace JSC {
+
+PassRefPtr<Profile> Profile::create(const UString& title, unsigned uid)
+{
+ return TreeProfile::create(title, uid);
+}
+
+Profile::Profile(const UString& title, unsigned uid)
+ : m_title(title)
+ , m_uid(uid)
+{
+ // FIXME: When multi-threading is supported this will be a vector and calls
+ // into the profiler will need to know which thread it is executing on.
+ m_head = ProfileNode::create(CallIdentifier("Thread_1", 0, 0), 0, 0);
+}
+
+Profile::~Profile()
+{
+}
+
+void Profile::forEach(void (ProfileNode::*function)())
+{
+ ProfileNode* currentNode = m_head->firstChild();
+ for (ProfileNode* nextNode = currentNode; nextNode; nextNode = nextNode->firstChild())
+ currentNode = nextNode;
+
+ if (!currentNode)
+ currentNode = m_head.get();
+
+ ProfileNode* endNode = m_head->traverseNextNodePostOrder();
+ while (currentNode && currentNode != endNode) {
+ (currentNode->*function)();
+ currentNode = currentNode->traverseNextNodePostOrder();
+ }
+}
+
+void Profile::focus(const ProfileNode* profileNode)
+{
+ if (!profileNode || !m_head)
+ return;
+
+ bool processChildren;
+ const CallIdentifier& callIdentifier = profileNode->callIdentifier();
+ for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder(processChildren))
+ processChildren = currentNode->focus(callIdentifier);
+
+ // Set the visible time of all nodes so that the %s display correctly.
+ forEach(&ProfileNode::calculateVisibleTotalTime);
+}
+
+void Profile::exclude(const ProfileNode* profileNode)
+{
+ if (!profileNode || !m_head)
+ return;
+
+ const CallIdentifier& callIdentifier = profileNode->callIdentifier();
+
+ for (ProfileNode* currentNode = m_head.get(); currentNode; currentNode = currentNode->traverseNextNodePreOrder())
+ currentNode->exclude(callIdentifier);
+
+ // Set the visible time of the head so the %s display correctly.
+ m_head->setVisibleTotalTime(m_head->totalTime() - m_head->selfTime());
+ m_head->setVisibleSelfTime(0.0);
+}
+
+void Profile::restoreAll()
+{
+ forEach(&ProfileNode::restore);
+}
+
+#ifndef NDEBUG
+void Profile::debugPrintData() const
+{
+ printf("Call graph:\n");
+ m_head->debugPrintData(0);
+}
+
+typedef pair<UString::Rep*, unsigned> NameCountPair;
+
+static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b)
+{
+ return a.second > b.second;
+}
+
+void Profile::debugPrintDataSampleStyle() const
+{
+ typedef Vector<NameCountPair> NameCountPairVector;
+
+ FunctionCallHashCount countedFunctions;
+ printf("Call graph:\n");
+ m_head->debugPrintDataSampleStyle(0, countedFunctions);
+
+ printf("\nTotal number in stack:\n");
+ NameCountPairVector sortedFunctions(countedFunctions.size());
+ copyToVector(countedFunctions, sortedFunctions);
+
+ std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
+ for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
+ printf(" %-12d%s\n", (*it).second, UString((*it).first).UTF8String().c_str());
+
+ printf("\nSort by top of stack, same collapsed (when >= 5):\n");
+}
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Profile_h
+#define Profile_h
+
+#include "ProfileNode.h"
+#include <runtime/UString.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class Profile : public RefCounted<Profile> {
+ public:
+ static PassRefPtr<Profile> create(const UString& title, unsigned uid);
+ virtual ~Profile();
+
+ const UString& title() const { return m_title; }
+ ProfileNode* head() const { return m_head.get(); }
+ void setHead(PassRefPtr<ProfileNode> head) { m_head = head; }
+ double totalTime() const { return m_head->totalTime(); }
+ unsigned int uid() const { return m_uid; }
+
+ void forEach(void (ProfileNode::*)());
+ void sortTotalTimeDescending() { forEach(&ProfileNode::sortTotalTimeDescending); }
+ void sortTotalTimeAscending() { forEach(&ProfileNode::sortTotalTimeAscending); }
+ void sortSelfTimeDescending() { forEach(&ProfileNode::sortSelfTimeDescending); }
+ void sortSelfTimeAscending() { forEach(&ProfileNode::sortSelfTimeAscending); }
+ void sortCallsDescending() { forEach(&ProfileNode::sortCallsDescending); }
+ void sortCallsAscending() { forEach(&ProfileNode::sortCallsAscending); }
+ void sortFunctionNameDescending() { forEach(&ProfileNode::sortFunctionNameDescending); }
+ void sortFunctionNameAscending() { forEach(&ProfileNode::sortFunctionNameAscending); }
+
+ void focus(const ProfileNode*);
+ void exclude(const ProfileNode*);
+ void restoreAll();
+
+ virtual Profile* heavyProfile() = 0;
+ virtual Profile* treeProfile() = 0;
+
+#ifndef NDEBUG
+ void debugPrintData() const;
+ void debugPrintDataSampleStyle() const;
+#endif
+
+ protected:
+ Profile(const UString& title, unsigned uid);
+
+ private:
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ UString m_title;
+ RefPtr<ProfileNode> m_head;
+ unsigned int m_uid;
+ };
+
+} // namespace JSC
+
+#endif // Profile_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileGenerator.h"
+
+#include "CallFrame.h"
+#include "JSGlobalObject.h"
+#include "JSStringRef.h"
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "Profile.h"
+#include "Profiler.h"
+#include "Tracing.h"
+
+namespace JSC {
+
+static const char* NonJSExecution = "(idle)";
+
+PassRefPtr<ProfileGenerator> ProfileGenerator::create(const UString& title, ExecState* originatingExec, unsigned uid)
+{
+ return adoptRef(new ProfileGenerator(title, originatingExec, uid));
+}
+
+ProfileGenerator::ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid)
+ : m_originatingGlobalExec(originatingExec ? originatingExec->lexicalGlobalObject()->globalExec() : 0)
+ , m_profileGroup(originatingExec ? originatingExec->lexicalGlobalObject()->profileGroup() : 0)
+{
+ m_profile = Profile::create(title, uid);
+ m_currentNode = m_head = m_profile->head();
+ if (originatingExec)
+ addParentForConsoleStart(originatingExec);
+}
+
+void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
+{
+ int lineNumber;
+ intptr_t sourceID;
+ UString sourceURL;
+ JSValuePtr function;
+
+ exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
+ m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(&exec->globalData(), function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
+ m_head->insertNode(m_currentNode.get());
+}
+
+const UString& ProfileGenerator::title() const
+{
+ return m_profile->title();
+}
+
+void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier)
+{
+ if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
+ CString name = callIdentifier.m_name.UTF8String();
+ CString url = callIdentifier.m_url.UTF8String();
+ JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.c_str()), const_cast<char*>(url.c_str()), callIdentifier.m_lineNumber);
+ }
+
+ if (!m_originatingGlobalExec)
+ return;
+
+ ASSERT_ARG(m_currentNode, m_currentNode);
+ m_currentNode = m_currentNode->willExecute(callIdentifier);
+}
+
+void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
+{
+ if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) {
+ CString name = callIdentifier.m_name.UTF8String();
+ CString url = callIdentifier.m_url.UTF8String();
+ JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.c_str()), const_cast<char*>(url.c_str()), callIdentifier.m_lineNumber);
+ }
+
+ if (!m_originatingGlobalExec)
+ return;
+
+ ASSERT_ARG(m_currentNode, m_currentNode);
+ if (m_currentNode->callIdentifier() != callIdentifier) {
+ RefPtr<ProfileNode> returningNode = ProfileNode::create(callIdentifier, m_head.get(), m_currentNode.get());
+ returningNode->setStartTime(m_currentNode->startTime());
+ returningNode->didExecute();
+ m_currentNode->insertNode(returningNode.release());
+ return;
+ }
+
+ m_currentNode = m_currentNode->didExecute();
+}
+
+void ProfileGenerator::stopProfiling()
+{
+ m_profile->forEach(&ProfileNode::stopProfiling);
+
+ removeProfileStart();
+ removeProfileEnd();
+
+ ASSERT_ARG(m_currentNode, m_currentNode);
+
+ // Set the current node to the parent, because we are in a call that
+ // will not get didExecute call.
+ m_currentNode = m_currentNode->parent();
+
+ if (double headSelfTime = m_head->selfTime()) {
+ RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, 0, 0), m_head.get(), m_head.get());
+
+ idleNode->setTotalTime(headSelfTime);
+ idleNode->setSelfTime(headSelfTime);
+ idleNode->setVisible(true);
+
+ m_head->setSelfTime(0.0);
+ m_head->addChild(idleNode.release());
+ }
+}
+
+// The console.ProfileGenerator that started this ProfileGenerator will be the first child.
+void ProfileGenerator::removeProfileStart()
+{
+ ProfileNode* currentNode = 0;
+ for (ProfileNode* next = m_head.get(); next; next = next->firstChild())
+ currentNode = next;
+
+ if (currentNode->callIdentifier().m_name != "profile")
+ return;
+
+ // Attribute the time of the node aobut to be removed to the self time of its parent
+ currentNode->parent()->setSelfTime(currentNode->parent()->selfTime() + currentNode->totalTime());
+ currentNode->parent()->removeChild(currentNode);
+}
+
+// The console.ProfileGeneratorEnd that stopped this ProfileGenerator will be the last child.
+void ProfileGenerator::removeProfileEnd()
+{
+ ProfileNode* currentNode = 0;
+ for (ProfileNode* next = m_head.get(); next; next = next->lastChild())
+ currentNode = next;
+
+ if (currentNode->callIdentifier().m_name != "profileEnd")
+ return;
+
+ // Attribute the time of the node aobut to be removed to the self time of its parent
+ currentNode->parent()->setSelfTime(currentNode->parent()->selfTime() + currentNode->totalTime());
+
+ ASSERT(currentNode->callIdentifier() == (currentNode->parent()->children()[currentNode->parent()->children().size() - 1])->callIdentifier());
+ currentNode->parent()->removeChild(currentNode);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileGenerator_h
+#define ProfileGenerator_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class CallIdentifier;
+ class ExecState;
+ class Profile;
+ class ProfileNode;
+ class UString;
+
+ class ProfileGenerator : public RefCounted<ProfileGenerator> {
+ public:
+ static PassRefPtr<ProfileGenerator> create(const UString& title, ExecState* originatingExec, unsigned uid);
+
+ // Members
+ const UString& title() const;
+ PassRefPtr<Profile> profile() const { return m_profile; }
+ ExecState* originatingGlobalExec() const { return m_originatingGlobalExec; }
+ unsigned profileGroup() const { return m_profileGroup; }
+
+ // Collecting
+ void willExecute(const CallIdentifier&);
+ void didExecute(const CallIdentifier&);
+
+ // Stopping Profiling
+ void stopProfiling();
+
+ typedef void (ProfileGenerator::*ProfileFunction)(const CallIdentifier& callIdentifier);
+
+ private:
+ ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid);
+ void addParentForConsoleStart(ExecState*);
+
+ void removeProfileStart();
+ void removeProfileEnd();
+
+ RefPtr<Profile> m_profile;
+ ExecState* m_originatingGlobalExec;
+ unsigned m_profileGroup;
+ RefPtr<ProfileNode> m_head;
+ RefPtr<ProfileNode> m_currentNode;
+ };
+
+} // namespace JSC
+
+#endif // ProfileGenerator_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProfileNode.h"
+
+#include "DateMath.h"
+#include "Profiler.h"
+#include <stdio.h>
+
+#if PLATFORM(WIN_OS)
+#include <windows.h>
+#endif
+
+namespace JSC {
+
+static double getCount()
+{
+#if PLATFORM(WIN_OS)
+ static LARGE_INTEGER frequency = {0};
+ if (!frequency.QuadPart)
+ QueryPerformanceFrequency(&frequency);
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
+#else
+ return getCurrentUTCTimeWithMicroseconds();
+#endif
+}
+
+ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+ : m_callIdentifier(callIdentifier)
+ , m_head(headNode)
+ , m_parent(parentNode)
+ , m_nextSibling(0)
+ , m_startTime(0.0)
+ , m_actualTotalTime(0.0)
+ , m_visibleTotalTime(0.0)
+ , m_actualSelfTime(0.0)
+ , m_visibleSelfTime(0.0)
+ , m_numberOfCalls(0)
+ , m_visible(true)
+{
+ startTimer();
+}
+
+ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
+ : m_callIdentifier(nodeToCopy->callIdentifier())
+ , m_head(headNode)
+ , m_parent(nodeToCopy->parent())
+ , m_nextSibling(0)
+ , m_startTime(0.0)
+ , m_actualTotalTime(nodeToCopy->actualTotalTime())
+ , m_visibleTotalTime(nodeToCopy->totalTime())
+ , m_actualSelfTime(nodeToCopy->actualSelfTime())
+ , m_visibleSelfTime(nodeToCopy->selfTime())
+ , m_numberOfCalls(nodeToCopy->numberOfCalls())
+ , m_visible(nodeToCopy->visible())
+{
+}
+
+ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
+{
+ for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
+ if ((*currentChild)->callIdentifier() == callIdentifier) {
+ (*currentChild)->startTimer();
+ return (*currentChild).get();
+ }
+ }
+
+ RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
+ if (m_children.size())
+ m_children.last()->setNextSibling(newChild.get());
+ m_children.append(newChild.release());
+ return m_children.last().get();
+}
+
+ProfileNode* ProfileNode::didExecute()
+{
+ endAndRecordCall();
+ return m_parent;
+}
+
+void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
+{
+ RefPtr<ProfileNode> child = prpChild;
+ child->setParent(this);
+ if (m_children.size())
+ m_children.last()->setNextSibling(child.get());
+ m_children.append(child.release());
+}
+
+ProfileNode* ProfileNode::findChild(ProfileNode* node) const
+{
+ if (!node)
+ return 0;
+
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ if (*node == m_children[i].get())
+ return m_children[i].get();
+ }
+
+ return 0;
+}
+
+void ProfileNode::removeChild(ProfileNode* node)
+{
+ if (!node)
+ return;
+
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ if (*node == m_children[i].get()) {
+ m_children.remove(i);
+ break;
+ }
+ }
+
+ resetChildrensSiblings();
+}
+
+void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
+{
+ RefPtr<ProfileNode> node = prpNode;
+
+ for (unsigned i = 0; i < m_children.size(); ++i)
+ node->addChild(m_children[i].release());
+
+ m_children.clear();
+ m_children.append(node.release());
+}
+
+void ProfileNode::stopProfiling()
+{
+ if (m_startTime)
+ endAndRecordCall();
+
+ m_visibleTotalTime = m_actualTotalTime;
+
+ ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
+
+ // Because we iterate in post order all of our children have been stopped before us.
+ for (unsigned i = 0; i < m_children.size(); ++i)
+ m_actualSelfTime += m_children[i]->totalTime();
+
+ ASSERT(m_actualSelfTime <= m_actualTotalTime);
+ m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
+ m_visibleSelfTime = m_actualSelfTime;
+}
+
+ProfileNode* ProfileNode::traverseNextNodePostOrder() const
+{
+ ProfileNode* next = m_nextSibling;
+ if (!next)
+ return m_parent;
+ while (ProfileNode* firstChild = next->firstChild())
+ next = firstChild;
+ return next;
+}
+
+ProfileNode* ProfileNode::traverseNextNodePreOrder(bool processChildren) const
+{
+ if (processChildren && m_children.size())
+ return m_children[0].get();
+
+ if (m_nextSibling)
+ return m_nextSibling;
+
+ ProfileNode* nextParent = m_parent;
+ if (!nextParent)
+ return 0;
+
+ ProfileNode* next;
+ for (next = m_parent->nextSibling(); !next; next = nextParent->nextSibling()) {
+ nextParent = nextParent->parent();
+ if (!nextParent)
+ return 0;
+ }
+
+ return next;
+}
+
+void ProfileNode::sort(bool comparator(const RefPtr<ProfileNode>& , const RefPtr<ProfileNode>& ))
+{
+ std::sort(childrenBegin(), childrenEnd(), comparator);
+ resetChildrensSiblings();
+}
+
+void ProfileNode::setTreeVisible(ProfileNode* node, bool visible)
+{
+ ProfileNode* nodeParent = node->parent();
+ ProfileNode* nodeSibling = node->nextSibling();
+ node->setParent(0);
+ node->setNextSibling(0);
+
+ for (ProfileNode* currentNode = node; currentNode; currentNode = currentNode->traverseNextNodePreOrder())
+ currentNode->setVisible(visible);
+
+ node->setParent(nodeParent);
+ node->setNextSibling(nodeSibling);
+}
+
+void ProfileNode::calculateVisibleTotalTime()
+{
+ double sumOfVisibleChildrensTime = 0.0;
+
+ for (unsigned i = 0; i < m_children.size(); ++i) {
+ if (m_children[i]->visible())
+ sumOfVisibleChildrensTime += m_children[i]->totalTime();
+ }
+
+ m_visibleTotalTime = m_visibleSelfTime + sumOfVisibleChildrensTime;
+}
+
+bool ProfileNode::focus(const CallIdentifier& callIdentifier)
+{
+ if (!m_visible)
+ return false;
+
+ if (m_callIdentifier != callIdentifier) {
+ m_visible = false;
+ return true;
+ }
+
+ for (ProfileNode* currentParent = m_parent; currentParent; currentParent = currentParent->parent())
+ currentParent->setVisible(true);
+
+ return false;
+}
+
+void ProfileNode::exclude(const CallIdentifier& callIdentifier)
+{
+ if (m_visible && m_callIdentifier == callIdentifier) {
+ setTreeVisible(this, false);
+
+ m_parent->setVisibleSelfTime(m_parent->selfTime() + m_visibleTotalTime);
+ }
+}
+
+void ProfileNode::restore()
+{
+ m_visibleTotalTime = m_actualTotalTime;
+ m_visibleSelfTime = m_actualSelfTime;
+ m_visible = true;
+}
+
+void ProfileNode::endAndRecordCall()
+{
+ m_actualTotalTime += m_startTime ? getCount() - m_startTime : 0.0;
+ m_startTime = 0.0;
+
+ ++m_numberOfCalls;
+}
+
+void ProfileNode::startTimer()
+{
+ if (!m_startTime)
+ m_startTime = getCount();
+}
+
+void ProfileNode::resetChildrensSiblings()
+{
+ unsigned size = m_children.size();
+ for (unsigned i = 0; i < size; ++i)
+ m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
+}
+
+#ifndef NDEBUG
+void ProfileNode::debugPrintData(int indentLevel) const
+{
+ // Print function names
+ for (int i = 0; i < indentLevel; ++i)
+ printf(" ");
+
+ printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
+ functionName().UTF8String().c_str(),
+ m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
+ m_visibleSelfTime, m_visibleTotalTime,
+ (m_visible ? "True" : "False"),
+ m_nextSibling ? m_nextSibling->functionName().UTF8String().c_str() : "");
+
+ ++indentLevel;
+
+ // Print children's names and information
+ for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+ (*currentChild)->debugPrintData(indentLevel);
+}
+
+// print the profiled data in a format that matches the tool sample's output.
+double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
+{
+ printf(" ");
+
+ // Print function names
+ const char* name = functionName().UTF8String().c_str();
+ double sampleCount = m_actualTotalTime * 1000;
+ if (indentLevel) {
+ for (int i = 0; i < indentLevel; ++i)
+ printf(" ");
+
+ countedFunctions.add(functionName().rep());
+
+ printf("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+ } else
+ printf("%s\n", name);
+
+ ++indentLevel;
+
+ // Print children's names and information
+ double sumOfChildrensCount = 0.0;
+ for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
+ sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
+
+ sumOfChildrensCount *= 1000; //
+ // Print remainder of samples to match sample's output
+ if (sumOfChildrensCount < sampleCount) {
+ printf(" ");
+ while (indentLevel--)
+ printf(" ");
+
+ printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().UTF8String().c_str());
+ }
+
+ return m_actualTotalTime;
+}
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileNode_h
+#define ProfileNode_h
+
+#include "CallIdentifier.h"
+#include <wtf/Vector.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class ProfileNode;
+
+ typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
+ typedef HashCountedSet<UString::Rep*> FunctionCallHashCount;
+
+ class ProfileNode : public RefCounted<ProfileNode> {
+ public:
+ static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+ {
+ return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode));
+ }
+ static PassRefPtr<ProfileNode> create(ProfileNode* headNode, ProfileNode* node)
+ {
+ return adoptRef(new ProfileNode(headNode, node));
+ }
+
+ bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
+
+ ProfileNode* willExecute(const CallIdentifier&);
+ ProfileNode* didExecute();
+
+ void stopProfiling();
+
+ // CallIdentifier members
+ const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
+ const UString& functionName() const { return m_callIdentifier.m_name; }
+ const UString& url() const { return m_callIdentifier.m_url; }
+ unsigned lineNumber() const { return m_callIdentifier.m_lineNumber; }
+
+ // Relationships
+ ProfileNode* head() const { return m_head; }
+ void setHead(ProfileNode* head) { m_head = head; }
+ ProfileNode* parent() const { return m_parent; }
+ void setParent(ProfileNode* parent) { m_parent = parent; }
+ ProfileNode* nextSibling() const { return m_nextSibling; }
+ void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; }
+
+ // Time members
+ double startTime() const { return m_startTime; }
+ void setStartTime(double startTime) { m_startTime = startTime; }
+ double totalTime() const { return m_visibleTotalTime; }
+ double actualTotalTime() const { return m_actualTotalTime; }
+ void setTotalTime(double time) { m_actualTotalTime = time; m_visibleTotalTime = time; }
+ void setActualTotalTime(double time) { m_actualTotalTime = time; }
+ void setVisibleTotalTime(double time) { m_visibleTotalTime = time; }
+ double selfTime() const { return m_visibleSelfTime; }
+ double actualSelfTime() const { return m_actualSelfTime; }
+ void setSelfTime(double time) {m_actualSelfTime = time; m_visibleSelfTime = time; }
+ void setActualSelfTime(double time) { m_actualSelfTime = time; }
+ void setVisibleSelfTime(double time) { m_visibleSelfTime = time; }
+
+ double totalPercent() const { return (m_visibleTotalTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
+ double selfPercent() const { return (m_visibleSelfTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; }
+
+ unsigned numberOfCalls() const { return m_numberOfCalls; }
+ void setNumberOfCalls(unsigned number) { m_numberOfCalls = number; }
+
+ // Children members
+ const Vector<RefPtr<ProfileNode> >& children() const { return m_children; }
+ ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : 0; }
+ ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : 0; }
+ ProfileNode* findChild(ProfileNode*) const;
+ void removeChild(ProfileNode*);
+ void addChild(PassRefPtr<ProfileNode> prpChild);
+ void insertNode(PassRefPtr<ProfileNode> prpNode);
+
+ // Visiblity
+ bool visible() const { return m_visible; }
+ void setVisible(bool visible) { m_visible = visible; }
+
+ static void setTreeVisible(ProfileNode*, bool visible);
+
+ // Sorting
+ ProfileNode* traverseNextNodePostOrder() const;
+ ProfileNode* traverseNextNodePreOrder(bool processChildren = true) const;
+
+ void sort(bool (*)(const RefPtr<ProfileNode>&, const RefPtr<ProfileNode>&));
+ void sortTotalTimeDescending() { sort(totalTimeDescendingComparator); }
+ void sortTotalTimeAscending() { sort(totalTimeAscendingComparator); }
+ void sortSelfTimeDescending() { sort(selfTimeDescendingComparator); }
+ void sortSelfTimeAscending() { sort(selfTimeAscendingComparator); }
+ void sortCallsDescending() { sort(callsDescendingComparator); }
+ void sortCallsAscending() { sort(callsAscendingComparator); }
+ void sortFunctionNameDescending() { sort(functionNameDescendingComparator); }
+ void sortFunctionNameAscending() { sort(functionNameAscendingComparator); }
+
+ // Views
+ void calculateVisibleTotalTime();
+ bool focus(const CallIdentifier&);
+ void exclude(const CallIdentifier&);
+ void restore();
+
+ void endAndRecordCall();
+
+#ifndef NDEBUG
+ const char* c_str() const { return m_callIdentifier; }
+ void debugPrintData(int indentLevel) const;
+ double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&) const;
+#endif
+
+ private:
+ ProfileNode(const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
+ ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy);
+
+ void startTimer();
+ void resetChildrensSiblings();
+
+ RefPtr<ProfileNode>* childrenBegin() { return m_children.begin(); }
+ RefPtr<ProfileNode>* childrenEnd() { return m_children.end(); }
+
+ // Sorting comparators
+ static inline bool totalTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() > b->totalTime(); }
+ static inline bool totalTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->totalTime() < b->totalTime(); }
+ static inline bool selfTimeDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() > b->selfTime(); }
+ static inline bool selfTimeAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->selfTime() < b->selfTime(); }
+ static inline bool callsDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() > b->numberOfCalls(); }
+ static inline bool callsAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->numberOfCalls() < b->numberOfCalls(); }
+ static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() > b->functionName(); }
+ static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() < b->functionName(); }
+
+ CallIdentifier m_callIdentifier;
+ ProfileNode* m_head;
+ ProfileNode* m_parent;
+ ProfileNode* m_nextSibling;
+
+ double m_startTime;
+ double m_actualTotalTime;
+ double m_visibleTotalTime;
+ double m_actualSelfTime;
+ double m_visibleSelfTime;
+ unsigned m_numberOfCalls;
+
+ bool m_visible;
+
+ Vector<RefPtr<ProfileNode> > m_children;
+ };
+
+} // namespace JSC
+
+#endif // ProfileNode_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Profiler.h"
+
+#include "CommonIdentifiers.h"
+#include "CallFrame.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Profile.h"
+#include "ProfileGenerator.h"
+#include "ProfileNode.h"
+#include <stdio.h>
+
+namespace JSC {
+
+static const char* GlobalCodeExecution = "(program)";
+static const char* AnonymousFunction = "(anonymous function)";
+static unsigned ProfilesUID = 0;
+
+static CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData*, JSFunction*);
+
+Profiler* Profiler::s_sharedProfiler = 0;
+Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
+
+Profiler* Profiler::profiler()
+{
+ if (!s_sharedProfiler)
+ s_sharedProfiler = new Profiler();
+ return s_sharedProfiler;
+}
+
+void Profiler::startProfiling(ExecState* exec, const UString& title)
+{
+ // Check if we currently have a Profile for this global ExecState and title.
+ // If so return early and don't create a new Profile.
+ ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+
+ for (size_t i = 0; i < m_currentProfiles.size(); ++i) {
+ ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+ if (profileGenerator->originatingGlobalExec() == globalExec && profileGenerator->title() == title)
+ return;
+ }
+
+ s_sharedEnabledProfilerReference = this;
+ RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(title, exec, ++ProfilesUID);
+ m_currentProfiles.append(profileGenerator);
+}
+
+PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& title)
+{
+ ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+ for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+ ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+ if (profileGenerator->originatingGlobalExec() == globalExec && (title.isNull() || profileGenerator->title() == title)) {
+ profileGenerator->stopProfiling();
+ RefPtr<Profile> returnProfile = profileGenerator->profile();
+
+ m_currentProfiles.remove(i);
+ if (!m_currentProfiles.size())
+ s_sharedEnabledProfilerReference = 0;
+
+ return returnProfile;
+ }
+ }
+
+ return 0;
+}
+
+static inline void dispatchFunctionToProfiles(const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
+{
+ for (size_t i = 0; i < profiles.size(); ++i) {
+ if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec())
+ (profiles[i].get()->*function)(callIdentifier);
+ }
+}
+
+void Profiler::willExecute(ExecState* exec, JSValuePtr function)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), noValue(), sourceURL, startingLineNumber);
+
+ dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::didExecute(ExecState* exec, JSValuePtr function)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+{
+ ASSERT(!m_currentProfiles.isEmpty());
+
+ dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), noValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+}
+
+CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValuePtr function, const UString& defaultSourceURL, int defaultLineNumber)
+{
+ if (!function)
+ return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
+ if (!function.isObject())
+ return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
+ if (asObject(function)->inherits(&JSFunction::info))
+ return createCallIdentifierFromFunctionImp(globalData, asFunction(function));
+ if (asObject(function)->inherits(&InternalFunction::info))
+ return CallIdentifier(static_cast<InternalFunction*>(asObject(function))->name(globalData), defaultSourceURL, defaultLineNumber);
+ return CallIdentifier("(" + asObject(function)->className() + " object)", defaultSourceURL, defaultLineNumber);
+}
+
+CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData* globalData, JSFunction* function)
+{
+ const UString& name = function->name(globalData);
+ return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->body()->sourceURL(), function->body()->lineNo());
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Profiler_h
+#define Profiler_h
+
+#include "Profile.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class CallIdentifier;
+ class ExecState;
+ class JSGlobalData;
+ class JSObject;
+ class JSValuePtr;
+ class ProfileGenerator;
+ class UString;
+
+ class Profiler {
+ public:
+ static Profiler** enabledProfilerReference()
+ {
+ return &s_sharedEnabledProfilerReference;
+ }
+
+ static Profiler* profiler();
+ static CallIdentifier createCallIdentifier(JSGlobalData*, JSValuePtr, const UString& sourceURL, int lineNumber);
+
+ void startProfiling(ExecState*, const UString& title);
+ PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
+
+ void willExecute(ExecState*, JSValuePtr function);
+ void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
+ void didExecute(ExecState*, JSValuePtr function);
+ void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
+
+ const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
+
+ private:
+ Vector<RefPtr<ProfileGenerator> > m_currentProfiles;
+ static Profiler* s_sharedProfiler;
+ static Profiler* s_sharedEnabledProfilerReference;
+ };
+
+} // namespace JSC
+
+#endif // Profiler_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ProfileServer_h
+#define ProfileServer_h
+
+namespace JSC {
+
+void startProfilerServerIfNeeded();
+
+} // namespace JSC
+
+#endif // ProfileServer_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "ProfilerServer.h"
+
+#import "JSProfilerPrivate.h"
+#import "JSRetainPtr.h"
+
+#import <Foundation/Foundation.h>
+#if PLATFORM(IPHONE_SIMULATOR)
+#import <Foundation/NSDistributedNotificationCenter.h>
+#endif
+
+@interface ProfilerServer : NSObject {
+@private
+ NSString *_serverName;
+ unsigned _listenerCount;
+}
++ (ProfilerServer *)sharedProfileServer;
+- (void)startProfiling;
+- (void)stopProfiling;
+@end
+
+@implementation ProfilerServer
+
++ (ProfilerServer *)sharedProfileServer
+{
+ static ProfilerServer *sharedServer;
+ if (!sharedServer)
+ sharedServer = [[ProfilerServer alloc] init];
+ return sharedServer;
+}
+
+- (id)init
+{
+ if (!(self = [super init]))
+ return nil;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ if ([defaults boolForKey:@"EnableJSProfiling"])
+ [self startProfiling];
+
+#if PLATFORM(IPHONE_SIMULATOR)
+ // FIXME: <rdar://problem/6546135>
+ // The catch-all notifications
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(startProfiling) name:@"ProfilerServerStartNotification" object:nil];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(stopProfiling) name:@"ProfilerServerStopNotification" object:nil];
+#endif
+
+ // The specific notifications
+ NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+ _serverName = [[NSString alloc] initWithFormat:@"ProfilerServer-%d", [processInfo processIdentifier]];
+
+#if PLATFORM(IPHONE_SIMULATOR)
+ // FIXME: <rdar://problem/6546135>
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(startProfiling) name:[_serverName stringByAppendingString:@"-Start"] object:nil];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(stopProfiling) name:[_serverName stringByAppendingString:@"-Stop"] object:nil];
+#endif
+
+ [pool drain];
+
+ return self;
+}
+
+- (void)startProfiling
+{
+ if (++_listenerCount > 1)
+ return;
+ JSRetainPtr<JSStringRef> profileName(Adopt, JSStringCreateWithUTF8CString([_serverName UTF8String]));
+ JSStartProfiling(0, profileName.get());
+}
+
+- (void)stopProfiling
+{
+ if (!_listenerCount || --_listenerCount > 0)
+ return;
+ JSRetainPtr<JSStringRef> profileName(Adopt, JSStringCreateWithUTF8CString([_serverName UTF8String]));
+ JSEndProfiling(0, profileName.get());
+}
+
+@end
+
+namespace JSC {
+
+void startProfilerServerIfNeeded()
+{
+ [ProfilerServer sharedProfileServer];
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TreeProfile.h"
+
+#include "HeavyProfile.h"
+
+namespace JSC {
+
+PassRefPtr<TreeProfile> TreeProfile::create(const UString& title, unsigned uid)
+{
+ return adoptRef(new TreeProfile(title, uid));
+}
+
+TreeProfile::TreeProfile(const UString& title, unsigned uid)
+ : Profile(title, uid)
+{
+}
+
+Profile* TreeProfile::heavyProfile()
+{
+ if (!m_heavyProfile)
+ m_heavyProfile = HeavyProfile::create(this);
+
+ return m_heavyProfile.get();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TreeProfile_h
+#define TreeProfile_h
+
+#include "Profile.h"
+
+namespace JSC {
+
+ class ExecState;
+ class HeavyProfile;
+ class UString;
+
+ class TreeProfile : public Profile {
+ public:
+ static PassRefPtr<TreeProfile> create(const UString& title, unsigned uid);
+
+ virtual Profile* heavyProfile();
+ virtual Profile* treeProfile() { return this; }
+
+ private:
+ TreeProfile(const UString& title, unsigned uid);
+ RefPtr<HeavyProfile> m_heavyProfile;
+ };
+
+} // namespace JSC
+
+#endif // TreeProfiler_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ArgList.h"
+
+#include "JSValue.h"
+#include "JSCell.h"
+
+using std::min;
+
+namespace JSC {
+
+void ArgList::getSlice(int startIndex, ArgList& result) const
+{
+ ASSERT(!result.m_isReadOnly);
+
+ const_iterator start = min(begin() + startIndex, end());
+ result.m_vector.appendRange(start, end());
+ result.m_size = result.m_vector.size();
+ result.m_buffer = result.m_vector.data();
+}
+
+void ArgList::markLists(ListSet& markSet)
+{
+ ListSet::iterator end = markSet.end();
+ for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
+ ArgList* list = *it;
+
+ iterator end2 = list->end();
+ for (iterator it2 = list->begin(); it2 != end2; ++it2)
+ if (!(*it2).marked())
+ (*it2).mark();
+ }
+}
+
+void ArgList::slowAppend(JSValuePtr v)
+{
+ // As long as our size stays within our Vector's inline
+ // capacity, all our values are allocated on the stack, and
+ // therefore don't need explicit marking. Once our size exceeds
+ // our Vector's inline capacity, though, our values move to the
+ // heap, where they do need explicit marking.
+ if (!m_markSet) {
+ // We can only register for explicit marking once we know which heap
+ // is the current one, i.e., when a non-immediate value is appended.
+ if (Heap* heap = Heap::heap(v)) {
+ ListSet& markSet = heap->markListSet();
+ markSet.add(this);
+ m_markSet = &markSet;
+ }
+ }
+
+ if (m_vector.size() < m_vector.capacity()) {
+ m_vector.uncheckedAppend(v);
+ return;
+ }
+
+ // 4x growth would be excessive for a normal vector, but it's OK for Lists
+ // because they're short-lived.
+ m_vector.reserveCapacity(m_vector.capacity() * 4);
+
+ m_vector.uncheckedAppend(v);
+ m_buffer = m_vector.data();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ArgList_h
+#define ArgList_h
+
+#include "JSImmediate.h"
+#include "Register.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class ArgList : Noncopyable {
+ private:
+ static const unsigned inlineCapacity = 8;
+ typedef Vector<Register, inlineCapacity> VectorType;
+ typedef HashSet<ArgList*> ListSet;
+
+ public:
+ typedef VectorType::iterator iterator;
+ typedef VectorType::const_iterator const_iterator;
+
+ // Constructor for a read-write list, to which you may append values.
+ // FIXME: Remove all clients of this API, then remove this API.
+ ArgList()
+ : m_markSet(0)
+#ifndef NDEBUG
+ , m_isReadOnly(false)
+#endif
+ {
+ m_buffer = m_vector.data();
+ m_size = 0;
+ }
+
+ // Constructor for a read-only list whose data has already been allocated elsewhere.
+ ArgList(Register* buffer, size_t size)
+ : m_buffer(buffer)
+ , m_size(size)
+ , m_markSet(0)
+#ifndef NDEBUG
+ , m_isReadOnly(true)
+#endif
+ {
+ }
+
+ void initialize(Register* buffer, size_t size)
+ {
+ ASSERT(!m_markSet);
+ ASSERT(isEmpty());
+
+ m_buffer = buffer;
+ m_size = size;
+#ifndef NDEBUG
+ m_isReadOnly = true;
+#endif
+ }
+
+ ~ArgList()
+ {
+ if (m_markSet)
+ m_markSet->remove(this);
+ }
+
+ size_t size() const { return m_size; }
+ bool isEmpty() const { return !m_size; }
+
+ JSValuePtr at(ExecState* exec, size_t i) const
+ {
+ if (i < m_size)
+ return m_buffer[i].jsValue(exec);
+ return jsUndefined();
+ }
+
+ void clear()
+ {
+ m_vector.clear();
+ m_buffer = 0;
+ m_size = 0;
+ }
+
+ void append(JSValuePtr v)
+ {
+ ASSERT(!m_isReadOnly);
+
+ if (m_size < inlineCapacity) {
+ m_vector.uncheckedAppend(v);
+ ++m_size;
+ } else {
+ // Putting this case all in one function measurably improves
+ // the performance of the fast "just append to inline buffer" case.
+ slowAppend(v);
+ ++m_size;
+ }
+ }
+
+ void getSlice(int startIndex, ArgList& result) const;
+
+ iterator begin() { return m_buffer; }
+ iterator end() { return m_buffer + m_size; }
+
+ const_iterator begin() const { return m_buffer; }
+ const_iterator end() const { return m_buffer + m_size; }
+
+ static void markLists(ListSet&);
+
+ private:
+ void slowAppend(JSValuePtr);
+
+ Register* m_buffer;
+ size_t m_size;
+
+ VectorType m_vector;
+ ListSet* m_markSet;
+#ifndef NDEBUG
+ bool m_isReadOnly;
+#endif
+
+ private:
+ // Prohibits new / delete, which would break GC.
+ friend class JSGlobalData;
+
+ void* operator new(size_t size)
+ {
+ return fastMalloc(size);
+ }
+ void operator delete(void* p)
+ {
+ fastFree(p);
+ }
+
+ void* operator new[](size_t);
+ void operator delete[](void*);
+
+ void* operator new(size_t, void*);
+ void operator delete(void*, size_t);
+ };
+
+} // namespace JSC
+
+#endif // ArgList_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Arguments.h"
+
+#include "JSActivation.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+
+using namespace std;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(Arguments);
+
+const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
+
+Arguments::~Arguments()
+{
+ if (d->extraArguments != d->extraArgumentsFixedBuffer)
+ delete [] d->extraArguments;
+}
+
+void Arguments::mark()
+{
+ JSObject::mark();
+
+ if (d->registerArray) {
+ for (unsigned i = 0; i < d->numParameters; ++i) {
+ if (!d->registerArray[i].marked())
+ d->registerArray[i].mark();
+ }
+ }
+
+ if (d->extraArguments) {
+ unsigned numExtraArguments = d->numArguments - d->numParameters;
+ for (unsigned i = 0; i < numExtraArguments; ++i) {
+ if (!d->extraArguments[i].marked())
+ d->extraArguments[i].mark();
+ }
+ }
+
+ if (!d->callee->marked())
+ d->callee->mark();
+
+ if (d->activation && !d->activation->marked())
+ d->activation->mark();
+}
+
+void Arguments::fillArgList(ExecState* exec, ArgList& args)
+{
+ if (LIKELY(!d->deletedArguments)) {
+ if (LIKELY(!d->numParameters)) {
+ args.initialize(d->extraArguments, d->numArguments);
+ return;
+ }
+
+ if (d->numParameters == d->numArguments) {
+ args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
+ return;
+ }
+
+ unsigned parametersLength = min(d->numParameters, d->numArguments);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i)
+ args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ for (; i < d->numArguments; ++i)
+ args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return;
+ }
+
+ unsigned parametersLength = min(d->numParameters, d->numArguments);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i) {
+ if (!d->deletedArguments[i])
+ args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ else
+ args.append(get(exec, i));
+ }
+ for (; i < d->numArguments; ++i) {
+ if (!d->deletedArguments[i])
+ args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ else
+ args.append(get(exec, i));
+ }
+}
+
+bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+{
+ if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters) {
+ slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ } else
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
+}
+
+bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters) {
+ slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ } else
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
+ slot.setValue(jsNumber(exec, d->numArguments));
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
+ slot.setValue(d->callee);
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void Arguments::put(ExecState* exec, unsigned i, JSValuePtr value, PutPropertySlot& slot)
+{
+ if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters)
+ d->registers[d->firstParameterIndex + i] = JSValuePtr(value);
+ else
+ d->extraArguments[i - d->numParameters] = JSValuePtr(value);
+ return;
+ }
+
+ JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
+}
+
+void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters)
+ d->registers[d->firstParameterIndex + i] = JSValuePtr(value);
+ else
+ d->extraArguments[i - d->numParameters] = JSValuePtr(value);
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
+ d->overrodeLength = true;
+ putDirect(propertyName, value, DontEnum);
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
+ d->overrodeCallee = true;
+ putDirect(propertyName, value, DontEnum);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+bool Arguments::deleteProperty(ExecState* exec, unsigned i)
+{
+ if (i < d->numArguments) {
+ if (!d->deletedArguments) {
+ d->deletedArguments.set(new bool[d->numArguments]);
+ memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+ }
+ if (!d->deletedArguments[i]) {
+ d->deletedArguments[i] = true;
+ return true;
+ }
+ }
+
+ return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
+}
+
+bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments) {
+ if (!d->deletedArguments) {
+ d->deletedArguments.set(new bool[d->numArguments]);
+ memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+ }
+ if (!d->deletedArguments[i]) {
+ d->deletedArguments[i] = true;
+ return true;
+ }
+ }
+
+ if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
+ d->overrodeLength = true;
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
+ d->overrodeCallee = true;
+ return true;
+ }
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Arguments_h
+#define Arguments_h
+
+#include "JSActivation.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Interpreter.h"
+
+namespace JSC {
+
+ struct ArgumentsData : Noncopyable {
+ JSActivation* activation;
+
+ unsigned numParameters;
+ ptrdiff_t firstParameterIndex;
+ unsigned numArguments;
+
+ Register* registers;
+ OwnArrayPtr<Register> registerArray;
+
+ Register* extraArguments;
+ OwnArrayPtr<bool> deletedArguments;
+ Register extraArgumentsFixedBuffer[4];
+
+ JSFunction* callee;
+ bool overrodeLength : 1;
+ bool overrodeCallee : 1;
+ };
+
+
+ class Arguments : public JSObject {
+ public:
+ enum NoParametersType { NoParameters };
+
+ Arguments(CallFrame*);
+ Arguments(CallFrame*, NoParametersType);
+ virtual ~Arguments();
+
+ static const ClassInfo info;
+
+ virtual void mark();
+
+ void fillArgList(ExecState*, ArgList&);
+
+ void copyRegisters();
+ bool isTornOff() const { return d->registerArray; }
+ void setActivation(JSActivation* activation)
+ {
+ d->activation = activation;
+ d->registers = &activation->registerAt(0);
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ void init(CallFrame*);
+
+ OwnPtr<ArgumentsData> d;
+ };
+
+ Arguments* asArguments(JSValuePtr);
+
+ inline Arguments* asArguments(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&Arguments::info));
+ return static_cast<Arguments*>(asObject(value));
+ }
+
+ ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
+ {
+ function = callFrame->callee();
+
+ CodeBlock* codeBlock = &function->body()->generatedBytecode();
+ int numParameters = codeBlock->m_numParameters;
+ argc = callFrame->argumentCount();
+
+ if (argc <= numParameters)
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ else
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+
+ argc -= 1; // - 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ }
+
+ inline Arguments::Arguments(CallFrame* callFrame)
+ : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(new ArgumentsData)
+ {
+ JSFunction* callee;
+ ptrdiff_t firstParameterIndex;
+ Register* argv;
+ int numArguments;
+ getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
+
+ d->numParameters = callee->body()->parameterCount();
+ d->firstParameterIndex = firstParameterIndex;
+ d->numArguments = numArguments;
+
+ d->activation = 0;
+ d->registers = callFrame->registers();
+
+ Register* extraArguments;
+ if (d->numArguments <= d->numParameters)
+ extraArguments = 0;
+ else {
+ unsigned numExtraArguments = d->numArguments - d->numParameters;
+ if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
+ extraArguments = new Register[numExtraArguments];
+ else
+ extraArguments = d->extraArgumentsFixedBuffer;
+ for (unsigned i = 0; i < numExtraArguments; ++i)
+ extraArguments[i] = argv[d->numParameters + i];
+ }
+
+ d->extraArguments = extraArguments;
+
+ d->callee = callee;
+ d->overrodeLength = false;
+ d->overrodeCallee = false;
+ }
+
+ inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
+ : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(new ArgumentsData)
+ {
+ ASSERT(!callFrame->callee()->body()->parameterCount());
+
+ unsigned numArguments = callFrame->argumentCount() - 1;
+
+ d->numParameters = 0;
+ d->numArguments = numArguments;
+ d->activation = 0;
+
+ Register* extraArguments;
+ if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
+ extraArguments = new Register[numArguments];
+ else
+ extraArguments = d->extraArgumentsFixedBuffer;
+
+ Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
+ for (unsigned i = 0; i < numArguments; ++i)
+ extraArguments[i] = argv[i];
+
+ d->extraArguments = extraArguments;
+
+ d->callee = callFrame->callee();
+ d->overrodeLength = false;
+ d->overrodeCallee = false;
+ }
+
+ inline void Arguments::copyRegisters()
+ {
+ ASSERT(!isTornOff());
+
+ if (!d->numParameters)
+ return;
+
+ int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
+ size_t registerArraySize = d->numParameters;
+
+ Register* registerArray = new Register[registerArraySize];
+ memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
+ d->registerArray.set(registerArray);
+ d->registers = registerArray + registerOffset;
+ }
+
+ // This JSActivation function is defined here so it can get at Arguments::setRegisters.
+ inline void JSActivation::copyRegisters(Arguments* arguments)
+ {
+ ASSERT(!d()->registerArray);
+
+ size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
+ size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+ size_t numLocals = numVars + numParametersMinusThis;
+
+ if (!numLocals)
+ return;
+
+ int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+ size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
+
+ Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
+ setRegisters(registerArray + registerOffset, registerArray);
+ if (arguments && !arguments->isTornOff())
+ static_cast<Arguments*>(arguments)->setActivation(this);
+ }
+
+} // namespace JSC
+
+#endif // Arguments_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "ArrayConstructor.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "Lookup.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
+
+ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
+{
+ // ECMA 15.4.3.1 Array.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
+{
+ // a single numeric argument denotes the array size (!)
+ if (args.size() == 1 && args.at(exec, 0).isNumber()) {
+ uint32_t n = args.at(exec, 0).toUInt32(exec);
+ if (n != args.at(exec, 0).toNumber(exec))
+ return throwError(exec, RangeError, "Array size is not a small enough positive integer.");
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n);
+ }
+
+ // otherwise the array is constructed with the arguments in it
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), args);
+}
+
+static JSObject* constructWithArrayConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructArrayWithSizeQuirk(exec, args);
+}
+
+// ECMA 15.4.2
+ConstructType ArrayConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithArrayConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValuePtr callArrayConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return constructArrayWithSizeQuirk(exec, args);
+}
+
+// ECMA 15.6.1
+CallType ArrayConstructor::getCallData(CallData& callData)
+{
+ // equivalent to 'new Array(....)'
+ callData.native.function = callArrayConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ArrayConstructor_h
+#define ArrayConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ArrayPrototype;
+
+ class ArrayConstructor : public InternalFunction {
+ public:
+ ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*);
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // ArrayConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "ArrayPrototype.h"
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "ObjectPrototype.h"
+#include "Lookup.h"
+#include "Operations.h"
+#include <algorithm>
+#include <wtf/Assertions.h>
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
+
+static JSValuePtr arrayProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncJoin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncPop(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncPush(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncReverse(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncSort(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncSplice(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncUnShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncEvery(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncForEach(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncSome(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncFilter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncMap(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+}
+
+#include "ArrayPrototype.lut.h"
+
+namespace JSC {
+
+static inline bool isNumericCompareFunction(CallType callType, const CallData& callData)
+{
+ if (callType != CallTypeJS)
+ return false;
+
+ return callData.js.functionBody->bytecode(callData.js.scopeChain).isNumericCompareFunction();
+}
+
+// ------------------------------ ArrayPrototype ----------------------------
+
+const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
+
+/* Source for ArrayPrototype.lut.h
+@begin arrayTable 16
+ toString arrayProtoFuncToString DontEnum|Function 0
+ toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
+ concat arrayProtoFuncConcat DontEnum|Function 1
+ join arrayProtoFuncJoin DontEnum|Function 1
+ pop arrayProtoFuncPop DontEnum|Function 0
+ push arrayProtoFuncPush DontEnum|Function 1
+ reverse arrayProtoFuncReverse DontEnum|Function 0
+ shift arrayProtoFuncShift DontEnum|Function 0
+ slice arrayProtoFuncSlice DontEnum|Function 2
+ sort arrayProtoFuncSort DontEnum|Function 1
+ splice arrayProtoFuncSplice DontEnum|Function 2
+ unshift arrayProtoFuncUnShift DontEnum|Function 1
+ every arrayProtoFuncEvery DontEnum|Function 1
+ forEach arrayProtoFuncForEach DontEnum|Function 1
+ some arrayProtoFuncSome DontEnum|Function 1
+ indexOf arrayProtoFuncIndexOf DontEnum|Function 1
+ lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
+ filter arrayProtoFuncFilter DontEnum|Function 1
+ map arrayProtoFuncMap DontEnum|Function 1
+@end
+*/
+
+// ECMA 15.4.4
+ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure)
+ : JSArray(structure)
+{
+}
+
+bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
+}
+
+// ------------------------------ Array Functions ----------------------------
+
+// Helper function
+static JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index)
+{
+ PropertySlot slot(obj);
+ if (!obj->getPropertySlot(exec, index, slot))
+ return noValue();
+ return slot.getValue(exec, index);
+}
+
+static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value)
+{
+ PutPropertySlot slot;
+ obj->put(exec, propertyName, value, slot);
+}
+
+JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&JSArray::info))
+ return throwError(exec, TypeError);
+ JSObject* thisObj = asArray(thisValue);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(',');
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValuePtr element = thisObj->get(exec, k);
+ if (element.isUndefinedOrNull())
+ continue;
+
+ UString str = element.toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&JSArray::info))
+ return throwError(exec, TypeError);
+ JSObject* thisObj = asArray(thisValue);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(',');
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValuePtr element = thisObj->get(exec, k);
+ if (element.isUndefinedOrNull())
+ continue;
+
+ JSObject* o = element.toObject(exec);
+ JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+ UString str;
+ CallData callData;
+ CallType callType = conversionFunction.getCallData(callData);
+ if (callType != CallTypeNone)
+ str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
+ else
+ str = element.toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+
+ UChar comma = ',';
+ UString separator = args.at(exec, 0).isUndefined() ? UString(&comma, 1) : args.at(exec, 0).toString(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(separator.data(), separator.size());
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValuePtr element = thisObj->get(exec, k);
+ if (element.isUndefinedOrNull())
+ continue;
+
+ UString str = element.toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSArray* arr = constructEmptyArray(exec);
+ int n = 0;
+ JSValuePtr curArg = thisValue.toThisObject(exec);
+ ArgList::const_iterator it = args.begin();
+ ArgList::const_iterator end = args.end();
+ while (1) {
+ if (curArg.isObject(&JSArray::info)) {
+ JSArray* curArray = asArray(curArg);
+ unsigned length = curArray->length();
+ for (unsigned k = 0; k < length; ++k) {
+ if (JSValuePtr v = getProperty(exec, curArray, k))
+ arr->put(exec, n, v);
+ n++;
+ }
+ } else {
+ arr->put(exec, n, curArg);
+ n++;
+ }
+ if (it == end)
+ break;
+ curArg = (*it).jsValue(exec);
+ ++it;
+ }
+ arr->setLength(n);
+ return arr;
+}
+
+JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (exec->interpreter()->isJSArray(thisValue))
+ return asArray(thisValue)->pop();
+
+ JSObject* thisObj = thisValue.toThisObject(exec);
+ JSValuePtr result;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (length == 0) {
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ result = jsUndefined();
+ } else {
+ result = thisObj->get(exec, length - 1);
+ thisObj->deleteProperty(exec, length - 1);
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+ }
+ return result;
+}
+
+JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (exec->interpreter()->isJSArray(thisValue) && args.size() == 1) {
+ JSArray* array = asArray(thisValue);
+ array->push(exec, args.begin()->jsValue(exec));
+ return jsNumber(exec, array->length());
+ }
+
+ JSObject* thisObj = thisValue.toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned n = 0; n < args.size(); n++)
+ thisObj->put(exec, length + n, args.at(exec, n));
+ length += args.size();
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ return jsNumber(exec, length);
+}
+
+JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ unsigned middle = length / 2;
+
+ for (unsigned k = 0; k < middle; k++) {
+ unsigned lk1 = length - k - 1;
+ JSValuePtr obj2 = getProperty(exec, thisObj, lk1);
+ JSValuePtr obj = getProperty(exec, thisObj, k);
+
+ if (obj2)
+ thisObj->put(exec, k, obj2);
+ else
+ thisObj->deleteProperty(exec, k);
+
+ if (obj)
+ thisObj->put(exec, lk1, obj);
+ else
+ thisObj->deleteProperty(exec, lk1);
+ }
+ return thisObj;
+}
+
+JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+ JSValuePtr result;
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (length == 0) {
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ result = jsUndefined();
+ } else {
+ result = thisObj->get(exec, 0);
+ for (unsigned k = 1; k < length; k++) {
+ if (JSValuePtr obj = getProperty(exec, thisObj, k))
+ thisObj->put(exec, k - 1, obj);
+ else
+ thisObj->deleteProperty(exec, k - 1);
+ }
+ thisObj->deleteProperty(exec, length - 1);
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+ }
+ return result;
+}
+
+JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
+
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ // We return a new array
+ JSArray* resObj = constructEmptyArray(exec);
+ JSValuePtr result = resObj;
+ double begin = args.at(exec, 0).toInteger(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (begin >= 0) {
+ if (begin > length)
+ begin = length;
+ } else {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ }
+ double end;
+ if (args.at(exec, 1).isUndefined())
+ end = length;
+ else {
+ end = args.at(exec, 1).toInteger(exec);
+ if (end < 0) {
+ end += length;
+ if (end < 0)
+ end = 0;
+ } else {
+ if (end > length)
+ end = length;
+ }
+ }
+
+ int n = 0;
+ int b = static_cast<int>(begin);
+ int e = static_cast<int>(end);
+ for (int k = b; k < e; k++, n++) {
+ if (JSValuePtr v = getProperty(exec, thisObj, k))
+ resObj->put(exec, n, v);
+ }
+ resObj->setLength(n);
+ return result;
+}
+
+JSValuePtr arrayProtoFuncSort(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+
+ if (thisObj->classInfo() == &JSArray::info) {
+ if (isNumericCompareFunction(callType, callData))
+ asArray(thisObj)->sortNumeric(exec, function, callType, callData);
+ else if (callType != CallTypeNone)
+ asArray(thisObj)->sort(exec, function, callType, callData);
+ else
+ asArray(thisObj)->sort(exec);
+ return thisObj;
+ }
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+
+ if (!length)
+ return thisObj;
+
+ // "Min" sort. Not the fastest, but definitely less code than heapsort
+ // or quicksort, and much less swapping than bubblesort/insertionsort.
+ for (unsigned i = 0; i < length - 1; ++i) {
+ JSValuePtr iObj = thisObj->get(exec, i);
+ unsigned themin = i;
+ JSValuePtr minObj = iObj;
+ for (unsigned j = i + 1; j < length; ++j) {
+ JSValuePtr jObj = thisObj->get(exec, j);
+ double compareResult;
+ if (jObj.isUndefined())
+ compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
+ else if (minObj.isUndefined())
+ compareResult = -1;
+ else if (callType != CallTypeNone) {
+ ArgList l;
+ l.append(jObj);
+ l.append(minObj);
+ compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec);
+ } else
+ compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
+
+ if (compareResult < 0) {
+ themin = j;
+ minObj = jObj;
+ }
+ }
+ // Swap themin and i
+ if (themin > i) {
+ thisObj->put(exec, i, minObj);
+ thisObj->put(exec, themin, iObj);
+ }
+ }
+ return thisObj;
+}
+
+JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ // 15.4.4.12
+ JSArray* resObj = constructEmptyArray(exec);
+ JSValuePtr result = resObj;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (!args.size())
+ return jsUndefined();
+ int begin = args.at(exec, 0).toUInt32(exec);
+ if (begin < 0)
+ begin = std::max<int>(begin + length, 0);
+ else
+ begin = std::min<int>(begin, length);
+
+ unsigned deleteCount;
+ if (args.size() > 1)
+ deleteCount = std::min<int>(std::max<int>(args.at(exec, 1).toUInt32(exec), 0), length - begin);
+ else
+ deleteCount = length - begin;
+
+ for (unsigned k = 0; k < deleteCount; k++) {
+ if (JSValuePtr v = getProperty(exec, thisObj, k + begin))
+ resObj->put(exec, k, v);
+ }
+ resObj->setLength(deleteCount);
+
+ unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
+ if (additionalArgs != deleteCount) {
+ if (additionalArgs < deleteCount) {
+ for (unsigned k = begin; k < length - deleteCount; ++k) {
+ if (JSValuePtr v = getProperty(exec, thisObj, k + deleteCount))
+ thisObj->put(exec, k + additionalArgs, v);
+ else
+ thisObj->deleteProperty(exec, k + additionalArgs);
+ }
+ for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
+ thisObj->deleteProperty(exec, k - 1);
+ } else {
+ for (unsigned k = length - deleteCount; (int)k > begin; --k) {
+ if (JSValuePtr obj = getProperty(exec, thisObj, k + deleteCount - 1))
+ thisObj->put(exec, k + additionalArgs - 1, obj);
+ else
+ thisObj->deleteProperty(exec, k + additionalArgs - 1);
+ }
+ }
+ }
+ for (unsigned k = 0; k < additionalArgs; ++k)
+ thisObj->put(exec, k + begin, args.at(exec, k + 2));
+
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));
+ return result;
+}
+
+JSValuePtr arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ // 15.4.4.13
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ unsigned nrArgs = args.size();
+ if (nrArgs) {
+ for (unsigned k = length; k > 0; --k) {
+ if (JSValuePtr v = getProperty(exec, thisObj, k - 1))
+ thisObj->put(exec, k + nrArgs - 1, v);
+ else
+ thisObj->deleteProperty(exec, k + nrArgs - 1);
+ }
+ }
+ for (unsigned k = 0; k < nrArgs; ++k)
+ thisObj->put(exec, k, args.at(exec, k));
+ JSValuePtr result = jsNumber(exec, length + nrArgs);
+ putProperty(exec, thisObj, exec->propertyNames().length, result);
+ return result;
+}
+
+JSValuePtr arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
+ JSArray* resultArray = constructEmptyArray(exec);
+
+ unsigned filterIndex = 0;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ JSValuePtr v = slot.getValue(exec, k);
+
+ ArgList eachArguments;
+
+ eachArguments.append(v);
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
+
+ if (result.toBoolean(exec))
+ resultArray->put(exec, filterIndex++, v);
+ }
+ return resultArray;
+}
+
+JSValuePtr arrayProtoFuncMap(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+
+ JSArray* resultArray = constructEmptyArray(exec, length);
+
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ JSValuePtr v = slot.getValue(exec, k);
+
+ ArgList eachArguments;
+
+ eachArguments.append(v);
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
+ resultArray->put(exec, k, result);
+ }
+
+ return resultArray;
+}
+
+// Documentation for these three is available at:
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
+
+JSValuePtr arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
+
+ JSValuePtr result = jsBoolean(true);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+
+ if (!predicateResult) {
+ result = jsBoolean(false);
+ break;
+ }
+ }
+
+ return result;
+}
+
+JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ call(exec, function, callType, callData, applyThis, eachArguments);
+ }
+ return jsUndefined();
+}
+
+JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValuePtr function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1).toObject(exec);
+
+ JSValuePtr result = jsBoolean(false);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+
+ if (predicateResult) {
+ result = jsBoolean(true);
+ break;
+ }
+ }
+ return result;
+}
+
+JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ // JavaScript 1.5 Extension by Mozilla
+ // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
+
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ unsigned index = 0;
+ double d = args.at(exec, 1).toInteger(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (d < 0)
+ d += length;
+ if (d > 0) {
+ if (d > length)
+ index = length;
+ else
+ index = static_cast<unsigned>(d);
+ }
+
+ JSValuePtr searchElement = args.at(exec, 0);
+ for (; index < length; ++index) {
+ JSValuePtr e = getProperty(exec, thisObj, index);
+ if (!e)
+ continue;
+ if (JSValuePtr::strictEqual(searchElement, e))
+ return jsNumber(exec, index);
+ }
+
+ return jsNumber(exec, -1);
+}
+
+JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ // JavaScript 1.6 Extension by Mozilla
+ // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
+
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ int index = length - 1;
+ double d = args.at(exec, 1).toIntegerPreserveNaN(exec);
+
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ return jsNumber(exec, -1);
+ }
+ if (d < length)
+ index = static_cast<int>(d);
+
+ JSValuePtr searchElement = args.at(exec, 0);
+ for (; index >= 0; --index) {
+ JSValuePtr e = getProperty(exec, thisObj, index);
+ if (!e)
+ continue;
+ if (JSValuePtr::strictEqual(searchElement, e))
+ return jsNumber(exec, index);
+ }
+
+ return jsNumber(exec, -1);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ArrayPrototype_h
+#define ArrayPrototype_h
+
+#include "JSArray.h"
+#include "Lookup.h"
+
+namespace JSC {
+
+ class ArrayPrototype : public JSArray {
+ public:
+ explicit ArrayPrototype(PassRefPtr<Structure>);
+
+ bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // ArrayPrototype_h
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BatchedTransitionOptimizer_h
+#define BatchedTransitionOptimizer_h
+
+#include <wtf/Noncopyable.h>
+#include "JSObject.h"
+
+namespace JSC {
+
+ class BatchedTransitionOptimizer : Noncopyable {
+ public:
+ BatchedTransitionOptimizer(JSObject* object)
+ : m_object(object)
+ {
+ if (!m_object->structure()->isDictionary())
+ m_object->setStructure(Structure::toDictionaryTransition(m_object->structure()));
+ }
+
+ ~BatchedTransitionOptimizer()
+ {
+ m_object->setStructure(Structure::fromDictionaryTransition(m_object->structure()));
+ }
+
+ private:
+ JSObject* m_object;
+ };
+
+} // namespace JSC
+
+#endif // BatchedTransitionOptimizer_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanConstructor.h"
+
+#include "BooleanPrototype.h"
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
+
+BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+}
+
+// ECMA 15.6.2
+JSObject* constructBoolean(ExecState* exec, const ArgList& args)
+{
+ BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
+ obj->setInternalValue(jsBoolean(args.at(exec, 0).toBoolean(exec)));
+ return obj;
+}
+
+static JSObject* constructWithBooleanConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructBoolean(exec, args);
+}
+
+ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithBooleanConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.6.1
+static JSValuePtr callBooleanConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsBoolean(args.at(exec, 0).toBoolean(exec));
+}
+
+CallType BooleanConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callBooleanConstructor;
+ return CallTypeHost;
+}
+
+JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValuePtr immediateBooleanValue)
+{
+ BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
+ obj->setInternalValue(immediateBooleanValue);
+ return obj;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanConstructor_h
+#define BooleanConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class BooleanPrototype;
+
+ class BooleanConstructor : public InternalFunction {
+ public:
+ BooleanConstructor(ExecState*, PassRefPtr<Structure>, BooleanPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValuePtr);
+ JSObject* constructBoolean(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // BooleanConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
+
+const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
+
+BooleanObject::BooleanObject(PassRefPtr<Structure> structure)
+ : JSWrapperObject(structure)
+{
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanObject_h
+#define BooleanObject_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ class BooleanObject : public JSWrapperObject {
+ public:
+ explicit BooleanObject(PassRefPtr<Structure>);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ BooleanObject* asBooleanObject(JSValuePtr);
+
+ inline BooleanObject* asBooleanObject(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&BooleanObject::info));
+ return static_cast<BooleanObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // BooleanObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+
+// Functions
+static JSValuePtr booleanProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr booleanProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+// ECMA 15.6.4
+
+BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ : BooleanObject(structure)
+{
+ setInternalValue(jsBoolean(false));
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
+}
+
+
+// ------------------------------ Functions --------------------------
+
+// ECMA 15.6.4.2 + 15.6.4.3
+
+JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (thisValue == jsBoolean(false))
+ return jsNontrivialString(exec, "false");
+
+ if (thisValue == jsBoolean(true))
+ return jsNontrivialString(exec, "true");
+
+ if (!thisValue.isObject(&BooleanObject::info))
+ return throwError(exec, TypeError);
+
+ if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
+ return jsNontrivialString(exec, "false");
+
+ ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
+ return jsNontrivialString(exec, "true");
+}
+
+JSValuePtr booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (thisValue.isBoolean())
+ return thisValue;
+
+ if (!thisValue.isObject(&BooleanObject::info))
+ return throwError(exec, TypeError);
+
+ return asBooleanObject(thisValue)->internalValue();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanPrototype_h
+#define BooleanPrototype_h
+
+#include "BooleanObject.h"
+
+namespace JSC {
+
+ class BooleanPrototype : public BooleanObject {
+ public:
+ BooleanPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // BooleanPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CallData.h"
+
+#include "JSFunction.h"
+
+namespace JSC {
+
+JSValuePtr call(ExecState* exec, JSValuePtr functionObject, CallType callType, const CallData& callData, JSValuePtr thisValue, const ArgList& args)
+{
+ if (callType == CallTypeHost)
+ return callData.native.function(exec, asObject(functionObject), thisValue, args);
+ ASSERT(callType == CallTypeJS);
+ // FIXME: Can this be done more efficiently using the callData?
+ return asFunction(functionObject)->call(exec, thisValue, args);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallData_h
+#define CallData_h
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class FunctionBodyNode;
+ class JSObject;
+ class JSValuePtr;
+ class ScopeChainNode;
+
+ enum CallType {
+ CallTypeNone,
+ CallTypeHost,
+ CallTypeJS
+ };
+
+ typedef JSValuePtr (*NativeFunction)(ExecState*, JSObject*, JSValuePtr thisValue, const ArgList&);
+
+ union CallData {
+ struct {
+ NativeFunction function;
+ } native;
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+ JSValuePtr call(ExecState*, JSValuePtr functionObject, CallType, const CallData&, JSValuePtr thisValue, const ArgList&);
+
+} // namespace JSC
+
+#endif // CallData_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ClassInfo_h
+#define ClassInfo_h
+
+#include "CallFrame.h"
+
+namespace JSC {
+
+ struct HashEntry;
+ struct HashTable;
+
+ struct ClassInfo {
+ /**
+ * A string denoting the class name. Example: "Window".
+ */
+ const char* className;
+
+ /**
+ * Pointer to the class information of the base class.
+ * 0L if there is none.
+ */
+ const ClassInfo* parentClass;
+ /**
+ * Static hash-table of properties.
+ * For classes that can be used from multiple threads, it is accessed via a getter function that would typically return a pointer to thread-specific value.
+ */
+ const HashTable* propHashTable(ExecState* exec) const
+ {
+ if (classPropHashTableGetterFunction)
+ return classPropHashTableGetterFunction(exec);
+ return staticPropHashTable;
+ }
+
+ const HashTable* staticPropHashTable;
+ typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*);
+ const ClassPropHashTableGetterFunction classPropHashTableGetterFunction;
+ };
+
+} // namespace JSC
+
+#endif // ClassInfo_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "Collector.h"
+
+#include "ArgList.h"
+#include "CallFrame.h"
+#include "CollectorHeapIterator.h"
+#include "Interpreter.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "Nodes.h"
+#include "Tracing.h"
+#include <algorithm>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/UnusedParam.h>
+
+#if PLATFORM(DARWIN)
+
+#include <mach/mach_port.h>
+#include <mach/mach_init.h>
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#include <mach/vm_map.h>
+
+#elif PLATFORM(WIN_OS)
+
+#include <windows.h>
+
+#elif PLATFORM(UNIX)
+
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#if PLATFORM(SOLARIS)
+#include <thread.h>
+#endif
+
+#if PLATFORM(OPENBSD)
+#include <pthread.h>
+#endif
+
+#if HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
+#endif
+
+#define DEBUG_COLLECTOR 0
+#define COLLECT_ON_EVERY_ALLOCATION 0
+
+using std::max;
+
+namespace JSC {
+
+// tunable parameters
+
+const size_t SPARE_EMPTY_BLOCKS = 2;
+const size_t GROWTH_FACTOR = 2;
+const size_t LOW_WATER_FACTOR = 4;
+const size_t ALLOCATIONS_PER_COLLECTION = 4000;
+// This value has to be a macro to be used in max() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_ARRAY_SIZE (static_cast<size_t>(14))
+
+static void freeHeap(CollectorHeap*);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+#if PLATFORM(DARWIN)
+typedef mach_port_t PlatformThread;
+#elif PLATFORM(WIN_OS)
+struct PlatformThread {
+ PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {}
+ DWORD id;
+ HANDLE handle;
+};
+#endif
+
+class Heap::Thread {
+public:
+ Thread(pthread_t pthread, const PlatformThread& platThread, void* base)
+ : posixThread(pthread)
+ , platformThread(platThread)
+ , stackBase(base)
+ {
+ }
+
+ Thread* next;
+ pthread_t posixThread;
+ PlatformThread platformThread;
+ void* stackBase;
+};
+
+#endif
+
+Heap::Heap(JSGlobalData* globalData)
+ : m_markListSet(0)
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ , m_registeredThreads(0)
+ , m_currentThreadRegistrar(0)
+#endif
+ , m_globalData(globalData)
+{
+ ASSERT(globalData);
+
+ memset(&primaryHeap, 0, sizeof(CollectorHeap));
+ memset(&numberHeap, 0, sizeof(CollectorHeap));
+}
+
+Heap::~Heap()
+{
+ // The destroy function must already have been called, so assert this.
+ ASSERT(!m_globalData);
+}
+
+void Heap::destroy()
+{
+ JSLock lock(false);
+
+ if (!m_globalData)
+ return;
+
+ // The global object is not GC protected at this point, so sweeping may delete it
+ // (and thus the global data) before other objects that may use the global data.
+ RefPtr<JSGlobalData> protect(m_globalData);
+
+ delete m_markListSet;
+ m_markListSet = 0;
+
+ sweep<PrimaryHeap>();
+ // No need to sweep number heap, because the JSNumber destructor doesn't do anything.
+
+ ASSERT(!primaryHeap.numLiveObjects);
+
+ freeHeap(&primaryHeap);
+ freeHeap(&numberHeap);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ if (m_currentThreadRegistrar) {
+ int error = pthread_key_delete(m_currentThreadRegistrar);
+ ASSERT_UNUSED(error, !error);
+ }
+
+ MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
+ for (Heap::Thread* t = m_registeredThreads; t;) {
+ Heap::Thread* next = t->next;
+ delete t;
+ t = next;
+ }
+#endif
+
+ m_globalData = 0;
+}
+
+template <HeapType heapType>
+static NEVER_INLINE CollectorBlock* allocateBlock()
+{
+#if PLATFORM(DARWIN)
+ vm_address_t address = 0;
+ // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>.
+ vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
+#elif PLATFORM(SYMBIAN)
+ // no memory map in symbian, need to hack with fastMalloc
+ void* address = fastMalloc(BLOCK_SIZE);
+ memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
+#elif PLATFORM(WIN_OS)
+ // windows virtual address granularity is naturally 64k
+ LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#elif HAVE(POSIX_MEMALIGN)
+ void* address;
+ posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
+ memset(address, 0, BLOCK_SIZE);
+#else
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#error Need to initialize pagesize safely.
+#endif
+ static size_t pagesize = getpagesize();
+
+ size_t extra = 0;
+ if (BLOCK_SIZE > pagesize)
+ extra = BLOCK_SIZE - pagesize;
+
+ void* mmapResult = mmap(NULL, BLOCK_SIZE + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
+
+ size_t adjust = 0;
+ if ((address & BLOCK_OFFSET_MASK) != 0)
+ adjust = BLOCK_SIZE - (address & BLOCK_OFFSET_MASK);
+
+ if (adjust > 0)
+ munmap(reinterpret_cast<char*>(address), adjust);
+
+ if (adjust < extra)
+ munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
+
+ address += adjust;
+ memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
+#endif
+ reinterpret_cast<CollectorBlock*>(address)->type = heapType;
+ return reinterpret_cast<CollectorBlock*>(address);
+}
+
+static void freeBlock(CollectorBlock* block)
+{
+#if PLATFORM(DARWIN)
+ vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
+#elif PLATFORM(SYMBIAN)
+ fastFree(block);
+#elif PLATFORM(WIN_OS)
+ VirtualFree(block, 0, MEM_RELEASE);
+#elif HAVE(POSIX_MEMALIGN)
+ free(block);
+#else
+ munmap(reinterpret_cast<char*>(block), BLOCK_SIZE);
+#endif
+}
+
+static void freeHeap(CollectorHeap* heap)
+{
+ for (size_t i = 0; i < heap->usedBlocks; ++i)
+ if (heap->blocks[i])
+ freeBlock(heap->blocks[i]);
+ fastFree(heap->blocks);
+ memset(heap, 0, sizeof(CollectorHeap));
+}
+
+void Heap::recordExtraCost(size_t cost)
+{
+ // Our frequency of garbage collection tries to balance memory use against speed
+ // by collecting based on the number of newly created values. However, for values
+ // that hold on to a great deal of memory that's not in the form of other JS values,
+ // that is not good enough - in some cases a lot of those objects can pile up and
+ // use crazy amounts of memory without a GC happening. So we track these extra
+ // memory costs. Only unusually large objects are noted, and we only keep track
+ // of this extra cost until the next GC. In garbage collected languages, most values
+ // are either very short lived temporaries, or have extremely long lifetimes. So
+ // if a large value survives one garbage collection, there is not much point to
+ // collecting more frequently as long as it stays alive.
+ // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost
+
+ primaryHeap.extraCost += cost;
+}
+
+template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
+{
+ typedef typename HeapConstants<heapType>::Block Block;
+ typedef typename HeapConstants<heapType>::Cell Cell;
+
+ CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+ ASSERT(JSLock::lockCount() > 0);
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+ ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize);
+
+ ASSERT(heap.operationInProgress == NoOperation);
+ ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
+ // FIXME: If another global variable access here doesn't hurt performance
+ // too much, we could CRASH() in NDEBUG builds, which could help ensure we
+ // don't spend any time debugging cases where we allocate inside an object's
+ // deallocation code.
+
+#if COLLECT_ON_EVERY_ALLOCATION
+ collect();
+#endif
+
+ size_t numLiveObjects = heap.numLiveObjects;
+ size_t usedBlocks = heap.usedBlocks;
+ size_t i = heap.firstBlockWithPossibleSpace;
+
+ // if we have a huge amount of extra cost, we'll try to collect even if we still have
+ // free cells left.
+ if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) {
+ size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+ size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+ const size_t newCost = numNewObjects + heap.extraCost;
+ if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect)
+ goto collect;
+ }
+
+ ASSERT(heap.operationInProgress == NoOperation);
+#ifndef NDEBUG
+ // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+ heap.operationInProgress = Allocation;
+#endif
+
+scan:
+ Block* targetBlock;
+ size_t targetBlockUsedCells;
+ if (i != usedBlocks) {
+ targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+ targetBlockUsedCells = targetBlock->usedCells;
+ ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+ while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) {
+ if (++i == usedBlocks)
+ goto collect;
+ targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+ targetBlockUsedCells = targetBlock->usedCells;
+ ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+ }
+ heap.firstBlockWithPossibleSpace = i;
+ } else {
+
+collect:
+ size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+ size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+ const size_t newCost = numNewObjects + heap.extraCost;
+
+ if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) {
+#ifndef NDEBUG
+ heap.operationInProgress = NoOperation;
+#endif
+ bool collected = collect();
+#ifndef NDEBUG
+ heap.operationInProgress = Allocation;
+#endif
+ if (collected) {
+ numLiveObjects = heap.numLiveObjects;
+ usedBlocks = heap.usedBlocks;
+ i = heap.firstBlockWithPossibleSpace;
+ goto scan;
+ }
+ }
+
+ // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
+ size_t numBlocks = heap.numBlocks;
+ if (usedBlocks == numBlocks) {
+ static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
+ if (numBlocks > maxNumBlocks)
+ CRASH();
+ numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
+ heap.numBlocks = numBlocks;
+ heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
+ }
+
+ targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
+ targetBlock->freeList = targetBlock->cells;
+ targetBlock->heap = this;
+ targetBlockUsedCells = 0;
+ heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock);
+ heap.usedBlocks = usedBlocks + 1;
+ heap.firstBlockWithPossibleSpace = usedBlocks;
+ }
+
+ // find a free spot in the block and detach it from the free list
+ Cell* newCell = targetBlock->freeList;
+
+ // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized
+ targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next;
+
+ targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
+ heap.numLiveObjects = numLiveObjects + 1;
+
+#ifndef NDEBUG
+ // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+ heap.operationInProgress = NoOperation;
+#endif
+
+ return newCell;
+}
+
+void* Heap::allocate(size_t s)
+{
+ return heapAllocate<PrimaryHeap>(s);
+}
+
+void* Heap::allocateNumber(size_t s)
+{
+ return heapAllocate<NumberHeap>(s);
+}
+
+static inline void* currentThreadStackBase()
+{
+#if PLATFORM(DARWIN)
+ pthread_t thread = pthread_self();
+ return pthread_get_stackaddr_np(thread);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC)
+ // offset 0x18 from the FS segment register gives a pointer to
+ // the thread information block for the current thread
+ NT_TIB* pTib;
+ __asm {
+ MOV EAX, FS:[18h]
+ MOV pTib, EAX
+ }
+ return static_cast<void*>(pTib->StackBase);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
+ PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
+ return reinterpret_cast<void*>(pTib->StackBase);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC)
+ // offset 0x18 from the FS segment register gives a pointer to
+ // the thread information block for the current thread
+ NT_TIB* pTib;
+ asm ( "movl %%fs:0x18, %0\n"
+ : "=r" (pTib)
+ );
+ return static_cast<void*>(pTib->StackBase);
+#elif PLATFORM(SOLARIS)
+ stack_t s;
+ thr_stksegment(&s);
+ return s.ss_sp;
+#elif PLATFORM(OPENBSD)
+ pthread_t thread = pthread_self();
+ stack_t stack;
+ pthread_stackseg_np(thread, &stack);
+ return stack.ss_sp;
+#elif PLATFORM(UNIX)
+ static void* stackBase = 0;
+ static size_t stackSize = 0;
+ static pthread_t stackThread;
+ pthread_t thread = pthread_self();
+ if (stackBase == 0 || thread != stackThread) {
+ pthread_attr_t sattr;
+ pthread_attr_init(&sattr);
+#if HAVE(PTHREAD_NP_H) || PLATFORM(NETBSD)
+ // e.g. on FreeBSD 5.4, neundorf@kde.org
+ pthread_attr_get_np(thread, &sattr);
+#else
+ // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
+ pthread_getattr_np(thread, &sattr);
+#endif
+ int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+ (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
+ ASSERT(stackBase);
+ pthread_attr_destroy(&sattr);
+ stackThread = thread;
+ }
+ return static_cast<char*>(stackBase) + stackSize;
+#elif PLATFORM(SYMBIAN)
+ static void* stackBase = 0;
+ if (stackBase == 0) {
+ TThreadStackInfo info;
+ RThread thread;
+ thread.StackInfo(info);
+ stackBase = (void*)info.iBase;
+ }
+ return (void*)stackBase;
+#else
+#error Need a way to get the stack base on this platform
+#endif
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline PlatformThread getCurrentPlatformThread()
+{
+#if PLATFORM(DARWIN)
+ return pthread_mach_thread_np(pthread_self());
+#elif PLATFORM(WIN_OS)
+ HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());
+ return PlatformThread(GetCurrentThreadId(), threadHandle);
+#endif
+}
+
+void Heap::makeUsableFromMultipleThreads()
+{
+ if (m_currentThreadRegistrar)
+ return;
+
+ int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
+ if (error)
+ CRASH();
+}
+
+void Heap::registerThread()
+{
+ if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
+ return;
+
+ pthread_setspecific(m_currentThreadRegistrar, this);
+ Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
+
+ MutexLocker lock(m_registeredThreadsMutex);
+
+ thread->next = m_registeredThreads;
+ m_registeredThreads = thread;
+}
+
+void Heap::unregisterThread(void* p)
+{
+ if (p)
+ static_cast<Heap*>(p)->unregisterThread();
+}
+
+void Heap::unregisterThread()
+{
+ pthread_t currentPosixThread = pthread_self();
+
+ MutexLocker lock(m_registeredThreadsMutex);
+
+ if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
+ Thread* t = m_registeredThreads;
+ m_registeredThreads = m_registeredThreads->next;
+ delete t;
+ } else {
+ Heap::Thread* last = m_registeredThreads;
+ Heap::Thread* t;
+ for (t = m_registeredThreads->next; t; t = t->next) {
+ if (pthread_equal(t->posixThread, currentPosixThread)) {
+ last->next = t->next;
+ break;
+ }
+ last = t;
+ }
+ ASSERT(t); // If t is NULL, we never found ourselves in the list.
+ delete t;
+ }
+}
+
+#else // ENABLE(JSC_MULTIPLE_THREADS)
+
+void Heap::registerThread()
+{
+}
+
+#endif
+
+#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)
+
+// cell size needs to be a power of two for this to be valid
+#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)
+
+void Heap::markConservatively(void* start, void* end)
+{
+ if (start > end) {
+ void* tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
+ ASSERT(IS_POINTER_ALIGNED(start));
+ ASSERT(IS_POINTER_ALIGNED(end));
+
+ char** p = static_cast<char**>(start);
+ char** e = static_cast<char**>(end);
+
+ size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
+ size_t usedNumberBlocks = numberHeap.usedBlocks;
+ CollectorBlock** primaryBlocks = primaryHeap.blocks;
+ CollectorBlock** numberBlocks = numberHeap.blocks;
+
+ const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
+
+ while (p != e) {
+ char* x = *p++;
+ if (IS_HALF_CELL_ALIGNED(x) && x) {
+ uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
+ xAsBits &= CELL_ALIGN_MASK;
+ uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
+ CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
+ // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
+ for (size_t block = 0; block < usedNumberBlocks; block++) {
+ if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
+ Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));
+ goto endMarkLoop;
+ }
+ }
+
+ // Mark the primary heap
+ for (size_t block = 0; block < usedPrimaryBlocks; block++) {
+ if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
+ if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {
+ JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
+ if (!imp->marked())
+ imp->mark();
+ }
+ break;
+ }
+ }
+ endMarkLoop:
+ ;
+ }
+ }
+}
+
+void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal()
+{
+ void* dummy;
+ void* stackPointer = &dummy;
+ void* stackBase = currentThreadStackBase();
+ markConservatively(stackPointer, stackBase);
+}
+
+void Heap::markCurrentThreadConservatively()
+{
+ // setjmp forces volatile registers onto the stack
+ jmp_buf registers;
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4611)
+#endif
+ setjmp(registers);
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
+ markCurrentThreadConservativelyInternal();
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline void suspendThread(const PlatformThread& platformThread)
+{
+#if PLATFORM(DARWIN)
+ thread_suspend(platformThread);
+#elif PLATFORM(WIN_OS)
+ SuspendThread(platformThread.handle);
+#else
+#error Need a way to suspend threads on this platform
+#endif
+}
+
+static inline void resumeThread(const PlatformThread& platformThread)
+{
+#if PLATFORM(DARWIN)
+ thread_resume(platformThread);
+#elif PLATFORM(WIN_OS)
+ ResumeThread(platformThread.handle);
+#else
+#error Need a way to resume threads on this platform
+#endif
+}
+
+typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
+
+#if PLATFORM(DARWIN)
+
+#if PLATFORM(X86)
+typedef i386_thread_state_t PlatformThreadRegisters;
+#elif PLATFORM(X86_64)
+typedef x86_thread_state64_t PlatformThreadRegisters;
+#elif PLATFORM(PPC)
+typedef ppc_thread_state_t PlatformThreadRegisters;
+#elif PLATFORM(PPC64)
+typedef ppc_thread_state64_t PlatformThreadRegisters;
+#elif PLATFORM(ARM)
+typedef arm_thread_state_t PlatformThreadRegisters;
+#else
+#error Unknown Architecture
+#endif
+
+#elif PLATFORM(WIN_OS)&& PLATFORM(X86)
+typedef CONTEXT PlatformThreadRegisters;
+#else
+#error Need a thread register struct for this platform
+#endif
+
+static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
+{
+#if PLATFORM(DARWIN)
+
+#if PLATFORM(X86)
+ unsigned user_count = sizeof(regs)/sizeof(int);
+ thread_state_flavor_t flavor = i386_THREAD_STATE;
+#elif PLATFORM(X86_64)
+ unsigned user_count = x86_THREAD_STATE64_COUNT;
+ thread_state_flavor_t flavor = x86_THREAD_STATE64;
+#elif PLATFORM(PPC)
+ unsigned user_count = PPC_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#elif PLATFORM(PPC64)
+ unsigned user_count = PPC_THREAD_STATE64_COUNT;
+ thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#elif PLATFORM(ARM)
+ unsigned user_count = ARM_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = ARM_THREAD_STATE;
+#else
+#error Unknown Architecture
+#endif
+
+ kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count);
+ if (result != KERN_SUCCESS) {
+ WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
+ "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
+ CRASH();
+ }
+ return user_count * sizeof(usword_t);
+// end PLATFORM(DARWIN)
+
+#elif PLATFORM(WIN_OS) && PLATFORM(X86)
+ regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+ GetThreadContext(platformThread.handle, ®s);
+ return sizeof(CONTEXT);
+#else
+#error Need a way to get thread registers on this platform
+#endif
+}
+
+static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
+{
+#if PLATFORM(DARWIN)
+
+#if __DARWIN_UNIX03
+
+#if PLATFORM(X86)
+ return reinterpret_cast<void*>(regs.__esp);
+#elif PLATFORM(X86_64)
+ return reinterpret_cast<void*>(regs.__rsp);
+#elif PLATFORM(PPC) || PLATFORM(PPC64)
+ return reinterpret_cast<void*>(regs.__r1);
+#elif PLATFORM(ARM)
+ return reinterpret_cast<void*>(regs.__sp);
+#else
+#error Unknown Architecture
+#endif
+
+#else // !__DARWIN_UNIX03
+
+#if PLATFORM(X86)
+ return reinterpret_cast<void*>(regs.esp);
+#elif PLATFORM(X86_64)
+ return reinterpret_cast<void*>(regs.rsp);
+#elif (PLATFORM(PPC) || PLATFORM(PPC64))
+ return reinterpret_cast<void*>(regs.r1);
+#else
+#error Unknown Architecture
+#endif
+
+#endif // __DARWIN_UNIX03
+
+// end PLATFORM(DARWIN)
+#elif PLATFORM(X86) && PLATFORM(WIN_OS)
+ return reinterpret_cast<void*>((uintptr_t) regs.Esp);
+#else
+#error Need a way to get the stack pointer for another thread on this platform
+#endif
+}
+
+void Heap::markOtherThreadConservatively(Thread* thread)
+{
+ suspendThread(thread->platformThread);
+
+ PlatformThreadRegisters regs;
+ size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
+
+ // mark the thread's registers
+ markConservatively(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize));
+
+ void* stackPointer = otherThreadStackPointer(regs);
+ markConservatively(stackPointer, thread->stackBase);
+
+ resumeThread(thread->platformThread);
+}
+
+#endif
+
+void Heap::markStackObjectsConservatively()
+{
+ markCurrentThreadConservatively();
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+ if (m_currentThreadRegistrar) {
+
+ MutexLocker lock(m_registeredThreadsMutex);
+
+#ifndef NDEBUG
+ // Forbid malloc during the mark phase. Marking a thread suspends it, so
+ // a malloc inside mark() would risk a deadlock with a thread that had been
+ // suspended while holding the malloc lock.
+ fastMallocForbid();
+#endif
+ // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
+ // and since this is a shared heap, they are real locks.
+ for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
+ if (!pthread_equal(thread->posixThread, pthread_self()))
+ markOtherThreadConservatively(thread);
+ }
+#ifndef NDEBUG
+ fastMallocAllow();
+#endif
+ }
+#endif
+}
+
+void Heap::setGCProtectNeedsLocking()
+{
+ // Most clients do not need to call this, with the notable exception of WebCore.
+ // Clients that use shared heap have JSLock protection, while others are supposed
+ // to do explicit locking. WebCore violates this contract in Database code,
+ // which calls gcUnprotect from a secondary thread.
+ if (!m_protectedValuesMutex)
+ m_protectedValuesMutex.set(new Mutex);
+}
+
+void Heap::protect(JSValuePtr k)
+{
+ ASSERT(k);
+ ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
+
+ if (!k.isCell())
+ return;
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ m_protectedValues.add(k.asCell());
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+}
+
+void Heap::unprotect(JSValuePtr k)
+{
+ ASSERT(k);
+ ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
+
+ if (!k.isCell())
+ return;
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ m_protectedValues.remove(k.asCell());
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+}
+
+Heap* Heap::heap(JSValuePtr v)
+{
+ if (!v.isCell())
+ return 0;
+ return Heap::cellBlock(v.asCell())->heap;
+}
+
+void Heap::markProtectedObjects()
+{
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ ProtectCountSet::iterator end = m_protectedValues.end();
+ for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+ JSCell* val = it->first;
+ if (!val->marked())
+ val->mark();
+ }
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+}
+
+template <HeapType heapType> size_t Heap::sweep()
+{
+ typedef typename HeapConstants<heapType>::Block Block;
+ typedef typename HeapConstants<heapType>::Cell Cell;
+
+ // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
+ CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+
+ size_t emptyBlocks = 0;
+ size_t numLiveObjects = heap.numLiveObjects;
+
+ for (size_t block = 0; block < heap.usedBlocks; block++) {
+ Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
+
+ size_t usedCells = curBlock->usedCells;
+ Cell* freeList = curBlock->freeList;
+
+ if (usedCells == HeapConstants<heapType>::cellsPerBlock) {
+ // special case with a block where all cells are used -- testing indicates this happens often
+ for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) {
+ if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+ Cell* cell = curBlock->cells + i;
+
+ if (heapType != NumberHeap) {
+ JSCell* imp = reinterpret_cast<JSCell*>(cell);
+ // special case for allocated but uninitialized object
+ // (We don't need this check earlier because nothing prior this point
+ // assumes the object has a valid vptr.)
+ if (cell->u.freeCell.zeroIfFree == 0)
+ continue;
+
+ imp->~JSCell();
+ }
+
+ --usedCells;
+ --numLiveObjects;
+
+ // put cell on the free list
+ cell->u.freeCell.zeroIfFree = 0;
+ cell->u.freeCell.next = freeList - (cell + 1);
+ freeList = cell;
+ }
+ }
+ } else {
+ size_t minimumCellsToProcess = usedCells;
+ for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) {
+ Cell* cell = curBlock->cells + i;
+ if (cell->u.freeCell.zeroIfFree == 0) {
+ ++minimumCellsToProcess;
+ } else {
+ if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+ if (heapType != NumberHeap) {
+ JSCell* imp = reinterpret_cast<JSCell*>(cell);
+ imp->~JSCell();
+ }
+ --usedCells;
+ --numLiveObjects;
+
+ // put cell on the free list
+ cell->u.freeCell.zeroIfFree = 0;
+ cell->u.freeCell.next = freeList - (cell + 1);
+ freeList = cell;
+ }
+ }
+ }
+ }
+
+ curBlock->usedCells = static_cast<uint32_t>(usedCells);
+ curBlock->freeList = freeList;
+ curBlock->marked.clearAll();
+
+ if (usedCells == 0) {
+ emptyBlocks++;
+ if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
+#if !DEBUG_COLLECTOR
+ freeBlock(reinterpret_cast<CollectorBlock*>(curBlock));
+#endif
+ // swap with the last block so we compact as we go
+ heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
+ heap.usedBlocks--;
+ block--; // Don't move forward a step in this case
+
+ if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
+ heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
+ heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
+ }
+ }
+ }
+ }
+
+ if (heap.numLiveObjects != numLiveObjects)
+ heap.firstBlockWithPossibleSpace = 0;
+
+ heap.numLiveObjects = numLiveObjects;
+ heap.numLiveObjectsAtLastCollect = numLiveObjects;
+ heap.extraCost = 0;
+ return numLiveObjects;
+}
+
+bool Heap::collect()
+{
+#ifndef NDEBUG
+ if (m_globalData->isSharedInstance) {
+ ASSERT(JSLock::lockCount() > 0);
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+ }
+#endif
+
+ ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
+ if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
+ CRASH();
+
+ JAVASCRIPTCORE_GC_BEGIN();
+ primaryHeap.operationInProgress = Collection;
+ numberHeap.operationInProgress = Collection;
+
+ // MARK: first mark all referenced objects recursively starting out from the set of root objects
+
+ markStackObjectsConservatively();
+ markProtectedObjects();
+ if (m_markListSet && m_markListSet->size())
+ ArgList::markLists(*m_markListSet);
+ if (m_globalData->exception && !m_globalData->exception.marked())
+ m_globalData->exception.mark();
+ m_globalData->interpreter->registerFile().markCallFrames(this);
+ m_globalData->smallStrings.mark();
+ if (m_globalData->scopeNodeBeingReparsed)
+ m_globalData->scopeNodeBeingReparsed->mark();
+
+ JAVASCRIPTCORE_GC_MARKED();
+
+ size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
+ size_t numLiveObjects = sweep<PrimaryHeap>();
+ numLiveObjects += sweep<NumberHeap>();
+
+ primaryHeap.operationInProgress = NoOperation;
+ numberHeap.operationInProgress = NoOperation;
+ JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects);
+
+ return numLiveObjects < originalLiveObjects;
+}
+
+size_t Heap::objectCount()
+{
+ return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count();
+}
+
+template <HeapType heapType>
+static void addToStatistics(Heap::Statistics& statistics, const CollectorHeap& heap)
+{
+ typedef HeapConstants<heapType> HC;
+ for (size_t i = 0; i < heap.usedBlocks; ++i) {
+ if (heap.blocks[i]) {
+ statistics.size += BLOCK_SIZE;
+ statistics.free += (HC::cellsPerBlock - heap.blocks[i]->usedCells) * HC::cellSize;
+ }
+ }
+}
+
+Heap::Statistics Heap::statistics() const
+{
+ Statistics statistics = { 0, 0 };
+ JSC::addToStatistics<PrimaryHeap>(statistics, primaryHeap);
+ JSC::addToStatistics<NumberHeap>(statistics, numberHeap);
+ return statistics;
+}
+
+size_t Heap::globalObjectCount()
+{
+ size_t count = 0;
+ if (JSGlobalObject* head = m_globalData->head) {
+ JSGlobalObject* o = head;
+ do {
+ ++count;
+ o = o->next();
+ } while (o != head);
+ }
+ return count;
+}
+
+size_t Heap::protectedGlobalObjectCount()
+{
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ size_t count = 0;
+ if (JSGlobalObject* head = m_globalData->head) {
+ JSGlobalObject* o = head;
+ do {
+ if (m_protectedValues.contains(o))
+ ++count;
+ o = o->next();
+ } while (o != head);
+ }
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+
+ return count;
+}
+
+size_t Heap::protectedObjectCount()
+{
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ size_t result = m_protectedValues.size();
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+
+ return result;
+}
+
+static const char* typeName(JSCell* cell)
+{
+ if (cell->isString())
+ return "string";
+ if (cell->isNumber())
+ return "number";
+ if (cell->isGetterSetter())
+ return "gettersetter";
+ ASSERT(cell->isObject());
+ const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo();
+ return info ? info->className : "Object";
+}
+
+HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
+{
+ HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->lock();
+
+ ProtectCountSet::iterator end = m_protectedValues.end();
+ for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+ counts->add(typeName(it->first));
+
+ if (m_protectedValuesMutex)
+ m_protectedValuesMutex->unlock();
+
+ return counts;
+}
+
+bool Heap::isBusy()
+{
+ return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
+}
+
+Heap::iterator Heap::primaryHeapBegin()
+{
+ return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+}
+
+Heap::iterator Heap::primaryHeapEnd()
+{
+ return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef Collector_h
+#define Collector_h
+
+#include <stddef.h>
+#include <string.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Threading.h>
+
+// This is supremely lame that we require pthreads to build on windows.
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
+
+namespace JSC {
+
+ class ArgList;
+ class CollectorBlock;
+ class JSCell;
+ class JSGlobalData;
+ class JSValuePtr;
+
+ enum OperationInProgress { NoOperation, Allocation, Collection };
+ enum HeapType { PrimaryHeap, NumberHeap };
+
+ template <HeapType> class CollectorHeapIterator;
+
+ struct CollectorHeap {
+ CollectorBlock** blocks;
+ size_t numBlocks;
+ size_t usedBlocks;
+ size_t firstBlockWithPossibleSpace;
+
+ size_t numLiveObjects;
+ size_t numLiveObjectsAtLastCollect;
+ size_t extraCost;
+
+ OperationInProgress operationInProgress;
+ };
+
+ class Heap : Noncopyable {
+ public:
+ class Thread;
+ typedef CollectorHeapIterator<PrimaryHeap> iterator;
+
+ void destroy();
+
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ // We can inline these functions because everything is compiled as
+ // one file, so the heapAllocate template definitions are available.
+ // However, allocateNumber is used via jsNumberCell outside JavaScriptCore.
+ // Thus allocateNumber needs to provide a non-inline version too.
+ void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }
+ void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }
+#endif
+ void* allocateNumber(size_t);
+ void* allocate(size_t);
+
+ bool collect();
+ bool isBusy(); // true if an allocation or collection is in progress
+
+ static const size_t minExtraCostSize = 256;
+
+ void reportExtraMemoryCost(size_t cost);
+
+ size_t objectCount();
+ struct Statistics {
+ size_t size;
+ size_t free;
+ };
+ Statistics statistics() const;
+
+ void setGCProtectNeedsLocking();
+ void protect(JSValuePtr);
+ void unprotect(JSValuePtr);
+
+ static Heap* heap(JSValuePtr); // 0 for immediate values
+
+ size_t globalObjectCount();
+ size_t protectedObjectCount();
+ size_t protectedGlobalObjectCount();
+ HashCountedSet<const char*>* protectedObjectTypeCounts();
+
+ void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+
+ static bool isCellMarked(const JSCell*);
+ static void markCell(JSCell*);
+
+ void markConservatively(void* start, void* end);
+
+ HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
+
+ JSGlobalData* globalData() const { return m_globalData; }
+ static bool isNumber(JSCell*);
+
+ // Iterators for the object heap.
+ iterator primaryHeapBegin();
+ iterator primaryHeapEnd();
+
+ private:
+ template <HeapType heapType> void* heapAllocate(size_t);
+ template <HeapType heapType> size_t sweep();
+ static CollectorBlock* cellBlock(const JSCell*);
+ static size_t cellOffset(const JSCell*);
+
+ friend class JSGlobalData;
+ Heap(JSGlobalData*);
+ ~Heap();
+
+ void recordExtraCost(size_t);
+ void markProtectedObjects();
+ void markCurrentThreadConservatively();
+ void markCurrentThreadConservativelyInternal();
+ void markOtherThreadConservatively(Thread*);
+ void markStackObjectsConservatively();
+
+ typedef HashCountedSet<JSCell*> ProtectCountSet;
+
+ CollectorHeap primaryHeap;
+ CollectorHeap numberHeap;
+
+ OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
+ ProtectCountSet m_protectedValues;
+
+ HashSet<ArgList*>* m_markListSet;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ void makeUsableFromMultipleThreads();
+
+ static void unregisterThread(void*);
+ void unregisterThread();
+
+ Mutex m_registeredThreadsMutex;
+ Thread* m_registeredThreads;
+ pthread_key_t m_currentThreadRegistrar;
+#endif
+
+ JSGlobalData* m_globalData;
+ };
+
+ // tunable parameters
+ template<size_t bytesPerWord> struct CellSize;
+
+ // cell size needs to be a power of two for certain optimizations in collector.cpp
+ template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit
+ template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit
+ const size_t BLOCK_SIZE = 16 * 4096; // 64k
+
+ // derived constants
+ const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
+ const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
+ const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
+ const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
+ const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
+ const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
+ const size_t CELL_MASK = CELL_SIZE - 1;
+ const size_t CELL_ALIGN_MASK = ~CELL_MASK;
+ const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
+ const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
+ const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
+ const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
+
+ struct CollectorBitmap {
+ uint32_t bits[BITMAP_WORDS];
+ bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); }
+ void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); }
+ void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); }
+ void clearAll() { memset(bits, 0, sizeof(bits)); }
+ };
+
+ struct CollectorCell {
+ union {
+ double memory[CELL_ARRAY_LENGTH];
+ struct {
+ void* zeroIfFree;
+ ptrdiff_t next;
+ } freeCell;
+ } u;
+ };
+
+ struct SmallCollectorCell {
+ union {
+ double memory[CELL_ARRAY_LENGTH / 2];
+ struct {
+ void* zeroIfFree;
+ ptrdiff_t next;
+ } freeCell;
+ } u;
+ };
+
+ class CollectorBlock {
+ public:
+ CollectorCell cells[CELLS_PER_BLOCK];
+ uint32_t usedCells;
+ CollectorCell* freeList;
+ CollectorBitmap marked;
+ Heap* heap;
+ HeapType type;
+ };
+
+ class SmallCellCollectorBlock {
+ public:
+ SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
+ uint32_t usedCells;
+ SmallCollectorCell* freeList;
+ CollectorBitmap marked;
+ Heap* heap;
+ HeapType type;
+ };
+
+ template <HeapType heapType> struct HeapConstants;
+
+ template <> struct HeapConstants<PrimaryHeap> {
+ static const size_t cellSize = CELL_SIZE;
+ static const size_t cellsPerBlock = CELLS_PER_BLOCK;
+ static const size_t bitmapShift = 0;
+ typedef CollectorCell Cell;
+ typedef CollectorBlock Block;
+ };
+
+ template <> struct HeapConstants<NumberHeap> {
+ static const size_t cellSize = SMALL_CELL_SIZE;
+ static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
+ static const size_t bitmapShift = 1;
+ typedef SmallCollectorCell Cell;
+ typedef SmallCellCollectorBlock Block;
+ };
+
+ inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
+ {
+ return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
+ }
+
+ inline bool Heap::isNumber(JSCell* cell)
+ {
+ return Heap::cellBlock(cell)->type == NumberHeap;
+ }
+
+ inline size_t Heap::cellOffset(const JSCell* cell)
+ {
+ return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
+ }
+
+ inline bool Heap::isCellMarked(const JSCell* cell)
+ {
+ return cellBlock(cell)->marked.get(cellOffset(cell));
+ }
+
+ inline void Heap::markCell(JSCell* cell)
+ {
+ cellBlock(cell)->marked.set(cellOffset(cell));
+ }
+
+ inline void Heap::reportExtraMemoryCost(size_t cost)
+ {
+ if (cost > minExtraCostSize)
+ recordExtraCost(cost / (CELL_SIZE * 2));
+ }
+
+} // namespace JSC
+
+#endif /* Collector_h */
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Collector.h"
+
+#ifndef CollectorHeapIterator_h
+#define CollectorHeapIterator_h
+
+namespace JSC {
+
+ template <HeapType heapType> class CollectorHeapIterator {
+ public:
+ CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock);
+
+ bool operator!=(const CollectorHeapIterator<heapType>& other) { return m_block != other.m_block || m_cell != other.m_cell; }
+ CollectorHeapIterator<heapType>& operator++();
+ JSCell* operator*() const;
+
+ private:
+ typedef typename HeapConstants<heapType>::Block Block;
+ typedef typename HeapConstants<heapType>::Cell Cell;
+
+ Block** m_block;
+ Block** m_endBlock;
+ Cell* m_cell;
+ Cell* m_endCell;
+ };
+
+ template <HeapType heapType>
+ CollectorHeapIterator<heapType>::CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock)
+ : m_block(reinterpret_cast<Block**>(block))
+ , m_endBlock(reinterpret_cast<Block**>(endBlock))
+ , m_cell(m_block == m_endBlock ? 0 : (*m_block)->cells)
+ , m_endCell(m_block == m_endBlock ? 0 : (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock)
+ {
+ if (m_cell && m_cell->u.freeCell.zeroIfFree == 0)
+ ++*this;
+ }
+
+ template <HeapType heapType>
+ CollectorHeapIterator<heapType>& CollectorHeapIterator<heapType>::operator++()
+ {
+ do {
+ for (++m_cell; m_cell != m_endCell; ++m_cell)
+ if (m_cell->u.freeCell.zeroIfFree != 0) {
+ return *this;
+ }
+
+ if (++m_block != m_endBlock) {
+ m_cell = (*m_block)->cells;
+ m_endCell = (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock;
+ }
+ } while(m_block != m_endBlock);
+
+ m_cell = 0;
+ return *this;
+ }
+
+ template <HeapType heapType>
+ JSCell* CollectorHeapIterator<heapType>::operator*() const
+ {
+ return reinterpret_cast<JSCell*>(m_cell);
+ }
+
+} // namespace JSC
+
+#endif // CollectorHeapIterator_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "CommonIdentifiers.h"
+
+namespace JSC {
+
+const char* const nullCString = 0;
+
+#define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
+
+CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
+ : nullIdentifier(globalData, nullCString)
+ , underscoreProto(globalData, "__proto__")
+ , thisIdentifier(globalData, "this")
+ JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
+{
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2003,2007 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CommonIdentifiers_h
+#define CommonIdentifiers_h
+
+#include "Identifier.h"
+#include <wtf/Noncopyable.h>
+
+// ArgList of property names, passed to a macro so we can do set them up various
+// ways without repeating the list.
+#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+ macro(__defineGetter__) \
+ macro(__defineSetter__) \
+ macro(__lookupGetter__) \
+ macro(__lookupSetter__) \
+ macro(apply) \
+ macro(arguments) \
+ macro(call) \
+ macro(callee) \
+ macro(caller) \
+ macro(compile) \
+ macro(constructor) \
+ macro(eval) \
+ macro(exec) \
+ macro(fromCharCode) \
+ macro(global) \
+ macro(hasOwnProperty) \
+ macro(ignoreCase) \
+ macro(index) \
+ macro(input) \
+ macro(isPrototypeOf) \
+ macro(length) \
+ macro(message) \
+ macro(multiline) \
+ macro(name) \
+ macro(now) \
+ macro(parse) \
+ macro(propertyIsEnumerable) \
+ macro(prototype) \
+ macro(source) \
+ macro(test) \
+ macro(toExponential) \
+ macro(toFixed) \
+ macro(toLocaleString) \
+ macro(toPrecision) \
+ macro(toString) \
+ macro(UTC) \
+ macro(valueOf)
+
+namespace JSC {
+
+ class CommonIdentifiers : Noncopyable {
+ private:
+ CommonIdentifiers(JSGlobalData*);
+ friend class JSGlobalData;
+
+ public:
+ const Identifier nullIdentifier;
+ const Identifier underscoreProto;
+ const Identifier thisIdentifier;
+
+#define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
+ JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL)
+#undef JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL
+ };
+
+} // namespace JSC
+
+#endif // CommonIdentifiers_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007 Apple Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Completion.h"
+
+#include "CallFrame.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "Interpreter.h"
+#include "Parser.h"
+#include "Debugger.h"
+#include <stdio.h>
+
+#if !PLATFORM(WIN_OS)
+#include <unistd.h>
+#endif
+
+namespace JSC {
+
+Completion checkSyntax(ExecState* exec, const SourceCode& source)
+{
+ JSLock lock(exec);
+
+ int errLine;
+ UString errMsg;
+
+ RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+ if (!progNode)
+ return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+ return Completion(Normal);
+}
+
+Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValuePtr thisValue)
+{
+ JSLock lock(exec);
+
+ int errLine;
+ UString errMsg;
+ RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+ if (!programNode)
+ return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+
+ JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
+
+ JSValuePtr exception = noValue();
+ JSValuePtr result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
+
+ if (exception) {
+ if (exception.isObject() && asObject(exception)->isWatchdogException())
+ return Completion(Interrupted, exception);
+ return Completion(Throw, exception);
+ }
+ return Completion(Normal, result);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Completion_h
+#define Completion_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+ class ExecState;
+ class ScopeChain;
+ class SourceCode;
+
+ enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted };
+
+ /*
+ * Completion objects are used to convey the return status and value
+ * from functions.
+ */
+ class Completion {
+ public:
+ Completion(ComplType type = Normal, JSValuePtr value = noValue())
+ : m_type(type)
+ , m_value(value)
+ {
+ }
+
+ ComplType complType() const { return m_type; }
+ JSValuePtr value() const { return m_value; }
+ void setValue(JSValuePtr v) { m_value = v; }
+ bool isValueCompletion() const { return m_value; }
+
+ private:
+ ComplType m_type;
+ JSValuePtr m_value;
+ };
+
+ Completion checkSyntax(ExecState*, const SourceCode&);
+ Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValuePtr thisValue = noValue());
+
+} // namespace JSC
+
+#endif // Completion_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ConstructData.h"
+
+#include "JSFunction.h"
+
+namespace JSC {
+
+JSObject* construct(ExecState* exec, JSValuePtr object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+{
+ if (constructType == ConstructTypeHost)
+ return constructData.native.function(exec, asObject(object), args);
+ ASSERT(constructType == ConstructTypeJS);
+ // FIXME: Can this be done more efficiently using the constructData?
+ return asFunction(object)->construct(exec, args);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConstructData_h
+#define ConstructData_h
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class FunctionBodyNode;
+ class JSObject;
+ class JSValuePtr;
+ class ScopeChainNode;
+
+ enum ConstructType {
+ ConstructTypeNone,
+ ConstructTypeHost,
+ ConstructTypeJS
+ };
+
+ typedef JSObject* (*NativeConstructor)(ExecState*, JSObject*, const ArgList&);
+
+ union ConstructData {
+ struct {
+ NativeConstructor function;
+ } native;
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+ JSObject* construct(ExecState*, JSValuePtr constructor, ConstructType, const ConstructData&, const ArgList&);
+
+} // namespace JSC
+
+#endif // ConstructData_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DateConstructor.h"
+
+#include "DateInstance.h"
+#include "DateMath.h"
+#include "DatePrototype.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include <math.h>
+#include <time.h>
+#include <wtf/MathExtras.h>
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+namespace JSC {
+
+// TODO: MakeTime (15.9.11.1) etc. ?
+
+ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+
+static JSValuePtr dateParse(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateNow(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateUTC(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
+
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 7), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.9.3
+JSObject* constructDate(ExecState* exec, const ArgList& args)
+{
+ int numArgs = args.size();
+
+ double value;
+
+ if (numArgs == 0) // new Date() ECMA 15.9.3.3
+ value = getCurrentUTCTime();
+ else if (numArgs == 1) {
+ if (args.at(exec, 0).isObject(&DateInstance::info))
+ value = asDateInstance(args.at(exec, 0))->internalNumber();
+ else {
+ JSValuePtr primitive = args.at(exec, 0).toPrimitive(exec);
+ if (primitive.isString())
+ value = parseDate(primitive.getString());
+ else
+ value = primitive.toNumber(exec);
+ }
+ } else {
+ if (isnan(args.at(exec, 0).toNumber(exec))
+ || isnan(args.at(exec, 1).toNumber(exec))
+ || (numArgs >= 3 && isnan(args.at(exec, 2).toNumber(exec)))
+ || (numArgs >= 4 && isnan(args.at(exec, 3).toNumber(exec)))
+ || (numArgs >= 5 && isnan(args.at(exec, 4).toNumber(exec)))
+ || (numArgs >= 6 && isnan(args.at(exec, 5).toNumber(exec)))
+ || (numArgs >= 7 && isnan(args.at(exec, 6).toNumber(exec))))
+ value = NaN;
+ else {
+ GregorianDateTime t;
+ int year = args.at(exec, 0).toInt32(exec);
+ t.year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.month = args.at(exec, 1).toInt32(exec);
+ t.monthDay = (numArgs >= 3) ? args.at(exec, 2).toInt32(exec) : 1;
+ t.hour = args.at(exec, 3).toInt32(exec);
+ t.minute = args.at(exec, 4).toInt32(exec);
+ t.second = args.at(exec, 5).toInt32(exec);
+ t.isDST = -1;
+ double ms = (numArgs >= 7) ? args.at(exec, 6).toNumber(exec) : 0;
+ value = gregorianDateTimeToMS(t, ms, false);
+ }
+ }
+
+ DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
+ result->setInternalValue(jsNumber(exec, timeClip(value)));
+ return result;
+}
+
+static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructDate(exec, args);
+}
+
+ConstructType DateConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithDateConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.9.2
+static JSValuePtr callDate(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ time_t localTime = time(0);
+ tm localTM;
+ getLocalTime(&localTime, &localTM);
+ GregorianDateTime ts(localTM);
+ return jsNontrivialString(exec, formatDate(ts) + " " + formatTime(ts, false));
+}
+
+CallType DateConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callDate;
+ return CallTypeHost;
+}
+
+static JSValuePtr dateParse(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, parseDate(args.at(exec, 0).toString(exec)));
+}
+
+static JSValuePtr dateNow(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ return jsNumber(exec, getCurrentUTCTime());
+}
+
+static JSValuePtr dateUTC(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ int n = args.size();
+ if (isnan(args.at(exec, 0).toNumber(exec))
+ || isnan(args.at(exec, 1).toNumber(exec))
+ || (n >= 3 && isnan(args.at(exec, 2).toNumber(exec)))
+ || (n >= 4 && isnan(args.at(exec, 3).toNumber(exec)))
+ || (n >= 5 && isnan(args.at(exec, 4).toNumber(exec)))
+ || (n >= 6 && isnan(args.at(exec, 5).toNumber(exec)))
+ || (n >= 7 && isnan(args.at(exec, 6).toNumber(exec))))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ int year = args.at(exec, 0).toInt32(exec);
+ t.year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.month = args.at(exec, 1).toInt32(exec);
+ t.monthDay = (n >= 3) ? args.at(exec, 2).toInt32(exec) : 1;
+ t.hour = args.at(exec, 3).toInt32(exec);
+ t.minute = args.at(exec, 4).toInt32(exec);
+ t.second = args.at(exec, 5).toInt32(exec);
+ double ms = (n >= 7) ? args.at(exec, 6).toNumber(exec) : 0;
+ return jsNumber(exec, gregorianDateTimeToMS(t, ms, true));
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DateConstructor_h
+#define DateConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class DatePrototype;
+
+ class DateConstructor : public InternalFunction {
+ public:
+ DateConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructDate(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // DateConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DateInstance.h"
+
+#include "DateMath.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+struct DateInstance::Cache {
+ double m_gregorianDateTimeCachedForMS;
+ GregorianDateTime m_cachedGregorianDateTime;
+ double m_gregorianDateTimeUTCCachedForMS;
+ GregorianDateTime m_cachedGregorianDateTimeUTC;
+};
+
+const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
+
+DateInstance::DateInstance(PassRefPtr<Structure> structure)
+ : JSWrapperObject(structure)
+ , m_cache(0)
+{
+}
+
+DateInstance::~DateInstance()
+{
+ delete m_cache;
+}
+
+void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
+{
+ if (!m_cache) {
+ m_cache = new Cache;
+ m_cache->m_gregorianDateTimeCachedForMS = NaN;
+ m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
+ }
+
+ if (outputIsUTC) {
+ if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
+ JSC::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
+ m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
+ }
+ t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
+ } else {
+ if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
+ JSC::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
+ m_cache->m_gregorianDateTimeCachedForMS = milli;
+ }
+ t.copyFrom(m_cache->m_cachedGregorianDateTime);
+ }
+}
+
+bool DateInstance::getTime(GregorianDateTime& t, int& offset) const
+{
+ double milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ msToGregorianDateTime(milli, false, t);
+ offset = gmtoffset(t);
+ return true;
+}
+
+bool DateInstance::getUTCTime(GregorianDateTime& t) const
+{
+ double milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ msToGregorianDateTime(milli, true, t);
+ return true;
+}
+
+bool DateInstance::getTime(double& milli, int& offset) const
+{
+ milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ GregorianDateTime t;
+ msToGregorianDateTime(milli, false, t);
+ offset = gmtoffset(t);
+ return true;
+}
+
+bool DateInstance::getUTCTime(double& milli) const
+{
+ milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ return true;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DateInstance_h
+#define DateInstance_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ struct GregorianDateTime;
+
+ class DateInstance : public JSWrapperObject {
+ public:
+ explicit DateInstance(PassRefPtr<Structure>);
+ virtual ~DateInstance();
+
+ double internalNumber() const { return internalValue().uncheckedGetNumber(); }
+
+ bool getTime(GregorianDateTime&, int& offset) const;
+ bool getUTCTime(GregorianDateTime&) const;
+ bool getTime(double& milliseconds, int& offset) const;
+ bool getUTCTime(double& milliseconds) const;
+
+ static const ClassInfo info;
+
+ void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&) const;
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ using JSWrapperObject::internalValue;
+
+ struct Cache;
+ mutable Cache* m_cache;
+ };
+
+ DateInstance* asDateInstance(JSValuePtr);
+
+ inline DateInstance* asDateInstance(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&DateInstance::info));
+ return static_cast<DateInstance*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // DateInstance_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "DateMath.h"
+
+#include "JSNumberCell.h"
+#include <math.h>
+#include <stdint.h>
+#include <time.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
+#if PLATFORM(DARWIN)
+#include <notify.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+#if HAVE(STRINGS_H)
+#include <strings.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+/* Constants */
+
+static const double minutesPerDay = 24.0 * 60.0;
+static const double secondsPerDay = 24.0 * 60.0 * 60.0;
+static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
+
+static const double usecPerSec = 1000000.0;
+
+static const double maxUnixTime = 2145859200.0; // 12/31/2037
+
+// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
+// First for non-leap years, then for leap years.
+static const int firstDayOfMonth[2][12] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
+};
+
+static inline bool isLeapYear(int year)
+{
+ if (year % 4 != 0)
+ return false;
+ if (year % 400 == 0)
+ return true;
+ if (year % 100 == 0)
+ return false;
+ return true;
+}
+
+static inline int daysInYear(int year)
+{
+ return 365 + isLeapYear(year);
+}
+
+static inline double daysFrom1970ToYear(int year)
+{
+ // The Gregorian Calendar rules for leap years:
+ // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years.
+ // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years.
+ // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years.
+
+ static const int leapDaysBefore1971By4Rule = 1970 / 4;
+ static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
+ static const int leapDaysBefore1971By400Rule = 1970 / 400;
+
+ const double yearMinusOne = year - 1;
+ const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
+ const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
+ const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
+
+ return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
+}
+
+static inline double msToDays(double ms)
+{
+ return floor(ms / msPerDay);
+}
+
+static inline int msToYear(double ms)
+{
+ int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
+ double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
+ if (msFromApproxYearTo1970 > ms)
+ return approxYear - 1;
+ if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
+ return approxYear + 1;
+ return approxYear;
+}
+
+static inline int dayInYear(double ms, int year)
+{
+ return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
+}
+
+static inline double msToMilliseconds(double ms)
+{
+ double result = fmod(ms, msPerDay);
+ if (result < 0)
+ result += msPerDay;
+ return result;
+}
+
+// 0: Sunday, 1: Monday, etc.
+static inline int msToWeekDay(double ms)
+{
+ int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
+ if (wd < 0)
+ wd += 7;
+ return wd;
+}
+
+static inline int msToSeconds(double ms)
+{
+ double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
+ if (result < 0)
+ result += secondsPerMinute;
+ return static_cast<int>(result);
+}
+
+static inline int msToMinutes(double ms)
+{
+ double result = fmod(floor(ms / msPerMinute), minutesPerHour);
+ if (result < 0)
+ result += minutesPerHour;
+ return static_cast<int>(result);
+}
+
+static inline int msToHours(double ms)
+{
+ double result = fmod(floor(ms/msPerHour), hoursPerDay);
+ if (result < 0)
+ result += hoursPerDay;
+ return static_cast<int>(result);
+}
+
+static inline int monthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+
+ if (d < (step = 31))
+ return 0;
+ step += (leapYear ? 29 : 28);
+ if (d < step)
+ return 1;
+ if (d < (step += 31))
+ return 2;
+ if (d < (step += 30))
+ return 3;
+ if (d < (step += 31))
+ return 4;
+ if (d < (step += 30))
+ return 5;
+ if (d < (step += 31))
+ return 6;
+ if (d < (step += 31))
+ return 7;
+ if (d < (step += 30))
+ return 8;
+ if (d < (step += 31))
+ return 9;
+ if (d < (step += 30))
+ return 10;
+ return 11;
+}
+
+static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
+{
+ startDayOfThisMonth = startDayOfNextMonth;
+ startDayOfNextMonth += daysInThisMonth;
+ return (dayInYear <= startDayOfNextMonth);
+}
+
+static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+ int next = 30;
+
+ if (d <= next)
+ return d + 1;
+ const int daysInFeb = (leapYear ? 29 : 28);
+ if (checkMonth(d, step, next, daysInFeb))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ step = next;
+ return d - step;
+}
+
+static inline int monthToDayInYear(int month, bool isLeapYear)
+{
+ return firstDayOfMonth[isLeapYear][month];
+}
+
+static inline double timeToMS(double hour, double min, double sec, double ms)
+{
+ return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
+}
+
+static int dateToDayInYear(int year, int month, int day)
+{
+ year += month / 12;
+
+ month %= 12;
+ if (month < 0) {
+ month += 12;
+ --year;
+ }
+
+ int yearday = static_cast<int>(floor(daysFrom1970ToYear(year)));
+ int monthday = monthToDayInYear(month, isLeapYear(year));
+
+ return yearday + monthday + day - 1;
+}
+
+double getCurrentUTCTime()
+{
+ return floor(getCurrentUTCTimeWithMicroseconds());
+}
+
+// Returns current time in milliseconds since 1 Jan 1970.
+double getCurrentUTCTimeWithMicroseconds()
+{
+ return currentTime() * 1000.0;
+}
+
+void getLocalTime(const time_t* localTime, struct tm* localTM)
+{
+#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WIN_CE)
+ *localTM = *localtime(localTime);
+#elif COMPILER(MSVC)
+ localtime_s(localTM, localTime);
+#else
+ localtime_r(localTime, localTM);
+#endif
+}
+
+// There is a hard limit at 2038 that we currently do not have a workaround
+// for (rdar://problem/5052975).
+static inline int maximumYearForDST()
+{
+ return 2037;
+}
+
+static inline int minimumYearForDST()
+{
+ // Because of the 2038 issue (see maximumYearForDST) if the current year is
+ // greater than the max year minus 27 (2010), we want to use the max year
+ // minus 27 instead, to ensure there is a range of 28 years that all years
+ // can map to.
+ return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
+}
+
+/*
+ * Find an equivalent year for the one given, where equivalence is deterined by
+ * the two years having the same leapness and the first day of the year, falling
+ * on the same day of the week.
+ *
+ * This function returns a year between this current year and 2037, however this
+ * function will potentially return incorrect results if the current year is after
+ * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after
+ * 2100, (rdar://problem/5055038).
+ */
+int equivalentYearForDST(int year)
+{
+ // It is ok if the cached year is not the current year as long as the rules
+ // for DST did not change between the two years; if they did the app would need
+ // to be restarted.
+ static int minYear = minimumYearForDST();
+ int maxYear = maximumYearForDST();
+
+ int difference;
+ if (year > maxYear)
+ difference = minYear - year;
+ else if (year < minYear)
+ difference = maxYear - year;
+ else
+ return year;
+
+ int quotient = difference / 28;
+ int product = (quotient) * 28;
+
+ year += product;
+ ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN)));
+ return year;
+}
+
+static int32_t calculateUTCOffset()
+{
+ tm localt;
+ memset(&localt, 0, sizeof(localt));
+
+ // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
+ localt.tm_mday = 1;
+ localt.tm_year = 100;
+ time_t utcOffset = 946684800 - mktime(&localt);
+
+ return static_cast<int32_t>(utcOffset * 1000);
+}
+
+#if PLATFORM(DARWIN)
+static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path.
+static bool s_haveCachedUTCOffset;
+static int s_notificationToken;
+#endif
+
+/*
+ * Get the difference in milliseconds between this time zone and UTC (GMT)
+ * NOT including DST.
+ */
+double getUTCOffset()
+{
+#if PLATFORM(DARWIN)
+ if (s_haveCachedUTCOffset) {
+ int notified;
+ uint32_t status = notify_check(s_notificationToken, ¬ified);
+ if (status == NOTIFY_STATUS_OK && !notified)
+ return s_cachedUTCOffset;
+ }
+#endif
+
+ int32_t utcOffset = calculateUTCOffset();
+
+#if PLATFORM(DARWIN)
+ // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition,
+ // and a newer value may be overwritten. In practice, time zones don't change that often.
+ s_cachedUTCOffset = utcOffset;
+#endif
+
+ return utcOffset;
+}
+
+/*
+ * Get the DST offset for the time passed in. Takes
+ * seconds (not milliseconds) and cannot handle dates before 1970
+ * on some OS'
+ */
+static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset)
+{
+ if (localTimeSeconds > maxUnixTime)
+ localTimeSeconds = maxUnixTime;
+ else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0)
+ localTimeSeconds += secondsPerDay;
+
+ //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset()
+ double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset;
+
+ // Offset from UTC but doesn't include DST obviously
+ int offsetHour = msToHours(offsetTime);
+ int offsetMinute = msToMinutes(offsetTime);
+
+ // FIXME: time_t has a potential problem in 2038
+ time_t localTime = static_cast<time_t>(localTimeSeconds);
+
+ tm localTM;
+ getLocalTime(&localTime, &localTM);
+
+ double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60);
+
+ if (diff < 0)
+ diff += secondsPerDay;
+
+ return (diff * msPerSecond);
+}
+
+// Get the DST offset, given a time in UTC
+static double getDSTOffset(double ms, double utcOffset)
+{
+ // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate
+ // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
+ // standard explicitly dictates that historical information should not be considered when
+ // determining DST. For this reason we shift away from years that localtime can handle but would
+ // return historically accurate information.
+ int year = msToYear(ms);
+ int equivalentYear = equivalentYearForDST(year);
+ if (year != equivalentYear) {
+ bool leapYear = isLeapYear(year);
+ int dayInYearLocal = dayInYear(ms, year);
+ int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
+ int month = monthFromDayInYear(dayInYearLocal, leapYear);
+ int day = dateToDayInYear(equivalentYear, month, dayInMonth);
+ ms = (day * msPerDay) + msToMilliseconds(ms);
+ }
+
+ return getDSTOffsetSimple(ms / msPerSecond, utcOffset);
+}
+
+double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
+{
+ int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay);
+ double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
+ double result = (day * msPerDay) + ms;
+
+ if (!inputIsUTC) { // convert to UTC
+ double utcOffset = getUTCOffset();
+ result -= utcOffset;
+ result -= getDSTOffset(result, utcOffset);
+ }
+
+ return result;
+}
+
+void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm)
+{
+ // input is UTC
+ double dstOff = 0.0;
+ const double utcOff = getUTCOffset();
+
+ if (!outputIsUTC) { // convert to local time
+ dstOff = getDSTOffset(ms, utcOff);
+ ms += dstOff + utcOff;
+ }
+
+ const int year = msToYear(ms);
+ tm.second = msToSeconds(ms);
+ tm.minute = msToMinutes(ms);
+ tm.hour = msToHours(ms);
+ tm.weekDay = msToWeekDay(ms);
+ tm.yearDay = dayInYear(ms, year);
+ tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.year = year - 1900;
+ tm.isDST = dstOff != 0.0;
+
+ tm.utcOffset = static_cast<long>((dstOff + utcOff) / msPerSecond);
+ tm.timeZone = NULL;
+}
+
+void initDateMath()
+{
+#ifndef NDEBUG
+ static bool alreadyInitialized;
+ ASSERT(!alreadyInitialized++);
+#endif
+
+ equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
+#if PLATFORM(DARWIN)
+ // Register for a notification whenever the time zone changes.
+ uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken);
+ if (status == NOTIFY_STATUS_OK) {
+ s_cachedUTCOffset = calculateUTCOffset();
+ s_haveCachedUTCOffset = true;
+ }
+#endif
+}
+
+static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
+{
+ double days = (day - 32075)
+ + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
+ + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
+ - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
+ - 2440588;
+ return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
+}
+
+// We follow the recommendation of RFC 2822 to consider all
+// obsolete time zones not listed here equivalent to "-0000".
+static const struct KnownZone {
+#if !PLATFORM(WIN_OS)
+ const
+#endif
+ char tzName[4];
+ int tzOffset;
+} known_zones[] = {
+ { "UT", 0 },
+ { "GMT", 0 },
+ { "EST", -300 },
+ { "EDT", -240 },
+ { "CST", -360 },
+ { "CDT", -300 },
+ { "MST", -420 },
+ { "MDT", -360 },
+ { "PST", -480 },
+ { "PDT", -420 }
+};
+
+inline static void skipSpacesAndComments(const char*& s)
+{
+ int nesting = 0;
+ char ch;
+ while ((ch = *s)) {
+ if (!isASCIISpace(ch)) {
+ if (ch == '(')
+ nesting++;
+ else if (ch == ')' && nesting > 0)
+ nesting--;
+ else if (nesting == 0)
+ break;
+ }
+ s++;
+ }
+}
+
+// returns 0-11 (Jan-Dec); -1 on failure
+static int findMonth(const char* monthStr)
+{
+ ASSERT(monthStr);
+ char needle[4];
+ for (int i = 0; i < 3; ++i) {
+ if (!*monthStr)
+ return -1;
+ needle[i] = static_cast<char>(toASCIILower(*monthStr++));
+ }
+ needle[3] = '\0';
+ const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
+ const char *str = strstr(haystack, needle);
+ if (str) {
+ int position = static_cast<int>(str - haystack);
+ if (position % 3 == 0)
+ return position / 3;
+ }
+ return -1;
+}
+
+static bool parseLong(const char* string, char** stopPosition, int base, long* result)
+{
+ *result = strtol(string, stopPosition, base);
+ // Avoid the use of errno as it is not available on Windows CE
+ if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX)
+ return false;
+ return true;
+}
+
+double parseDate(const UString &date)
+{
+ // This parses a date in the form:
+ // Tuesday, 09-Nov-99 23:12:40 GMT
+ // or
+ // Sat, 01-Jan-2000 08:00:00 GMT
+ // or
+ // Sat, 01 Jan 2000 08:00:00 GMT
+ // or
+ // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
+ // ### non RFC formats, added for Javascript:
+ // [Wednesday] January 09 1999 23:12:40 GMT
+ // [Wednesday] January 09 23:12:40 GMT 1999
+ //
+ // We ignore the weekday.
+
+ CString dateCString = date.UTF8String();
+ const char *dateString = dateCString.c_str();
+
+ // Skip leading space
+ skipSpacesAndComments(dateString);
+
+ long month = -1;
+ const char *wordStart = dateString;
+ // Check contents of first words if not number
+ while (*dateString && !isASCIIDigit(*dateString)) {
+ if (isASCIISpace(*dateString) || *dateString == '(') {
+ if (dateString - wordStart >= 3)
+ month = findMonth(wordStart);
+ skipSpacesAndComments(dateString);
+ wordStart = dateString;
+ } else
+ dateString++;
+ }
+
+ // Missing delimiter between month and day (like "January29")?
+ if (month == -1 && wordStart != dateString)
+ month = findMonth(wordStart);
+
+ skipSpacesAndComments(dateString);
+
+ if (!*dateString)
+ return NaN;
+
+ // ' 09-Nov-99 23:12:40 GMT'
+ char* newPosStr;
+ long day;
+ if (!parseLong(dateString, &newPosStr, 10, &day))
+ return NaN;
+ dateString = newPosStr;
+
+ if (!*dateString)
+ return NaN;
+
+ if (day < 0)
+ return NaN;
+
+ long year = 0;
+ if (day > 31) {
+ // ### where is the boundary and what happens below?
+ if (*dateString != '/')
+ return NaN;
+ // looks like a YYYY/MM/DD date
+ if (!*++dateString)
+ return NaN;
+ year = day;
+ if (!parseLong(dateString, &newPosStr, 10, &month))
+ return NaN;
+ month -= 1;
+ dateString = newPosStr;
+ if (*dateString++ != '/' || !*dateString)
+ return NaN;
+ if (!parseLong(dateString, &newPosStr, 10, &day))
+ return NaN;
+ dateString = newPosStr;
+ } else if (*dateString == '/' && month == -1) {
+ dateString++;
+ // This looks like a MM/DD/YYYY date, not an RFC date.
+ month = day - 1; // 0-based
+ if (!parseLong(dateString, &newPosStr, 10, &day))
+ return NaN;
+ if (day < 1 || day > 31)
+ return NaN;
+ dateString = newPosStr;
+ if (*dateString == '/')
+ dateString++;
+ if (!*dateString)
+ return NaN;
+ } else {
+ if (*dateString == '-')
+ dateString++;
+
+ skipSpacesAndComments(dateString);
+
+ if (*dateString == ',')
+ dateString++;
+
+ if (month == -1) { // not found yet
+ month = findMonth(dateString);
+ if (month == -1)
+ return NaN;
+
+ while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
+ dateString++;
+
+ if (!*dateString)
+ return NaN;
+
+ // '-99 23:12:40 GMT'
+ if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
+ return NaN;
+ dateString++;
+ }
+ }
+
+ if (month < 0 || month > 11)
+ return NaN;
+
+ // '99 23:12:40 GMT'
+ if (year <= 0 && *dateString) {
+ if (!parseLong(dateString, &newPosStr, 10, &year))
+ return NaN;
+ }
+
+ // Don't fail if the time is missing.
+ long hour = 0;
+ long minute = 0;
+ long second = 0;
+ if (!*newPosStr)
+ dateString = newPosStr;
+ else {
+ // ' 23:12:40 GMT'
+ if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
+ if (*newPosStr != ':')
+ return NaN;
+ // There was no year; the number was the hour.
+ year = -1;
+ } else {
+ // in the normal case (we parsed the year), advance to the next number
+ dateString = ++newPosStr;
+ skipSpacesAndComments(dateString);
+ }
+
+ parseLong(dateString, &newPosStr, 10, &hour);
+ // Do not check for errno here since we want to continue
+ // even if errno was set becasue we are still looking
+ // for the timezone!
+
+ // Read a number? If not, this might be a timezone name.
+ if (newPosStr != dateString) {
+ dateString = newPosStr;
+
+ if (hour < 0 || hour > 23)
+ return NaN;
+
+ if (!*dateString)
+ return NaN;
+
+ // ':12:40 GMT'
+ if (*dateString++ != ':')
+ return NaN;
+
+ if (!parseLong(dateString, &newPosStr, 10, &minute))
+ return NaN;
+ dateString = newPosStr;
+
+ if (minute < 0 || minute > 59)
+ return NaN;
+
+ // ':40 GMT'
+ if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
+ return NaN;
+
+ // seconds are optional in rfc822 + rfc2822
+ if (*dateString ==':') {
+ dateString++;
+
+ if (!parseLong(dateString, &newPosStr, 10, &second))
+ return NaN;
+ dateString = newPosStr;
+
+ if (second < 0 || second > 59)
+ return NaN;
+ }
+
+ skipSpacesAndComments(dateString);
+
+ if (strncasecmp(dateString, "AM", 2) == 0) {
+ if (hour > 12)
+ return NaN;
+ if (hour == 12)
+ hour = 0;
+ dateString += 2;
+ skipSpacesAndComments(dateString);
+ } else if (strncasecmp(dateString, "PM", 2) == 0) {
+ if (hour > 12)
+ return NaN;
+ if (hour != 12)
+ hour += 12;
+ dateString += 2;
+ skipSpacesAndComments(dateString);
+ }
+ }
+ }
+
+ bool haveTZ = false;
+ int offset = 0;
+
+ // Don't fail if the time zone is missing.
+ // Some websites omit the time zone (4275206).
+ if (*dateString) {
+ if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
+ dateString += 3;
+ haveTZ = true;
+ }
+
+ if (*dateString == '+' || *dateString == '-') {
+ long o;
+ if (!parseLong(dateString, &newPosStr, 10, &o))
+ return NaN;
+ dateString = newPosStr;
+
+ if (o < -9959 || o > 9959)
+ return NaN;
+
+ int sgn = (o < 0) ? -1 : 1;
+ o = abs(o);
+ if (*dateString != ':') {
+ offset = ((o / 100) * 60 + (o % 100)) * sgn;
+ } else { // GMT+05:00
+ long o2;
+ if (!parseLong(dateString, &newPosStr, 10, &o2))
+ return NaN;
+ dateString = newPosStr;
+ offset = (o * 60 + o2) * sgn;
+ }
+ haveTZ = true;
+ } else {
+ for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
+ if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
+ offset = known_zones[i].tzOffset;
+ dateString += strlen(known_zones[i].tzName);
+ haveTZ = true;
+ break;
+ }
+ }
+ }
+ }
+
+ skipSpacesAndComments(dateString);
+
+ if (*dateString && year == -1) {
+ if (!parseLong(dateString, &newPosStr, 10, &year))
+ return NaN;
+ dateString = newPosStr;
+ }
+
+ skipSpacesAndComments(dateString);
+
+ // Trailing garbage
+ if (*dateString)
+ return NaN;
+
+ // Y2K: Handle 2 digit years.
+ if (year >= 0 && year < 100) {
+ if (year < 50)
+ year += 2000;
+ else
+ year += 1900;
+ }
+
+ // fall back to local timezone
+ if (!haveTZ) {
+ GregorianDateTime t;
+ t.monthDay = day;
+ t.month = month;
+ t.year = year - 1900;
+ t.isDST = -1;
+ t.second = second;
+ t.minute = minute;
+ t.hour = hour;
+
+ // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
+ return gregorianDateTimeToMS(t, 0, false);
+ }
+
+ return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
+}
+
+double timeClip(double t)
+{
+ if (!isfinite(t))
+ return NaN;
+ if (fabs(t) > 8.64E15)
+ return NaN;
+ return trunc(t);
+}
+
+UString formatDate(const GregorianDateTime &t)
+{
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
+ weekdayName[(t.weekDay + 6) % 7],
+ monthName[t.month], t.monthDay, t.year + 1900);
+ return buffer;
+}
+
+UString formatDateUTCVariant(const GregorianDateTime &t)
+{
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
+ weekdayName[(t.weekDay + 6) % 7],
+ t.monthDay, monthName[t.month], t.year + 1900);
+ return buffer;
+}
+
+UString formatTime(const GregorianDateTime &t, bool utc)
+{
+ char buffer[100];
+ if (utc) {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
+ } else {
+ int offset = abs(gmtoffset(t));
+ char tzname[70];
+ struct tm gtm = t;
+ strftime(tzname, sizeof(tzname), "%Z", >m);
+
+ if (tzname[0]) {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
+ t.hour, t.minute, t.second,
+ gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
+ t.hour, t.minute, t.second,
+ gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
+ }
+ }
+ return UString(buffer);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ */
+
+#ifndef DateMath_h
+#define DateMath_h
+
+#include <time.h>
+#include <string.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+class UString;
+struct GregorianDateTime;
+
+void initDateMath();
+void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
+double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
+double getUTCOffset();
+int equivalentYearForDST(int year);
+double getCurrentUTCTime();
+double getCurrentUTCTimeWithMicroseconds();
+void getLocalTime(const time_t*, tm*);
+
+// Not really math related, but this is currently the only shared place to put these.
+double parseDate(const UString&);
+double timeClip(double);
+UString formatDate(const GregorianDateTime&);
+UString formatDateUTCVariant(const GregorianDateTime&);
+UString formatTime(const GregorianDateTime&, bool inputIsUTC);
+
+
+const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+const double hoursPerDay = 24.0;
+const double minutesPerHour = 60.0;
+const double secondsPerHour = 60.0 * 60.0;
+const double secondsPerMinute = 60.0;
+const double msPerSecond = 1000.0;
+const double msPerMinute = 60.0 * 1000.0;
+const double msPerHour = 60.0 * 60.0 * 1000.0;
+const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
+
+// Intentionally overridding the default tm of the system
+// Tee members of tm differ on various operating systems.
+struct GregorianDateTime : Noncopyable {
+ GregorianDateTime()
+ : second(0)
+ , minute(0)
+ , hour(0)
+ , weekDay(0)
+ , monthDay(0)
+ , yearDay(0)
+ , month(0)
+ , year(0)
+ , isDST(0)
+ , utcOffset(0)
+ , timeZone(0)
+ {
+ }
+
+ ~GregorianDateTime()
+ {
+ delete [] timeZone;
+ }
+
+ GregorianDateTime(const tm& inTm)
+ : second(inTm.tm_sec)
+ , minute(inTm.tm_min)
+ , hour(inTm.tm_hour)
+ , weekDay(inTm.tm_wday)
+ , monthDay(inTm.tm_mday)
+ , yearDay(inTm.tm_yday)
+ , month(inTm.tm_mon)
+ , year(inTm.tm_year)
+ , isDST(inTm.tm_isdst)
+ {
+#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT)
+ utcOffset = static_cast<int>(inTm.tm_gmtoff);
+
+ int inZoneSize = strlen(inTm.tm_zone) + 1;
+ timeZone = new char[inZoneSize];
+ strncpy(timeZone, inTm.tm_zone, inZoneSize);
+#else
+ utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0));
+ timeZone = 0;
+#endif
+ }
+
+ operator tm() const
+ {
+ tm ret;
+ memset(&ret, 0, sizeof(ret));
+
+ ret.tm_sec = second;
+ ret.tm_min = minute;
+ ret.tm_hour = hour;
+ ret.tm_wday = weekDay;
+ ret.tm_mday = monthDay;
+ ret.tm_yday = yearDay;
+ ret.tm_mon = month;
+ ret.tm_year = year;
+ ret.tm_isdst = isDST;
+
+#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT)
+ ret.tm_gmtoff = static_cast<long>(utcOffset);
+ ret.tm_zone = timeZone;
+#endif
+
+ return ret;
+ }
+
+ void copyFrom(const GregorianDateTime& rhs)
+ {
+ second = rhs.second;
+ minute = rhs.minute;
+ hour = rhs.hour;
+ weekDay = rhs.weekDay;
+ monthDay = rhs.monthDay;
+ yearDay = rhs.yearDay;
+ month = rhs.month;
+ year = rhs.year;
+ isDST = rhs.isDST;
+ utcOffset = rhs.utcOffset;
+ if (rhs.timeZone) {
+ int inZoneSize = strlen(rhs.timeZone) + 1;
+ timeZone = new char[inZoneSize];
+ strncpy(timeZone, rhs.timeZone, inZoneSize);
+ } else
+ timeZone = 0;
+ }
+
+ int second;
+ int minute;
+ int hour;
+ int weekDay;
+ int monthDay;
+ int yearDay;
+ int month;
+ int year;
+ int isDST;
+ int utcOffset;
+ char* timeZone;
+};
+
+static inline int gmtoffset(const GregorianDateTime& t)
+{
+ return t.utcOffset;
+}
+
+} // namespace JSC
+
+#endif // DateMath_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DatePrototype.h"
+
+#include "DateMath.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "DateInstance.h"
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <time.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/UnusedParam.h>
+
+#if HAVE(SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+#include <CoreFoundation/CoreFoundation.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
+
+static JSValuePtr dateProtoFuncGetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetDay(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncGetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetTime(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncSetYear(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToGMTString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToTimeString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr dateProtoFuncToUTCString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+}
+
+#include "DatePrototype.lut.h"
+
+namespace JSC {
+
+enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
+
+
+// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
+// Instead we should consider using this whenever PLATFORM(CF) is true.
+
+static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
+{
+ if (string == "short")
+ return kCFDateFormatterShortStyle;
+ if (string == "medium")
+ return kCFDateFormatterMediumStyle;
+ if (string == "long")
+ return kCFDateFormatterLongStyle;
+ if (string == "full")
+ return kCFDateFormatterFullStyle;
+ return defaultStyle;
+}
+
+static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args)
+{
+ CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+ CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+
+ bool useCustomFormat = false;
+ UString customFormatString;
+
+ UString arg0String = args.at(exec, 0).toString(exec);
+ if (arg0String == "custom" && !args.at(exec, 1).isUndefined()) {
+ useCustomFormat = true;
+ customFormatString = args.at(exec, 1).toString(exec);
+ } else if (format == LocaleDateAndTime && !args.at(exec, 1).isUndefined()) {
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ timeStyle = styleFromArgString(args.at(exec, 1).toString(exec), timeStyle);
+ } else if (format != LocaleTime && !args.at(exec, 0).isUndefined())
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ else if (format != LocaleDate && !args.at(exec, 0).isUndefined())
+ timeStyle = styleFromArgString(arg0String, timeStyle);
+
+ CFLocaleRef locale = CFLocaleCopyCurrent();
+ CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
+ CFRelease(locale);
+
+ if (useCustomFormat) {
+ CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size());
+ CFDateFormatterSetFormat(formatter, customFormatCFString);
+ CFRelease(customFormatCFString);
+ }
+
+ CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970);
+
+ CFRelease(formatter);
+
+ // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
+ // That's not great error handling, but it just won't happen so it doesn't matter.
+ UChar buffer[200];
+ const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
+ size_t length = CFStringGetLength(string);
+ ASSERT(length <= bufferLength);
+ if (length > bufferLength)
+ length = bufferLength;
+ CFStringGetCharacters(string, CFRangeMake(0, length), buffer);
+
+ CFRelease(string);
+
+ return jsNontrivialString(exec, UString(buffer, length));
+}
+
+
+// Converts a list of arguments sent to a Date member function into milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([hour,] [min,] [sec,] [ms])
+static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
+{
+ double milliseconds = 0;
+ bool ok = true;
+ int idx = 0;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // hours
+ if (maxArgs >= 4 && idx < numArgs) {
+ t->hour = 0;
+ milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerHour;
+ }
+
+ // minutes
+ if (maxArgs >= 3 && idx < numArgs && ok) {
+ t->minute = 0;
+ milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerMinute;
+ }
+
+ // seconds
+ if (maxArgs >= 2 && idx < numArgs && ok) {
+ t->second = 0;
+ milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerSecond;
+ }
+
+ if (!ok)
+ return false;
+
+ // milliseconds
+ if (idx < numArgs) {
+ double millis = args.at(exec, idx).toNumber(exec);
+ ok = isfinite(millis);
+ milliseconds += millis;
+ } else
+ milliseconds += *ms;
+
+ *ms = milliseconds;
+ return ok;
+}
+
+// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([years,] [months,] [days])
+static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
+{
+ int idx = 0;
+ bool ok = true;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // years
+ if (maxArgs >= 3 && idx < numArgs)
+ t->year = args.at(exec, idx++).toInt32(exec, ok) - 1900;
+
+ // months
+ if (maxArgs >= 2 && idx < numArgs && ok)
+ t->month = args.at(exec, idx++).toInt32(exec, ok);
+
+ // days
+ if (idx < numArgs && ok) {
+ t->monthDay = 0;
+ *ms += args.at(exec, idx).toInt32(exec, ok) * msPerDay;
+ }
+
+ return ok;
+}
+
+const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
+
+/* Source for DatePrototype.lut.h
+@begin dateTable
+ toString dateProtoFuncToString DontEnum|Function 0
+ toUTCString dateProtoFuncToUTCString DontEnum|Function 0
+ toDateString dateProtoFuncToDateString DontEnum|Function 0
+ toTimeString dateProtoFuncToTimeString DontEnum|Function 0
+ toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
+ toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
+ toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
+ valueOf dateProtoFuncGetTime DontEnum|Function 0
+ getTime dateProtoFuncGetTime DontEnum|Function 0
+ getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
+ getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
+ toGMTString dateProtoFuncToGMTString DontEnum|Function 0
+ getMonth dateProtoFuncGetMonth DontEnum|Function 0
+ getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
+ getDate dateProtoFuncGetDate DontEnum|Function 0
+ getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
+ getDay dateProtoFuncGetDay DontEnum|Function 0
+ getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
+ getHours dateProtoFuncGetHours DontEnum|Function 0
+ getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
+ getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
+ getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
+ getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
+ getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
+ getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
+ getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
+ getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
+ setTime dateProtoFuncSetTime DontEnum|Function 1
+ setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
+ setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
+ setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
+ setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
+ setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
+ setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
+ setHours dateProtoFuncSetHours DontEnum|Function 4
+ setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
+ setDate dateProtoFuncSetDate DontEnum|Function 1
+ setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
+ setMonth dateProtoFuncSetMonth DontEnum|Function 2
+ setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
+ setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
+ setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
+ setYear dateProtoFuncSetYear DontEnum|Function 1
+ getYear dateProtoFuncGetYear DontEnum|Function 0
+@end
+*/
+
+// ECMA 15.9.4
+
+DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure)
+ : DateInstance(structure)
+{
+ setInternalValue(jsNaN(exec));
+ // The constructor will be added later, after DateConstructor has been built.
+}
+
+bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
+}
+
+// Functions
+
+JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
+}
+
+JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t));
+}
+
+JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatTime(t, utc));
+}
+
+JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
+}
+
+JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
+}
+
+JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
+}
+
+JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ return jsNumber(exec, milli);
+}
+
+JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
+}
+
+JSValuePtr dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+
+ double milli = timeClip(args.at(exec, 0).toNumber(exec));
+ JSValuePtr result = jsNumber(exec, milli);
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+
+ if (args.isEmpty() || isnan(milli)) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+
+ if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValuePtr setNewValueFromDateArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (numArgsToUse == 3 && isnan(milli))
+ // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+ }
+
+ if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValuePtr dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValuePtr dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (isnan(milli))
+ // Based on ECMA 262 B.2.5 (setYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ }
+
+ bool ok = true;
+ int32_t year = args.at(exec, 0).toInt32(exec, ok);
+ if (!ok) {
+ JSValuePtr result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ t.year = (year > 99 || year < 0) ? year - 1900 : year;
+ JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValuePtr dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+
+ // NOTE: IE returns the full year even in getYear.
+ return jsNumber(exec, t.year);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DatePrototype_h
+#define DatePrototype_h
+
+#include "DateInstance.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class DatePrototype : public DateInstance {
+ public:
+ DatePrototype(ExecState*, PassRefPtr<Structure>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+ };
+
+} // namespace JSC
+
+#endif // DatePrototype_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Error.h"
+
+#include "ConstructData.h"
+#include "ErrorConstructor.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "NativeErrorConstructor.h"
+
+namespace JSC {
+
+const char* expressionBeginOffsetPropertyName = "expressionBeginOffset";
+const char* expressionCaretOffsetPropertyName = "expressionCaretOffset";
+const char* expressionEndOffsetPropertyName = "expressionEndOffset";
+
+JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL)
+{
+ JSObject* constructor;
+ const char* name;
+ switch (type) {
+ case EvalError:
+ constructor = exec->lexicalGlobalObject()->evalErrorConstructor();
+ name = "Evaluation error";
+ break;
+ case RangeError:
+ constructor = exec->lexicalGlobalObject()->rangeErrorConstructor();
+ name = "Range error";
+ break;
+ case ReferenceError:
+ constructor = exec->lexicalGlobalObject()->referenceErrorConstructor();
+ name = "Reference error";
+ break;
+ case SyntaxError:
+ constructor = exec->lexicalGlobalObject()->syntaxErrorConstructor();
+ name = "Syntax error";
+ break;
+ case TypeError:
+ constructor = exec->lexicalGlobalObject()->typeErrorConstructor();
+ name = "Type error";
+ break;
+ case URIError:
+ constructor = exec->lexicalGlobalObject()->URIErrorConstructor();
+ name = "URI error";
+ break;
+ default:
+ constructor = exec->lexicalGlobalObject()->errorConstructor();
+ name = "Error";
+ break;
+ }
+
+ ArgList args;
+ if (message.isEmpty())
+ args.append(jsString(exec, name));
+ else
+ args.append(jsString(exec, message));
+ ConstructData constructData;
+ ConstructType constructType = constructor->getConstructData(constructData);
+ JSObject* error = construct(exec, constructor, constructType, constructData, args);
+
+ if (lineNumber != -1)
+ error->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, lineNumber), ReadOnly | DontDelete);
+ if (sourceID != -1)
+ error->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, sourceID), ReadOnly | DontDelete);
+ if (!sourceURL.isNull())
+ error->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsString(exec, sourceURL), ReadOnly | DontDelete);
+
+ return error;
+}
+
+JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
+{
+ return create(exec, type, message, -1, -1, NULL);
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type)
+{
+ JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const UString& message)
+{
+ JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const char* message)
+{
+ JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const UString& message, int line, intptr_t sourceID, const UString& sourceURL)
+{
+ JSObject* error = Error::create(exec, type, message, line, sourceID, sourceURL);
+ exec->setException(error);
+ return error;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Error_h
+#define Error_h
+
+#include <stdint.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSObject;
+ class UString;
+
+ /**
+ * Types of Native Errors available. For custom errors, GeneralError
+ * should be used.
+ */
+ enum ErrorType {
+ GeneralError = 0,
+ EvalError = 1,
+ RangeError = 2,
+ ReferenceError = 3,
+ SyntaxError = 4,
+ TypeError = 5,
+ URIError = 6
+ };
+
+ extern const char* expressionBeginOffsetPropertyName;
+ extern const char* expressionCaretOffsetPropertyName;
+ extern const char* expressionEndOffsetPropertyName;
+
+ class Error {
+ public:
+ static JSObject* create(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
+ static JSObject* create(ExecState*, ErrorType, const char* message);
+ };
+
+ JSObject* throwError(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
+ JSObject* throwError(ExecState*, ErrorType, const UString& message);
+ JSObject* throwError(ExecState*, ErrorType, const char* message);
+ JSObject* throwError(ExecState*, ErrorType);
+
+} // namespace JSC
+
+#endif // Error_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorConstructor.h"
+
+#include "ErrorPrototype.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
+
+ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
+{
+ // ECMA 15.11.3.1 Error.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum);
+}
+
+// ECMA 15.9.3
+ErrorInstance* constructError(ExecState* exec, const ArgList& args)
+{
+ ErrorInstance* obj = new (exec) ErrorInstance(exec->lexicalGlobalObject()->errorStructure());
+ if (!args.at(exec, 0).isUndefined())
+ obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0).toString(exec)));
+ return obj;
+}
+
+static JSObject* constructWithErrorConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructError(exec, args);
+}
+
+ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithErrorConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.9.2
+static JSValuePtr callErrorConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ // "Error()" gives the sames result as "new Error()"
+ return constructError(exec, args);
+}
+
+CallType ErrorConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callErrorConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorConstructor_h
+#define ErrorConstructor_h
+
+#include "ErrorInstance.h"
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ErrorPrototype;
+
+ class ErrorConstructor : public InternalFunction {
+ public:
+ ErrorConstructor(ExecState*, PassRefPtr<Structure>, ErrorPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ ErrorInstance* constructError(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // ErrorConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorInstance.h"
+
+namespace JSC {
+
+const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
+
+ErrorInstance::ErrorInstance(PassRefPtr<Structure> structure)
+ : JSObject(structure)
+{
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorInstance_h
+#define ErrorInstance_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class ErrorInstance : public JSObject {
+ public:
+ explicit ErrorInstance(PassRefPtr<Structure>);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // ErrorInstance_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorPrototype.h"
+
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include "UString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
+
+static JSValuePtr errorProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+// ECMA 15.9.4
+ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ : ErrorInstance(structure)
+{
+ // The constructor will be added later in ErrorConstructor's constructor
+
+ putDirectWithoutTransition(exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
+ putDirectWithoutTransition(exec->propertyNames().message, jsNontrivialString(exec, "Unknown error"), DontEnum);
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
+}
+
+JSValuePtr errorProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ UString s = "Error";
+
+ JSValuePtr v = thisObj->get(exec, exec->propertyNames().name);
+ if (!v.isUndefined())
+ s = v.toString(exec);
+
+ v = thisObj->get(exec, exec->propertyNames().message);
+ if (!v.isUndefined()) {
+ // Mozilla-compatible format.
+ s += ": ";
+ s += v.toString(exec);
+ }
+
+ return jsNontrivialString(exec, s);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorPrototype_h
+#define ErrorPrototype_h
+
+#include "ErrorInstance.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class ErrorPrototype : public ErrorInstance {
+ public:
+ ErrorPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // ErrorPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ExceptionHelpers.h"
+
+#include "CodeBlock.h"
+#include "CallFrame.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSObject.h"
+#include "JSNotAnObject.h"
+#include "Interpreter.h"
+#include "Nodes.h"
+
+namespace JSC {
+
+class InterruptedExecutionError : public JSObject {
+public:
+ InterruptedExecutionError(JSGlobalData* globalData)
+ : JSObject(globalData->interruptedExecutionErrorStructure)
+ {
+ }
+
+ virtual bool isWatchdogException() const { return true; }
+
+ virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
+};
+
+JSValuePtr createInterruptedExecutionException(JSGlobalData* globalData)
+{
+ return new (globalData) InterruptedExecutionError(globalData);
+}
+
+static JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg)
+{
+ return Error::create(exec, e, msg, -1, -1, 0);
+}
+
+JSValuePtr createStackOverflowError(ExecState* exec)
+{
+ return createError(exec, RangeError, "Maximum call stack size exceeded.");
+}
+
+JSValuePtr createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
+{
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
+ UString message = "Can't find variable: ";
+ message.append(ident.ustring());
+ JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+ return exception;
+}
+
+static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValuePtr value, UString error)
+{
+ if (!expressionStop || expressionStart > codeBlock->source()->length()) {
+ UString errorText = value.toString(exec);
+ errorText.append(" is ");
+ errorText.append(error);
+ return errorText;
+ }
+
+ UString errorText = "Result of expression ";
+
+ if (expressionStart < expressionStop) {
+ errorText.append('\'');
+ errorText.append(codeBlock->source()->getRange(expressionStart, expressionStop));
+ errorText.append("' [");
+ errorText.append(value.toString(exec));
+ errorText.append("] is ");
+ } else {
+ // No range information, so give a few characters of context
+ const UChar* data = codeBlock->source()->data();
+ int dataLength = codeBlock->source()->length();
+ int start = expressionStart;
+ int stop = expressionStart;
+ // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
+ // then strip whitespace.
+ while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
+ start--;
+ while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
+ start++;
+ while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
+ stop++;
+ while (stop > expressionStart && isStrWhiteSpace(data[stop]))
+ stop--;
+ errorText.append("near '...");
+ errorText.append(codeBlock->source()->getRange(start, stop));
+ errorText.append("...' [");
+ errorText.append(value.toString(exec));
+ errorText.append("] is ");
+ }
+ errorText.append(error);
+ errorText.append(".");
+ return errorText;
+}
+
+JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+{
+ UString message = "not a valid argument for '";
+ message.append(op);
+ message.append("'");
+
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
+ UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message);
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+ return exception;
+}
+
+JSObject* createNotAConstructorError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+{
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
+
+ // We're in a "new" expression, so we need to skip over the "new.." part
+ int startPoint = divotPoint - (startOffset ? startOffset - 4 : 0); // -4 for "new "
+ const UChar* data = codeBlock->source()->data();
+ while (startPoint < divotPoint && isStrWhiteSpace(data[startPoint]))
+ startPoint++;
+
+ UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor");
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+ return exception;
+}
+
+JSValuePtr createNotAFunctionError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+{
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
+ UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function");
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+ return exception;
+}
+
+JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull)
+{
+ return new (exec) JSNotAnObjectErrorStub(exec, isNull);
+}
+
+JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, unsigned bytecodeOffset, CodeBlock* codeBlock)
+{
+ // Both op_construct and op_instanceof require a use of op_get_by_id to get
+ // the prototype property from an object. The exception messages for exceptions
+ // thrown by these instances op_get_by_id need to reflect this.
+ OpcodeID followingOpcodeID;
+ if (codeBlock->getByIdExceptionInfoForBytecodeOffset(exec, bytecodeOffset, followingOpcodeID)) {
+ ASSERT(followingOpcodeID == op_construct || followingOpcodeID == op_instanceof);
+ if (followingOpcodeID == op_construct)
+ return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock);
+ return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock);
+ }
+
+ int startOffset = 0;
+ int endOffset = 0;
+ int divotPoint = 0;
+ int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
+ UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object");
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
+ exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+ return exception;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ExceptionHelpers_h
+#define ExceptionHelpers_h
+
+#include "JSImmediate.h"
+
+namespace JSC {
+
+ class CodeBlock;
+ class ExecState;
+ class Identifier;
+ class Instruction;
+ class JSGlobalData;
+ class JSNotAnObjectErrorStub;
+ class JSObject;
+ class JSValuePtr;
+ class Node;
+
+ JSValuePtr createInterruptedExecutionException(JSGlobalData*);
+ JSValuePtr createStackOverflowError(ExecState*);
+ JSValuePtr createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
+ JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
+ JSObject* createInvalidParamError(ExecState*, const char* op, JSValuePtr, unsigned bytecodeOffset, CodeBlock*);
+ JSObject* createNotAConstructorError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*);
+ JSValuePtr createNotAFunctionError(ExecState*, JSValuePtr, unsigned bytecodeOffset, CodeBlock*);
+ JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
+
+} // namespace JSC
+
+#endif // ExceptionHelpers_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "FunctionConstructor.h"
+
+#include "FunctionPrototype.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "Parser.h"
+#include "Debugger.h"
+#include "Lexer.h"
+#include "Nodes.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
+
+FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // Number of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+}
+
+static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructFunction(exec, args);
+}
+
+ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithFunctionConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValuePtr callFunctionConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return constructFunction(exec, args);
+}
+
+// ECMA 15.3.1 The Function Constructor Called as a Function
+CallType FunctionConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callFunctionConstructor;
+ return CallTypeHost;
+}
+
+FunctionBodyNode* extractFunctionBody(ProgramNode* program)
+{
+ if (!program)
+ return 0;
+
+ StatementVector& children = program->children();
+ if (children.size() != 1)
+ return 0;
+
+ ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(children[0].get());
+ ASSERT(exprStatement->isExprStatement());
+ if (!exprStatement || !exprStatement->isExprStatement())
+ return 0;
+
+ FuncExprNode* funcExpr = static_cast<FuncExprNode*>(exprStatement->expr());
+ ASSERT(funcExpr->isFuncExprNode());
+ if (!funcExpr || !funcExpr->isFuncExprNode())
+ return 0;
+
+ FunctionBodyNode* body = funcExpr->body();
+ ASSERT(body);
+ return body;
+}
+
+// ECMA 15.3.2 The Function Constructor
+JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+{
+ // Functions need to have a space following the opening { due to for web compatibility
+ // see https://bugs.webkit.org/show_bug.cgi?id=24350
+ // We also need \n before the closing } to handle // comments at the end of the last line
+ UString program;
+ if (args.isEmpty())
+ program = "(function() { \n})";
+ else if (args.size() == 1)
+ program = "(function() { " + args.at(exec, 0).toString(exec) + "\n})";
+ else {
+ program = "(function(" + args.at(exec, 0).toString(exec);
+ for (size_t i = 1; i < args.size() - 1; i++)
+ program += "," + args.at(exec, i).toString(exec);
+ program += ") { " + args.at(exec, args.size() - 1).toString(exec) + "\n})";
+ }
+
+ int errLine;
+ UString errMsg;
+ SourceCode source = makeSource(program, sourceURL, lineNumber);
+ RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+ FunctionBodyNode* body = extractFunctionBody(programNode.get());
+ if (!body)
+ return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
+ return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
+}
+
+// ECMA 15.3.2 The Function Constructor
+JSObject* constructFunction(ExecState* exec, const ArgList& args)
+{
+ return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef FunctionConstructor_h
+#define FunctionConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class FunctionPrototype;
+ class ProgramNode;
+ class FunctionBodyNode;
+
+ class FunctionConstructor : public InternalFunction {
+ public:
+ FunctionConstructor(ExecState*, PassRefPtr<Structure>, FunctionPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+ JSObject* constructFunction(ExecState*, const ArgList&);
+
+ FunctionBodyNode* extractFunctionBody(ProgramNode*);
+
+} // namespace JSC
+
+#endif // FunctionConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "FunctionPrototype.h"
+
+#include "Arguments.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "Interpreter.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
+
+static JSValuePtr functionProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionProtoFuncApply(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr functionProtoFuncCall(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+ : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
+{
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+}
+
+void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum);
+}
+
+static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&)
+{
+ return jsUndefined();
+}
+
+// ECMA 15.3.4
+CallType FunctionPrototype::getCallData(CallData& callData)
+{
+ callData.native.function = callFunctionPrototype;
+ return CallTypeHost;
+}
+
+// Functions
+
+JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (thisValue.isObject(&JSFunction::info)) {
+ JSFunction* function = asFunction(thisValue);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + function->body()->toSourceString());
+ }
+
+ if (thisValue.isObject(&InternalFunction::info)) {
+ InternalFunction* function = asInternalFunction(thisValue);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}");
+ }
+
+ return throwError(exec, TypeError);
+}
+
+JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ CallData callData;
+ CallType callType = thisValue.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSValuePtr thisArg = args.at(exec, 0);
+ JSValuePtr argArray = args.at(exec, 1);
+
+ JSValuePtr applyThis;
+ if (thisArg.isUndefinedOrNull())
+ applyThis = exec->globalThisValue();
+ else
+ applyThis = thisArg.toObject(exec);
+
+ ArgList applyArgs;
+ if (!argArray.isUndefinedOrNull()) {
+ if (!argArray.isObject())
+ return throwError(exec, TypeError);
+ if (asObject(argArray)->classInfo() == &Arguments::info)
+ asArguments(argArray)->fillArgList(exec, applyArgs);
+ else if (exec->interpreter()->isJSArray(argArray))
+ asArray(argArray)->fillArgList(exec, applyArgs);
+ else if (asObject(argArray)->inherits(&JSArray::info)) {
+ unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned i = 0; i < length; ++i)
+ applyArgs.append(asArray(argArray)->get(exec, i));
+ } else
+ return throwError(exec, TypeError);
+ }
+
+ return call(exec, thisValue, callType, callData, applyThis, applyArgs);
+}
+
+JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ CallData callData;
+ CallType callType = thisValue.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSValuePtr thisArg = args.at(exec, 0);
+
+ JSObject* callThis;
+ if (thisArg.isUndefinedOrNull())
+ callThis = exec->globalThisValue();
+ else
+ callThis = thisArg.toObject(exec);
+
+ ArgList argsTail;
+ args.getSlice(1, argsTail);
+ return call(exec, thisValue, callType, callData, callThis, argsTail);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef FunctionPrototype_h
+#define FunctionPrototype_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class FunctionPrototype : public InternalFunction {
+ public:
+ FunctionPrototype(ExecState*, PassRefPtr<Structure>);
+ void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ }
+
+ private:
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // FunctionPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "GetterSetter.h"
+
+#include "JSObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+void GetterSetter::mark()
+{
+ JSCell::mark();
+
+ if (m_getter && !m_getter->marked())
+ m_getter->mark();
+ if (m_setter && !m_setter->marked())
+ m_setter->mark();
+}
+
+JSValuePtr GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return jsNull();
+}
+
+bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+{
+ ASSERT_NOT_REACHED();
+ number = 0;
+ value = noValue();
+ return true;
+}
+
+bool GetterSetter::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double GetterSetter::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0.0;
+}
+
+UString GetterSetter::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return UString::null();
+}
+
+JSObject* GetterSetter::toObject(ExecState* exec) const
+{
+ ASSERT_NOT_REACHED();
+ return jsNull().toObject(exec);
+}
+
+bool GetterSetter::isGetterSetter() const
+{
+ return true;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GetterSetter_h
+#define GetterSetter_h
+
+#include "JSCell.h"
+
+namespace JSC {
+
+ class JSObject;
+
+ // This is an internal value object which stores getter and setter functions
+ // for a property.
+ class GetterSetter : public JSCell {
+ public:
+ GetterSetter()
+ : JSCell(0)
+ , m_getter(0)
+ , m_setter(0)
+ {
+ }
+
+ virtual void mark();
+
+ JSObject* getter() const { return m_getter; }
+ void setGetter(JSObject* getter) { m_getter = getter; }
+ JSObject* setter() const { return m_setter; }
+ void setSetter(JSObject* setter) { m_setter = setter; }
+
+ private:
+ virtual bool isGetterSetter() const;
+
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ JSObject* m_getter;
+ JSObject* m_setter;
+ };
+
+ GetterSetter* asGetterSetter(JSValuePtr);
+
+ inline GetterSetter* asGetterSetter(JSValuePtr value)
+ {
+ ASSERT(asCell(value)->isGetterSetter());
+ return static_cast<GetterSetter*>(asCell(value));
+ }
+
+
+} // namespace JSC
+
+#endif // GetterSetter_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "GlobalEvalFunction.h"
+
+#include "JSGlobalObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
+
+GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
+ : PrototypeFunction(exec, structure, len, name, function)
+ , m_cachedGlobalObject(cachedGlobalObject)
+{
+ ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
+}
+
+void GlobalEvalFunction::mark()
+{
+ PrototypeFunction::mark();
+ if (!m_cachedGlobalObject->marked())
+ m_cachedGlobalObject->mark();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GlobalEvalFunction_h
+#define GlobalEvalFunction_h
+
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ class JSGlobalObject;
+
+ class GlobalEvalFunction : public PrototypeFunction {
+ public:
+ GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
+ JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
+
+ private:
+ virtual void mark();
+
+ JSGlobalObject* m_cachedGlobalObject;
+ };
+
+} // namespace JSC
+
+#endif // GlobalEvalFunction_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Identifier.h"
+
+#include "CallFrame.h"
+#include <new> // for placement new
+#include <string.h> // for strlen
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
+
+class IdentifierTable {
+public:
+ ~IdentifierTable()
+ {
+ HashSet<UString::Rep*>::iterator end = m_table.end();
+ for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
+ (*iter)->setIdentifierTable(0);
+ }
+
+ std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
+ {
+ std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
+ (*result.first)->setIdentifierTable(this);
+ return result;
+ }
+
+ template<typename U, typename V>
+ std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
+ {
+ std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
+ (*result.first)->setIdentifierTable(this);
+ return result;
+ }
+
+ void remove(UString::Rep* r) { m_table.remove(r); }
+
+ LiteralIdentifierTable& literalTable() { return m_literalTable; }
+
+private:
+ HashSet<UString::Rep*> m_table;
+ LiteralIdentifierTable m_literalTable;
+};
+
+IdentifierTable* createIdentifierTable()
+{
+ return new IdentifierTable;
+}
+
+void deleteIdentifierTable(IdentifierTable* table)
+{
+ delete table;
+}
+
+bool Identifier::equal(const UString::Rep* r, const char* s)
+{
+ int length = r->len;
+ const UChar* d = r->data();
+ for (int i = 0; i != length; ++i)
+ if (d[i] != (unsigned char)s[i])
+ return false;
+ return s[length] == 0;
+}
+
+bool Identifier::equal(const UString::Rep* r, const UChar* s, int length)
+{
+ if (r->len != length)
+ return false;
+ const UChar* d = r->data();
+ for (int i = 0; i != length; ++i)
+ if (d[i] != s[i])
+ return false;
+ return true;
+}
+
+struct CStringTranslator {
+ static unsigned hash(const char* c)
+ {
+ return UString::Rep::computeHash(c);
+ }
+
+ static bool equal(UString::Rep* r, const char* s)
+ {
+ return Identifier::equal(r, s);
+ }
+
+ static void translate(UString::Rep*& location, const char* c, unsigned hash)
+ {
+ size_t length = strlen(c);
+ UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * length));
+ for (size_t i = 0; i != length; i++)
+ d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+
+ UString::Rep* r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
+ r->_hash = hash;
+
+ location = r;
+ }
+};
+
+PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
+{
+ if (!c) {
+ UString::Rep::null().hash();
+ return &UString::Rep::null();
+ }
+ if (!c[0]) {
+ UString::Rep::empty().hash();
+ return &UString::Rep::empty();
+ }
+ if (!c[1])
+ return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
+
+ IdentifierTable& identifierTable = *globalData->identifierTable;
+ LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
+
+ const LiteralIdentifierTable::iterator& iter = literalIdentifierTable.find(c);
+ if (iter != literalIdentifierTable.end())
+ return iter->second;
+
+ pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, CStringTranslator>(c);
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ RefPtr<UString::Rep> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+
+ literalIdentifierTable.add(c, addedString.get());
+
+ return addedString.release();
+}
+
+PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c)
+{
+ return add(&exec->globalData(), c);
+}
+
+struct UCharBuffer {
+ const UChar* s;
+ unsigned int length;
+};
+
+struct UCharBufferTranslator {
+ static unsigned hash(const UCharBuffer& buf)
+ {
+ return UString::Rep::computeHash(buf.s, buf.length);
+ }
+
+ static bool equal(UString::Rep* str, const UCharBuffer& buf)
+ {
+ return Identifier::equal(str, buf.s, buf.length);
+ }
+
+ static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
+ {
+ UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * buf.length));
+ for (unsigned i = 0; i != buf.length; i++)
+ d[i] = buf.s[i];
+
+ UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef();
+ r->_hash = hash;
+
+ location = r;
+ }
+};
+
+PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
+{
+ if (length == 1) {
+ UChar c = s[0];
+ if (c <= 0xFF)
+ return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+ }
+ if (!length) {
+ UString::Rep::empty().hash();
+ return &UString::Rep::empty();
+ }
+ UCharBuffer buf = {s, length};
+ pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf);
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+}
+
+PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length)
+{
+ return add(&exec->globalData(), s, length);
+}
+
+PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
+{
+ ASSERT(!r->identifierTable());
+ if (r->len == 1) {
+ UChar c = r->data()[0];
+ if (c <= 0xFF)
+ r = globalData->smallStrings.singleCharacterStringRep(c);
+ if (r->identifierTable()) {
+#ifndef NDEBUG
+ checkSameIdentifierTable(globalData, r);
+#endif
+ return r;
+ }
+ }
+ if (!r->len) {
+ UString::Rep::empty().hash();
+ return &UString::Rep::empty();
+ }
+ return *globalData->identifierTable->add(r).first;
+}
+
+PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r)
+{
+ return addSlowCase(&exec->globalData(), r);
+}
+
+void Identifier::remove(UString::Rep* r)
+{
+ r->identifierTable()->remove(r);
+}
+
+#ifndef NDEBUG
+
+void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep)
+{
+ ASSERT(rep->identifierTable() == exec->globalData().identifierTable);
+}
+
+void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep)
+{
+ ASSERT(rep->identifierTable() == globalData->identifierTable);
+}
+
+#else
+
+void Identifier::checkSameIdentifierTable(ExecState*, UString::Rep*)
+{
+}
+
+void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*)
+{
+}
+
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2003, 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Identifier_h
+#define Identifier_h
+
+#include "JSGlobalData.h"
+#include "UString.h"
+
+namespace JSC {
+
+ class ExecState;
+
+ class Identifier {
+ friend class Structure;
+ public:
+ Identifier() { }
+
+ Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals.
+ Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { }
+ Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { }
+ Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { }
+
+ Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals.
+ Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { }
+ Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { }
+ Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { }
+
+ // Special constructor for cases where we overwrite an object in place.
+ Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { }
+
+ const UString& ustring() const { return _ustring; }
+
+ const UChar* data() const { return _ustring.data(); }
+ int size() const { return _ustring.size(); }
+
+ const char* ascii() const { return _ustring.ascii(); }
+
+ static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
+
+ bool isNull() const { return _ustring.isNull(); }
+ bool isEmpty() const { return _ustring.isEmpty(); }
+
+ uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); }
+ uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); };
+ uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); }
+ unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); }
+ double toDouble() const { return _ustring.toDouble(); }
+
+ friend bool operator==(const Identifier&, const Identifier&);
+ friend bool operator!=(const Identifier&, const Identifier&);
+
+ friend bool operator==(const Identifier&, const char*);
+ friend bool operator!=(const Identifier&, const char*);
+
+ static void remove(UString::Rep*);
+
+ static bool equal(const UString::Rep*, const char*);
+ static bool equal(const UString::Rep*, const UChar*, int length);
+ static bool equal(const UString::Rep* a, const UString::Rep* b) { return JSC::equal(a, b); }
+
+ static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals.
+ static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals.
+
+ private:
+ UString _ustring;
+
+ static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); }
+ static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); }
+
+ static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length);
+ static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length);
+
+ static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
+ {
+ if (r->identifierTable()) {
+#ifndef NDEBUG
+ checkSameIdentifierTable(exec, r);
+#endif
+ return r;
+ }
+ return addSlowCase(exec, r);
+ }
+ static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
+ {
+ if (r->identifierTable()) {
+#ifndef NDEBUG
+ checkSameIdentifierTable(globalData, r);
+#endif
+ return r;
+ }
+ return addSlowCase(globalData, r);
+ }
+
+ static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r);
+ static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r);
+
+ static void checkSameIdentifierTable(ExecState*, UString::Rep*);
+ static void checkSameIdentifierTable(JSGlobalData*, UString::Rep*);
+ };
+
+ inline bool operator==(const Identifier& a, const Identifier& b)
+ {
+ return Identifier::equal(a, b);
+ }
+
+ inline bool operator!=(const Identifier& a, const Identifier& b)
+ {
+ return !Identifier::equal(a, b);
+ }
+
+ inline bool operator==(const Identifier& a, const char* b)
+ {
+ return Identifier::equal(a, b);
+ }
+
+ inline bool operator!=(const Identifier& a, const char* b)
+ {
+ return !Identifier::equal(a, b);
+ }
+
+ IdentifierTable* createIdentifierTable();
+ void deleteIdentifierTable(IdentifierTable*);
+
+} // namespace JSC
+
+#endif // Identifier_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InitializeThreading.h"
+
+#include "JSImmediate.h"
+#include "Collector.h"
+#include "DateMath.h"
+#include "dtoa.h"
+#include "Identifier.h"
+#include "JSGlobalObject.h"
+#include "UString.h"
+#include <wtf/Threading.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
+#endif
+
+static void initializeThreadingOnce()
+{
+ WTF::initializeThreading();
+ initializeUString();
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex = new Mutex;
+ initDateMath();
+#endif
+}
+
+void initializeThreading()
+{
+#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+ pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
+#else
+ static bool initializedThreading = false;
+ if (!initializedThreading) {
+ initializeThreadingOnce();
+ initializedThreading = true;
+ }
+#endif
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InitializeThreading_h
+#define InitializeThreading_h
+
+namespace JSC {
+
+ // This function must be called from the main thread. It is safe to call it repeatedly.
+ // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
+ void initializeThreading();
+
+}
+
+#endif // InitializeThreading_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "InternalFunction.h"
+
+#include "FunctionPrototype.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
+
+const ClassInfo InternalFunction::info = { "Function", 0, 0, 0 };
+
+const ClassInfo* InternalFunction::classInfo() const
+{
+ return &info;
+}
+
+InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<Structure> structure, const Identifier& name)
+ : JSObject(structure)
+{
+ putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum);
+}
+
+const UString& InternalFunction::name(JSGlobalData* globalData)
+{
+ return asString(getDirect(globalData->propertyNames->name))->value();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InternalFunction_h
+#define InternalFunction_h
+
+#include "JSObject.h"
+#include "Identifier.h"
+
+namespace JSC {
+
+ class FunctionPrototype;
+
+ class InternalFunction : public JSObject {
+ public:
+ virtual const ClassInfo* classInfo() const;
+ static const ClassInfo info;
+
+ const UString& name(JSGlobalData*);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ }
+
+ protected:
+ InternalFunction(PassRefPtr<Structure> structure) : JSObject(structure) { }
+ InternalFunction(JSGlobalData*, PassRefPtr<Structure>, const Identifier&);
+
+ private:
+ virtual CallType getCallData(CallData&) = 0;
+ };
+
+ InternalFunction* asInternalFunction(JSValuePtr);
+
+ inline InternalFunction* asInternalFunction(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&InternalFunction::info));
+ return static_cast<InternalFunction*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // InternalFunction_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSActivation.h"
+
+#include "Arguments.h"
+#include "Interpreter.h"
+#include "JSFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSActivation);
+
+const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
+
+JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
+ : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame))
+{
+}
+
+JSActivation::~JSActivation()
+{
+ delete d();
+}
+
+void JSActivation::mark()
+{
+ Base::mark();
+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
+
+ size_t i = 0;
+ size_t count = numParametersMinusThis;
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+
+ size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+
+ // Skip the call frame, which sits between the parameters and vars.
+ i += RegisterFile::CallFrameHeaderSize;
+ count += RegisterFile::CallFrameHeaderSize + numVars;
+
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+}
+
+bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (symbolTableGet(propertyName, slot))
+ return true;
+
+ if (JSValuePtr* location = getDirectLocation(propertyName)) {
+ slot.setValueSlot(location);
+ return true;
+ }
+
+ // Only return the built-in arguments object if it wasn't overridden above.
+ if (propertyName == exec->propertyNames().arguments) {
+ slot.setCustom(this, getArgumentsGetter());
+ return true;
+ }
+
+ // We don't call through to JSObject because there's no way to give an
+ // activation object getter properties or a prototype.
+ ASSERT(!hasGetterSetterProperties());
+ ASSERT(prototype().isNull());
+ return false;
+}
+
+void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePut(propertyName, value))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!hasGetterSetterProperties());
+ putDirect(propertyName, value, 0, true, slot);
+}
+
+// FIXME: Make this function honor ReadOnly (const) and DontEnum
+void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!hasGetterSetterProperties());
+ PutPropertySlot slot;
+ putDirect(propertyName, value, attributes, true, slot);
+}
+
+bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().arguments)
+ return false;
+
+ return Base::deleteProperty(exec, propertyName);
+}
+
+JSObject* JSActivation::toThisObject(ExecState* exec) const
+{
+ return exec->globalThisValue();
+}
+
+bool JSActivation::isDynamicScope() const
+{
+ return d()->functionBody->usesEval();
+}
+
+JSValuePtr JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSActivation* activation = asActivation(slot.slotBase());
+
+ if (activation->d()->functionBody->usesArguments()) {
+ PropertySlot slot;
+ activation->symbolTableGet(exec->propertyNames().arguments, slot);
+ return slot.getValue(exec, exec->propertyNames().arguments);
+ }
+
+ CallFrame* callFrame = CallFrame::create(activation->d()->registers);
+ Arguments* arguments = callFrame->optionalCalleeArguments();
+ if (!arguments) {
+ arguments = new (callFrame) Arguments(callFrame);
+ arguments->copyRegisters();
+ callFrame->setCalleeArguments(arguments);
+ }
+ ASSERT(arguments->isObject(&Arguments::info));
+
+ return arguments;
+}
+
+// These two functions serve the purpose of isolating the common case from a
+// PIC branch.
+
+PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
+{
+ return argumentsGetter;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSActivation_h
+#define JSActivation_h
+
+#include "CodeBlock.h"
+#include "JSVariableObject.h"
+#include "RegisterFile.h"
+#include "SymbolTable.h"
+#include "Nodes.h"
+
+namespace JSC {
+
+ class Arguments;
+ class Register;
+
+ class JSActivation : public JSVariableObject {
+ typedef JSVariableObject Base;
+ public:
+ JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>);
+ virtual ~JSActivation();
+
+ virtual void mark();
+
+ virtual bool isDynamicScope() const;
+
+ virtual bool isActivationObject() const { return true; }
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
+
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ virtual JSObject* toThisObject(ExecState*) const;
+
+ void copyRegisters(Arguments* arguments);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+
+ private:
+ struct JSActivationData : public JSVariableObjectData {
+ JSActivationData(PassRefPtr<FunctionBodyNode> functionBody, Register* registers)
+ : JSVariableObjectData(&functionBody->generatedBytecode().symbolTable(), registers)
+ , functionBody(functionBody)
+ {
+ }
+
+ RefPtr<FunctionBodyNode> functionBody;
+ };
+
+ static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
+
+ JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
+ };
+
+ JSActivation* asActivation(JSValuePtr);
+
+ inline JSActivation* asActivation(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&JSActivation::info));
+ return static_cast<JSActivation*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // JSActivation_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "JSArray.h"
+
+#include "ArrayPrototype.h"
+#include "PropertyNameArray.h"
+#include <wtf/AVLTree.h>
+#include <wtf/Assertions.h>
+#include <Operations.h>
+
+#define CHECK_ARRAY_CONSISTENCY 0
+
+using namespace std;
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSArray);
+
+// Overview of JSArray
+//
+// Properties of JSArray objects may be stored in one of three locations:
+// * The regular JSObject property map.
+// * A storage vector.
+// * A sparse map of array entries.
+//
+// Properties with non-numeric identifiers, with identifiers that are not representable
+// as an unsigned integer, or where the value is greater than MAX_ARRAY_INDEX
+// (specifically, this is only one property - the value 0xFFFFFFFFU as an unsigned 32-bit
+// integer) are not considered array indices and will be stored in the JSObject property map.
+//
+// All properties with a numeric identifer, representable as an unsigned integer i,
+// where (i <= MAX_ARRAY_INDEX), are an array index and will be stored in either the
+// storage vector or the sparse map. An array index i will be handled in the following
+// fashion:
+//
+// * Where (i < MIN_SPARSE_ARRAY_INDEX) the value will be stored in the storage vector.
+// * Where (MIN_SPARSE_ARRAY_INDEX <= i <= MAX_STORAGE_VECTOR_INDEX) the value will either
+// be stored in the storage vector or in the sparse array, depending on the density of
+// data that would be stored in the vector (a vector being used where at least
+// (1 / minDensityMultiplier) of the entries would be populated).
+// * Where (MAX_STORAGE_VECTOR_INDEX < i <= MAX_ARRAY_INDEX) the value will always be stored
+// in the sparse array.
+
+// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
+// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
+// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValuePtr)) +
+// (vectorLength * sizeof(JSValuePtr)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr))
+
+// These values have to be macros to be used in max() and min() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_SPARSE_ARRAY_INDEX 10000U
+#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
+// 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
+#define MAX_ARRAY_INDEX 0xFFFFFFFEU
+
+// Our policy for when to use a vector and when to use a sparse map.
+// For all array indices under MIN_SPARSE_ARRAY_INDEX, we always use a vector.
+// When indices greater than MIN_SPARSE_ARRAY_INDEX are involved, we use a vector
+// as long as it is 1/8 full. If more sparse than that, we use a map.
+static const unsigned minDensityMultiplier = 8;
+
+const ClassInfo JSArray::info = {"Array", 0, 0, 0};
+
+static inline size_t storageSize(unsigned vectorLength)
+{
+ ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+ // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
+ // - as asserted above - the following calculation cannot overflow.
+ size_t size = (sizeof(ArrayStorage) - sizeof(JSValuePtr)) + (vectorLength * sizeof(JSValuePtr));
+ // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
+ // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
+ ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValuePtr))) / sizeof(JSValuePtr) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValuePtr))));
+
+ return size;
+}
+
+static inline unsigned increasedVectorLength(unsigned newLength)
+{
+ ASSERT(newLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+ // Mathematically equivalent to:
+ // increasedLength = (newLength * 3 + 1) / 2;
+ // or:
+ // increasedLength = (unsigned)ceil(newLength * 1.5));
+ // This form is not prone to internal overflow.
+ unsigned increasedLength = newLength + (newLength >> 1) + (newLength & 1);
+ ASSERT(increasedLength >= newLength);
+
+ return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
+}
+
+static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
+{
+ return length / minDensityMultiplier <= numValues;
+}
+
+#if !CHECK_ARRAY_CONSISTENCY
+
+inline void JSArray::checkConsistency(ConsistencyCheckType)
+{
+}
+
+#endif
+
+JSArray::JSArray(PassRefPtr<Structure> structure)
+ : JSObject(structure)
+{
+ unsigned initialCapacity = 0;
+
+ m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+ m_fastAccessCutoff = 0;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_length = 0;
+
+ checkConsistency();
+}
+
+JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength)
+ : JSObject(structure)
+{
+ unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
+
+ m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+ m_fastAccessCutoff = 0;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_length = initialLength;
+
+ Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValuePtr));
+
+ checkConsistency();
+}
+
+JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList& list)
+ : JSObject(structure)
+{
+ unsigned length = list.size();
+
+ m_fastAccessCutoff = length;
+
+ ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length)));
+
+ storage->m_vectorLength = length;
+ storage->m_numValuesInVector = length;
+ storage->m_sparseValueMap = 0;
+ storage->m_length = length;
+
+ size_t i = 0;
+ ArgList::const_iterator end = list.end();
+ for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
+ storage->m_vector[i] = (*it).jsValue(exec);
+
+ m_storage = storage;
+
+ Heap::heap(this)->reportExtraMemoryCost(storageSize(length));
+
+ checkConsistency();
+}
+
+JSArray::~JSArray()
+{
+ checkConsistency(DestructorConsistencyCheck);
+
+ delete m_storage->m_sparseValueMap;
+ fastFree(m_storage);
+}
+
+bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+{
+ ArrayStorage* storage = m_storage;
+
+ if (i >= storage->m_length) {
+ if (i > MAX_ARRAY_INDEX)
+ return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
+ return false;
+ }
+
+ if (i < storage->m_vectorLength) {
+ JSValuePtr& valueSlot = storage->m_vector[i];
+ if (valueSlot) {
+ slot.setValueSlot(&valueSlot);
+ return true;
+ }
+ } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap::iterator it = map->find(i);
+ if (it != map->end()) {
+ slot.setValueSlot(&it->second);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setValue(jsNumber(exec, length()));
+ return true;
+ }
+
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex)
+ return JSArray::getOwnPropertySlot(exec, i, slot);
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+// ECMA 15.4.5.1
+void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex) {
+ put(exec, i, value);
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ unsigned newLength = value.toUInt32(exec);
+ if (value.toNumber(exec) != static_cast<double>(newLength)) {
+ throwError(exec, RangeError, "Invalid array length.");
+ return;
+ }
+ setLength(newLength);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value)
+{
+ checkConsistency();
+
+ unsigned length = m_storage->m_length;
+ if (i >= length && i <= MAX_ARRAY_INDEX) {
+ length = i + 1;
+ m_storage->m_length = length;
+ }
+
+ if (i < m_storage->m_vectorLength) {
+ JSValuePtr& valueSlot = m_storage->m_vector[i];
+ if (valueSlot) {
+ valueSlot = value;
+ checkConsistency();
+ return;
+ }
+ valueSlot = value;
+ if (++m_storage->m_numValuesInVector == m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+
+ putSlowCase(exec, i, value);
+}
+
+NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr value)
+{
+ ArrayStorage* storage = m_storage;
+ SparseArrayValueMap* map = storage->m_sparseValueMap;
+
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ if (i > MAX_ARRAY_INDEX) {
+ PutPropertySlot slot;
+ put(exec, Identifier::from(exec, i), value, slot);
+ return;
+ }
+
+ // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
+ // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
+ if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
+ if (!map) {
+ map = new SparseArrayValueMap;
+ storage->m_sparseValueMap = map;
+ }
+ map->set(i, value);
+ return;
+ }
+ }
+
+ // We have decided that we'll put the new item into the vector.
+ // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.
+ if (!map || map->isEmpty()) {
+ if (increaseVectorLength(i + 1)) {
+ storage = m_storage;
+ storage->m_vector[i] = value;
+ if (++storage->m_numValuesInVector == storage->m_length)
+ m_fastAccessCutoff = storage->m_length;
+ checkConsistency();
+ } else
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ // Decide how many values it would be best to move from the map.
+ unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
+ unsigned newVectorLength = increasedVectorLength(i + 1);
+ for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+ newNumValuesInVector += map->contains(j);
+ if (i >= MIN_SPARSE_ARRAY_INDEX)
+ newNumValuesInVector -= map->contains(i);
+ if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
+ unsigned proposedNewNumValuesInVector = newNumValuesInVector;
+ // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further.
+ while (newVectorLength < MAX_STORAGE_VECTOR_LENGTH) {
+ unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);
+ for (unsigned j = max(newVectorLength, MIN_SPARSE_ARRAY_INDEX); j < proposedNewVectorLength; ++j)
+ proposedNewNumValuesInVector += map->contains(j);
+ if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))
+ break;
+ newVectorLength = proposedNewVectorLength;
+ newNumValuesInVector = proposedNewNumValuesInVector;
+ }
+ }
+
+ storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
+ if (!storage) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ unsigned vectorLength = storage->m_vectorLength;
+
+ Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+
+ if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
+ for (unsigned j = vectorLength; j < newVectorLength; ++j)
+ storage->m_vector[j] = noValue();
+ if (i > MIN_SPARSE_ARRAY_INDEX)
+ map->remove(i);
+ } else {
+ for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j)
+ storage->m_vector[j] = noValue();
+ for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+ storage->m_vector[j] = map->take(j);
+ }
+
+ storage->m_vector[i] = value;
+
+ storage->m_vectorLength = newVectorLength;
+ storage->m_numValuesInVector = newNumValuesInVector;
+
+ m_storage = storage;
+
+ checkConsistency();
+}
+
+bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex)
+ return deleteProperty(exec, i);
+
+ if (propertyName == exec->propertyNames().length)
+ return false;
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+bool JSArray::deleteProperty(ExecState* exec, unsigned i)
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ if (i < storage->m_vectorLength) {
+ JSValuePtr& valueSlot = storage->m_vector[i];
+ if (!valueSlot) {
+ checkConsistency();
+ return false;
+ }
+ valueSlot = noValue();
+ --storage->m_numValuesInVector;
+ if (m_fastAccessCutoff > i)
+ m_fastAccessCutoff = i;
+ checkConsistency();
+ return true;
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap::iterator it = map->find(i);
+ if (it != map->end()) {
+ map->remove(it);
+ checkConsistency();
+ return true;
+ }
+ }
+ }
+
+ checkConsistency();
+
+ if (i > MAX_ARRAY_INDEX)
+ return deleteProperty(exec, Identifier::from(exec, i));
+
+ return false;
+}
+
+void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ // FIXME: Filling PropertyNameArray with an identifier for every integer
+ // is incredibly inefficient for large arrays. We need a different approach,
+ // which almost certainly means a different structure for PropertyNameArray.
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+ for (unsigned i = 0; i < usedVectorLength; ++i) {
+ if (storage->m_vector[i])
+ propertyNames.add(Identifier::from(exec, i));
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ propertyNames.add(Identifier::from(exec, it->first));
+ }
+
+ JSObject::getPropertyNames(exec, propertyNames);
+}
+
+bool JSArray::increaseVectorLength(unsigned newLength)
+{
+ // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
+ // to the vector. Callers have to account for that, because they can do it more efficiently.
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned vectorLength = storage->m_vectorLength;
+ ASSERT(newLength > vectorLength);
+ ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
+ unsigned newVectorLength = increasedVectorLength(newLength);
+
+ storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
+ if (!storage)
+ return false;
+
+ Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+ storage->m_vectorLength = newVectorLength;
+
+ for (unsigned i = vectorLength; i < newVectorLength; ++i)
+ storage->m_vector[i] = noValue();
+
+ m_storage = storage;
+ return true;
+}
+
+void JSArray::setLength(unsigned newLength)
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned length = m_storage->m_length;
+
+ if (newLength < length) {
+ if (m_fastAccessCutoff > newLength)
+ m_fastAccessCutoff = newLength;
+
+ unsigned usedVectorLength = min(length, storage->m_vectorLength);
+ for (unsigned i = newLength; i < usedVectorLength; ++i) {
+ JSValuePtr& valueSlot = storage->m_vector[i];
+ bool hadValue = valueSlot;
+ valueSlot = noValue();
+ storage->m_numValuesInVector -= hadValue;
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap copy = *map;
+ SparseArrayValueMap::iterator end = copy.end();
+ for (SparseArrayValueMap::iterator it = copy.begin(); it != end; ++it) {
+ if (it->first >= newLength)
+ map->remove(it->first);
+ }
+ if (map->isEmpty()) {
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+ }
+ }
+
+ m_storage->m_length = newLength;
+
+ checkConsistency();
+}
+
+JSValuePtr JSArray::pop()
+{
+ checkConsistency();
+
+ unsigned length = m_storage->m_length;
+ if (!length)
+ return jsUndefined();
+
+ --length;
+
+ JSValuePtr result;
+
+ if (m_fastAccessCutoff > length) {
+ JSValuePtr& valueSlot = m_storage->m_vector[length];
+ result = valueSlot;
+ ASSERT(result);
+ valueSlot = noValue();
+ --m_storage->m_numValuesInVector;
+ m_fastAccessCutoff = length;
+ } else if (length < m_storage->m_vectorLength) {
+ JSValuePtr& valueSlot = m_storage->m_vector[length];
+ result = valueSlot;
+ valueSlot = noValue();
+ if (result)
+ --m_storage->m_numValuesInVector;
+ else
+ result = jsUndefined();
+ } else {
+ result = jsUndefined();
+ if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator it = map->find(length);
+ if (it != map->end()) {
+ result = it->second;
+ map->remove(it);
+ if (map->isEmpty()) {
+ delete map;
+ m_storage->m_sparseValueMap = 0;
+ }
+ }
+ }
+ }
+
+ m_storage->m_length = length;
+
+ checkConsistency();
+
+ return result;
+}
+
+void JSArray::push(ExecState* exec, JSValuePtr value)
+{
+ checkConsistency();
+
+ if (m_storage->m_length < m_storage->m_vectorLength) {
+ ASSERT(!m_storage->m_vector[m_storage->m_length]);
+ m_storage->m_vector[m_storage->m_length] = value;
+ if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+
+ if (m_storage->m_length < MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ if (!map || map->isEmpty()) {
+ if (increaseVectorLength(m_storage->m_length + 1)) {
+ m_storage->m_vector[m_storage->m_length] = value;
+ if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+ checkConsistency();
+ throwOutOfMemoryError(exec);
+ return;
+ }
+ }
+
+ putSlowCase(exec, m_storage->m_length++, value);
+}
+
+void JSArray::mark()
+{
+ JSObject::mark();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+ for (unsigned i = 0; i < usedVectorLength; ++i) {
+ JSValuePtr value = storage->m_vector[i];
+ if (value && !value.marked())
+ value.mark();
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+ JSValuePtr value = it->second;
+ if (!value.marked())
+ value.mark();
+ }
+ }
+}
+
+static int compareNumbersForQSort(const void* a, const void* b)
+{
+ double da = static_cast<const JSValuePtr*>(a)->uncheckedGetNumber();
+ double db = static_cast<const JSValuePtr*>(b)->uncheckedGetNumber();
+ return (da > db) - (da < db);
+}
+
+typedef std::pair<JSValuePtr, UString> ValueStringPair;
+
+static int compareByStringPairForQSort(const void* a, const void* b)
+{
+ const ValueStringPair* va = static_cast<const ValueStringPair*>(a);
+ const ValueStringPair* vb = static_cast<const ValueStringPair*>(b);
+ return compare(va->second, vb->second);
+}
+
+void JSArray::sortNumeric(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData)
+{
+ unsigned lengthNotIncludingUndefined = compactForSorting();
+ if (m_storage->m_sparseValueMap) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ if (!lengthNotIncludingUndefined)
+ return;
+
+ bool allValuesAreNumbers = true;
+ size_t size = m_storage->m_numValuesInVector;
+ for (size_t i = 0; i < size; ++i) {
+ if (!m_storage->m_vector[i].isNumber()) {
+ allValuesAreNumbers = false;
+ break;
+ }
+ }
+
+ if (!allValuesAreNumbers)
+ return sort(exec, compareFunction, callType, callData);
+
+ // For numeric comparison, which is fast, qsort is faster than mergesort. We
+ // also don't require mergesort's stability, since there's no user visible
+ // side-effect from swapping the order of equal primitive values.
+ qsort(m_storage->m_vector, size, sizeof(JSValuePtr), compareNumbersForQSort);
+
+ checkConsistency(SortConsistencyCheck);
+}
+
+void JSArray::sort(ExecState* exec)
+{
+ unsigned lengthNotIncludingUndefined = compactForSorting();
+ if (m_storage->m_sparseValueMap) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ if (!lengthNotIncludingUndefined)
+ return;
+
+ // Converting JavaScript values to strings can be expensive, so we do it once up front and sort based on that.
+ // This is a considerable improvement over doing it twice per comparison, though it requires a large temporary
+ // buffer. Besides, this protects us from crashing if some objects have custom toString methods that return
+ // random or otherwise changing results, effectively making compare function inconsistent.
+
+ Vector<ValueStringPair> values(lengthNotIncludingUndefined);
+ if (!values.begin()) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
+ JSValuePtr value = m_storage->m_vector[i];
+ ASSERT(!value.isUndefined());
+ values[i].first = value;
+ }
+
+ // FIXME: While calling these toString functions, the array could be mutated.
+ // In that case, objects pointed to by values in this vector might get garbage-collected!
+
+ // FIXME: The following loop continues to call toString on subsequent values even after
+ // a toString call raises an exception.
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
+ values[i].second = values[i].first.toString(exec);
+
+ if (exec->hadException())
+ return;
+
+ // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather
+ // than O(N log N).
+
+#if HAVE(MERGESORT)
+ mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);
+#else
+ // FIXME: The qsort library function is likely to not be a stable sort.
+ // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort.
+ qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);
+#endif
+
+ // FIXME: If the toString function changed the length of the array, this might be
+ // modifying the vector incorrectly.
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
+ m_storage->m_vector[i] = values[i].first;
+
+ checkConsistency(SortConsistencyCheck);
+}
+
+struct AVLTreeNodeForArrayCompare {
+ JSValuePtr value;
+
+ // Child pointers. The high bit of gt is robbed and used as the
+ // balance factor sign. The high bit of lt is robbed and used as
+ // the magnitude of the balance factor.
+ int32_t gt;
+ int32_t lt;
+};
+
+struct AVLTreeAbstractorForArrayCompare {
+ typedef int32_t handle; // Handle is an index into m_nodes vector.
+ typedef JSValuePtr key;
+ typedef int32_t size;
+
+ Vector<AVLTreeNodeForArrayCompare> m_nodes;
+ ExecState* m_exec;
+ JSValuePtr m_compareFunction;
+ CallType m_compareCallType;
+ const CallData* m_compareCallData;
+ JSValuePtr m_globalThisValue;
+
+ handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }
+ void set_less(handle h, handle lh) { m_nodes[h].lt &= 0x80000000; m_nodes[h].lt |= lh; }
+ handle get_greater(handle h) { return m_nodes[h].gt & 0x7FFFFFFF; }
+ void set_greater(handle h, handle gh) { m_nodes[h].gt &= 0x80000000; m_nodes[h].gt |= gh; }
+
+ int get_balance_factor(handle h)
+ {
+ if (m_nodes[h].gt & 0x80000000)
+ return -1;
+ return static_cast<unsigned>(m_nodes[h].lt) >> 31;
+ }
+
+ void set_balance_factor(handle h, int bf)
+ {
+ if (bf == 0) {
+ m_nodes[h].lt &= 0x7FFFFFFF;
+ m_nodes[h].gt &= 0x7FFFFFFF;
+ } else {
+ m_nodes[h].lt |= 0x80000000;
+ if (bf < 0)
+ m_nodes[h].gt |= 0x80000000;
+ else
+ m_nodes[h].gt &= 0x7FFFFFFF;
+ }
+ }
+
+ int compare_key_key(key va, key vb)
+ {
+ ASSERT(!va.isUndefined());
+ ASSERT(!vb.isUndefined());
+
+ if (m_exec->hadException())
+ return 1;
+
+ ArgList arguments;
+ arguments.append(va);
+ arguments.append(vb);
+ double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec);
+ return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.
+ }
+
+ int compare_key_node(key k, handle h) { return compare_key_key(k, m_nodes[h].value); }
+ int compare_node_node(handle h1, handle h2) { return compare_key_key(m_nodes[h1].value, m_nodes[h2].value); }
+
+ static handle null() { return 0x7FFFFFFF; }
+};
+
+void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData)
+{
+ checkConsistency();
+
+ // FIXME: This ignores exceptions raised in the compare function or in toNumber.
+
+ // The maximum tree depth is compiled in - but the caller is clearly up to no good
+ // if a larger array is passed.
+ ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
+ if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
+ return;
+
+ if (!m_storage->m_length)
+ return;
+
+ unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);
+
+ AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
+ tree.abstractor().m_exec = exec;
+ tree.abstractor().m_compareFunction = compareFunction;
+ tree.abstractor().m_compareCallType = callType;
+ tree.abstractor().m_compareCallData = &callData;
+ tree.abstractor().m_globalThisValue = exec->globalThisValue();
+ tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));
+
+ if (!tree.abstractor().m_nodes.begin()) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ // FIXME: If the compare function modifies the array, the vector, map, etc. could be modified
+ // right out from under us while we're building the tree here.
+
+ unsigned numDefined = 0;
+ unsigned numUndefined = 0;
+
+ // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.
+ for (; numDefined < usedVectorLength; ++numDefined) {
+ JSValuePtr v = m_storage->m_vector[numDefined];
+ if (!v || v.isUndefined())
+ break;
+ tree.abstractor().m_nodes[numDefined].value = v;
+ tree.insert(numDefined);
+ }
+ for (unsigned i = numDefined; i < usedVectorLength; ++i) {
+ JSValuePtr v = m_storage->m_vector[i];
+ if (v) {
+ if (v.isUndefined())
+ ++numUndefined;
+ else {
+ tree.abstractor().m_nodes[numDefined].value = v;
+ tree.insert(numDefined);
+ ++numDefined;
+ }
+ }
+ }
+
+ unsigned newUsedVectorLength = numDefined + numUndefined;
+
+ if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > m_storage->m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+ }
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+ tree.abstractor().m_nodes[numDefined].value = it->second;
+ tree.insert(numDefined);
+ ++numDefined;
+ }
+
+ delete map;
+ m_storage->m_sparseValueMap = 0;
+ }
+
+ ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
+
+ // FIXME: If the compare function changed the length of the array, the following might be
+ // modifying the vector incorrectly.
+
+ // Copy the values back into m_storage.
+ AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;
+ iter.start_iter_least(tree);
+ for (unsigned i = 0; i < numDefined; ++i) {
+ m_storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value;
+ ++iter;
+ }
+
+ // Put undefined values back in.
+ for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
+ m_storage->m_vector[i] = jsUndefined();
+
+ // Ensure that unused values in the vector are zeroed out.
+ for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
+ m_storage->m_vector[i] = noValue();
+
+ m_fastAccessCutoff = newUsedVectorLength;
+ m_storage->m_numValuesInVector = newUsedVectorLength;
+
+ checkConsistency(SortConsistencyCheck);
+}
+
+void JSArray::fillArgList(ExecState* exec, ArgList& args)
+{
+ unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+ unsigned i = 0;
+ for (; i < fastAccessLength; ++i)
+ args.append(getIndex(i));
+ for (; i < m_storage->m_length; ++i)
+ args.append(get(exec, i));
+}
+
+unsigned JSArray::compactForSorting()
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);
+
+ unsigned numDefined = 0;
+ unsigned numUndefined = 0;
+
+ for (; numDefined < usedVectorLength; ++numDefined) {
+ JSValuePtr v = storage->m_vector[numDefined];
+ if (!v || v.isUndefined())
+ break;
+ }
+ for (unsigned i = numDefined; i < usedVectorLength; ++i) {
+ JSValuePtr v = storage->m_vector[i];
+ if (v) {
+ if (v.isUndefined())
+ ++numUndefined;
+ else
+ storage->m_vector[numDefined++] = v;
+ }
+ }
+
+ unsigned newUsedVectorLength = numDefined + numUndefined;
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > storage->m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries - if not,
+ // exception is thrown by caller.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
+ return 0;
+ storage = m_storage;
+ }
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ storage->m_vector[numDefined++] = it->second;
+
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+
+ for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
+ storage->m_vector[i] = jsUndefined();
+ for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
+ storage->m_vector[i] = noValue();
+
+ m_fastAccessCutoff = newUsedVectorLength;
+ storage->m_numValuesInVector = newUsedVectorLength;
+
+ checkConsistency(SortConsistencyCheck);
+
+ return numDefined;
+}
+
+void* JSArray::lazyCreationData()
+{
+ return m_storage->lazyCreationData;
+}
+
+void JSArray::setLazyCreationData(void* d)
+{
+ m_storage->lazyCreationData = d;
+}
+
+#if CHECK_ARRAY_CONSISTENCY
+
+void JSArray::checkConsistency(ConsistencyCheckType type)
+{
+ ASSERT(m_storage);
+ if (type == SortConsistencyCheck)
+ ASSERT(!m_storage->m_sparseValueMap);
+
+ ASSERT(m_fastAccessCutoff <= m_storage->m_length);
+ ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
+
+ unsigned numValuesInVector = 0;
+ for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
+ if (JSValuePtr value = m_storage->m_vector[i]) {
+ ASSERT(i < m_storage->m_length);
+ if (type != DestructorConsistencyCheck)
+ value->type(); // Likely to crash if the object was deallocated.
+ ++numValuesInVector;
+ } else {
+ ASSERT(i >= m_fastAccessCutoff);
+ if (type == SortConsistencyCheck)
+ ASSERT(i >= m_storage->m_numValuesInVector);
+ }
+ }
+ ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
+
+ if (m_storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
+ for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
+ unsigned index = it->first;
+ ASSERT(index < m_storage->m_length);
+ ASSERT(index >= m_storage->m_vectorLength);
+ ASSERT(index <= MAX_ARRAY_INDEX);
+ ASSERT(it->second);
+ if (type != DestructorConsistencyCheck)
+ it->second->type(); // Likely to crash if the object was deallocated.
+ }
+ }
+}
+
+#endif
+
+JSArray* constructEmptyArray(ExecState* exec)
+{
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+}
+
+JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
+{
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
+}
+
+JSArray* constructArray(ExecState* exec, JSValuePtr singleItemValue)
+{
+ ArgList values;
+ values.append(singleItemValue);
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+}
+
+JSArray* constructArray(ExecState* exec, const ArgList& values)
+{
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JSArray_h
+#define JSArray_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ typedef HashMap<unsigned, JSValuePtr> SparseArrayValueMap;
+
+ struct ArrayStorage {
+ unsigned m_length;
+ unsigned m_vectorLength;
+ unsigned m_numValuesInVector;
+ SparseArrayValueMap* m_sparseValueMap;
+ void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
+ JSValuePtr m_vector[1];
+ };
+
+ class JSArray : public JSObject {
+ friend class JIT;
+
+ public:
+ explicit JSArray(PassRefPtr<Structure>);
+ JSArray(PassRefPtr<Structure>, unsigned initialLength);
+ JSArray(ExecState*, PassRefPtr<Structure>, const ArgList& initialValues);
+ virtual ~JSArray();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValuePtr); // FIXME: Make protected and add setItem.
+
+ static const ClassInfo info;
+
+ unsigned length() const { return m_storage->m_length; }
+ void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
+
+ void sort(ExecState*);
+ void sort(ExecState*, JSValuePtr compareFunction, CallType, const CallData&);
+ void sortNumeric(ExecState*, JSValuePtr compareFunction, CallType, const CallData&);
+
+ void push(ExecState*, JSValuePtr);
+ JSValuePtr pop();
+
+ bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+ JSValuePtr getIndex(unsigned i)
+ {
+ ASSERT(canGetIndex(i));
+ return m_storage->m_vector[i];
+ }
+
+ bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+ JSValuePtr setIndex(unsigned i, JSValuePtr v)
+ {
+ ASSERT(canSetIndex(i));
+ return m_storage->m_vector[i] = v;
+ }
+
+ void fillArgList(ExecState*, ArgList&);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void mark();
+
+ void* lazyCreationData();
+ void setLazyCreationData(void*);
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
+ void putSlowCase(ExecState*, unsigned propertyName, JSValuePtr);
+
+ bool increaseVectorLength(unsigned newLength);
+
+ unsigned compactForSorting();
+
+ enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
+ void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
+
+ unsigned m_fastAccessCutoff;
+ ArrayStorage* m_storage;
+ };
+
+ JSArray* asArray(JSValuePtr);
+
+ JSArray* constructEmptyArray(ExecState*);
+ JSArray* constructEmptyArray(ExecState*, unsigned initialLength);
+ JSArray* constructArray(ExecState*, JSValuePtr singleItemValue);
+ JSArray* constructArray(ExecState*, const ArgList& values);
+
+ inline JSArray* asArray(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&JSArray::info));
+ return static_cast<JSArray*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // JSArray_h
--- /dev/null
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSByteArray.h"
+
+#include "JSGlobalObject.h"
+#include "PropertyNameArray.h"
+
+using namespace WTF;
+
+namespace JSC {
+
+const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
+
+JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
+ : JSObject(structure)
+ , m_storage(storage)
+ , m_classInfo(classInfo)
+{
+ putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
+}
+
+PassRefPtr<Structure> JSByteArray::createStructure(JSValuePtr prototype)
+{
+ PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType));
+ return result;
+}
+
+bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ bool ok;
+ unsigned index = propertyName.toUInt32(&ok, false);
+ if (ok && canAccessIndex(index)) {
+ slot.setValue(getIndex(exec, index));
+ return true;
+ }
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ if (canAccessIndex(propertyName)) {
+ slot.setValue(getIndex(exec, propertyName));
+ return true;
+ }
+ return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ bool ok;
+ unsigned index = propertyName.toUInt32(&ok, false);
+ if (ok) {
+ setIndex(exec, index, value);
+ return;
+ }
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+{
+ setIndex(exec, propertyName, value);
+}
+
+void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ unsigned length = m_storage->length();
+ for (unsigned i = 0; i < length; ++i)
+ propertyNames.add(Identifier::from(exec, i));
+ JSObject::getPropertyNames(exec, propertyNames);
+}
+
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSByteArray_h
+#define JSByteArray_h
+
+#include "JSObject.h"
+
+#include <wtf/ByteArray.h>
+
+namespace JSC {
+
+ class JSByteArray : public JSObject {
+ friend class Interpreter;
+ public:
+ bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
+ JSValuePtr getIndex(ExecState* exec, unsigned i)
+ {
+ ASSERT(canAccessIndex(i));
+ return jsNumber(exec, m_storage->data()[i]);
+ }
+
+ void setIndex(unsigned i, int value)
+ {
+ ASSERT(canAccessIndex(i));
+ if (value & ~0xFF) {
+ if (value < 0)
+ value = 0;
+ else
+ value = 255;
+ }
+ m_storage->data()[i] = static_cast<unsigned char>(value);
+ }
+
+ void setIndex(unsigned i, double value)
+ {
+ ASSERT(canAccessIndex(i));
+ if (!(value > 0)) // Clamp NaN to 0
+ value = 0;
+ else if (value > 255)
+ value = 255;
+ m_storage->data()[i] = static_cast<unsigned char>(value + 0.5);
+ }
+
+ void setIndex(ExecState* exec, unsigned i, JSValuePtr value)
+ {
+ double byteValue = value.toNumber(exec);
+ if (exec->hadException())
+ return;
+ if (canAccessIndex(i))
+ setIndex(i, byteValue);
+ }
+
+ JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype);
+
+ virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
+ virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+ virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValuePtr, JSC::PutPropertySlot&);
+ virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValuePtr);
+
+ virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+
+ virtual const ClassInfo* classInfo() const { return m_classInfo; }
+ static const ClassInfo s_defaultInfo;
+
+ size_t length() const { return m_storage->length(); }
+
+ private:
+ enum VPtrStealingHackType { VPtrStealingHack };
+ JSByteArray(VPtrStealingHackType)
+ : JSObject(createStructure(jsNull()))
+ , m_classInfo(0)
+ {
+ }
+
+ RefPtr<WTF::ByteArray> m_storage;
+ const ClassInfo* m_classInfo;
+ };
+
+ JSByteArray* asByteArray(JSValuePtr value);
+ inline JSByteArray* asByteArray(JSValuePtr value)
+ {
+ return static_cast<JSByteArray*>(asCell(value));
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSCell.h"
+
+#include "JSFunction.h"
+#include "JSString.h"
+#include "JSObject.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+#if defined NAN && defined INFINITY
+
+extern const double NaN = NAN;
+extern const double Inf = INFINITY;
+
+#else // !(defined NAN && defined INFINITY)
+
+// The trick is to define the NaN and Inf globals with a different type than the declaration.
+// This trick works because the mangled name of the globals does not include the type, although
+// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
+// characters don't necessarily need the same alignment doubles do, but for now it seems to work.
+// It would be good to figure out a 100% clean way that still avoids code that runs at init time.
+
+// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
+// while NaN_double has to be 4-byte aligned for 32-bits.
+// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
+
+static const union {
+ struct {
+ unsigned char NaN_Bytes[8];
+ unsigned char Inf_Bytes[8];
+ } bytes;
+
+ struct {
+ double NaN_Double;
+ double Inf_Double;
+ } doubles;
+
+} NaNInf = { {
+#if PLATFORM(BIG_ENDIAN)
+ { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
+ { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
+#elif PLATFORM(MIDDLE_ENDIAN)
+ { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
+ { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
+#else
+ { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
+ { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
+#endif
+} } ;
+
+extern const double NaN = NaNInf.doubles.NaN_Double;
+extern const double Inf = NaNInf.doubles.Inf_Double;
+
+#endif // !(defined NAN && defined INFINITY)
+
+void* JSCell::operator new(size_t size, ExecState* exec)
+{
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return exec->heap()->inlineAllocate(size);
+#else
+ return exec->heap()->allocate(size);
+#endif
+}
+
+bool JSCell::getUInt32(uint32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getTruncatedInt32(int32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getTruncatedUInt32(uint32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getString(UString&stringValue) const
+{
+ if (!isString())
+ return false;
+ stringValue = static_cast<const JSString*>(this)->value();
+ return true;
+}
+
+UString JSCell::getString() const
+{
+ return isString() ? static_cast<const JSString*>(this)->value() : UString();
+}
+
+JSObject* JSCell::getObject()
+{
+ return isObject() ? static_cast<JSObject*>(this) : 0;
+}
+
+const JSObject* JSCell::getObject() const
+{
+ return isObject() ? static_cast<const JSObject*>(this) : 0;
+}
+
+CallType JSCell::getCallData(CallData&)
+{
+ return CallTypeNone;
+}
+
+ConstructType JSCell::getConstructData(ConstructData&)
+{
+ return ConstructTypeNone;
+}
+
+bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
+{
+ // This is not a general purpose implementation of getOwnPropertySlot.
+ // It should only be called by JSValue::get.
+ // It calls getPropertySlot, not getOwnPropertySlot.
+ JSObject* object = toObject(exec);
+ slot.setBase(object);
+ if (!object->getPropertySlot(exec, identifier, slot))
+ slot.setUndefined();
+ return true;
+}
+
+bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
+{
+ // This is not a general purpose implementation of getOwnPropertySlot.
+ // It should only be called by JSValue::get.
+ // It calls getPropertySlot, not getOwnPropertySlot.
+ JSObject* object = toObject(exec);
+ slot.setBase(object);
+ if (!object->getPropertySlot(exec, identifier, slot))
+ slot.setUndefined();
+ return true;
+}
+
+void JSCell::put(ExecState* exec, const Identifier& identifier, JSValuePtr value, PutPropertySlot& slot)
+{
+ toObject(exec)->put(exec, identifier, value, slot);
+}
+
+void JSCell::put(ExecState* exec, unsigned identifier, JSValuePtr value)
+{
+ toObject(exec)->put(exec, identifier, value);
+}
+
+bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
+{
+ return toObject(exec)->deleteProperty(exec, identifier);
+}
+
+bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
+{
+ return toObject(exec)->deleteProperty(exec, identifier);
+}
+
+JSObject* JSCell::toThisObject(ExecState* exec) const
+{
+ return toObject(exec);
+}
+
+UString JSCell::toThisString(ExecState* exec) const
+{
+ return toThisObject(exec)->toString(exec);
+}
+
+JSString* JSCell::toThisJSString(ExecState* exec)
+{
+ return jsString(exec, toThisString(exec));
+}
+
+const ClassInfo* JSCell::classInfo() const
+{
+ return 0;
+}
+
+JSValuePtr JSCell::getJSNumber()
+{
+ return noValue();
+}
+
+bool JSCell::isGetterSetter() const
+{
+ return false;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSCell_h
+#define JSCell_h
+
+#include <wtf/Noncopyable.h>
+#include "Structure.h"
+#include "JSValue.h"
+#include "JSImmediate.h"
+#include "Collector.h"
+
+namespace JSC {
+
+ class JSCell : Noncopyable {
+ friend class JIT;
+ friend class GetterSetter;
+ friend class Heap;
+ friend class JSNumberCell;
+ friend class JSObject;
+ friend class JSPropertyNameIterator;
+ friend class JSString;
+ friend class JSValuePtr;
+ friend class Interpreter;
+
+ private:
+ explicit JSCell(Structure*);
+ virtual ~JSCell();
+
+ public:
+ // Querying the type.
+ bool isNumber() const;
+ bool isString() const;
+ bool isObject() const;
+ virtual bool isGetterSetter() const;
+ virtual bool isObject(const ClassInfo*) const;
+
+ Structure* structure() const;
+
+ // Extracting the value.
+ bool getString(UString&) const;
+ UString getString() const; // null string if not a string
+ JSObject* getObject(); // NULL if not an object
+ const JSObject* getObject() const; // NULL if not an object
+
+ virtual CallType getCallData(CallData&);
+ virtual ConstructType getConstructData(ConstructData&);
+
+ // Extracting integer values.
+ // FIXME: remove these methods, can check isNumberCell in JSValuePtr && then call asNumberCell::*.
+ virtual bool getUInt32(uint32_t&) const;
+ virtual bool getTruncatedInt32(int32_t&) const;
+ virtual bool getTruncatedUInt32(uint32_t&) const;
+
+ // Basic conversions.
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&) = 0;
+ virtual bool toBoolean(ExecState*) const = 0;
+ virtual double toNumber(ExecState*) const = 0;
+ virtual UString toString(ExecState*) const = 0;
+ virtual JSObject* toObject(ExecState*) const = 0;
+
+ // Garbage collection.
+ void* operator new(size_t, ExecState*);
+ void* operator new(size_t, JSGlobalData*);
+ void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
+ virtual void mark();
+ bool marked() const;
+
+ // Object operations, with the toObject operation included.
+ virtual const ClassInfo* classInfo() const;
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValuePtr);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+ virtual JSValuePtr getJSNumber();
+ void* vptr() { return *reinterpret_cast<void**>(this); }
+
+ private:
+ // Base implementation; for non-object classes implements getPropertySlot.
+ bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ Structure* m_structure;
+ };
+
+ JSCell* asCell(JSValuePtr);
+
+ inline JSCell* asCell(JSValuePtr value)
+ {
+ return value.asCell();
+ }
+
+ inline JSCell::JSCell(Structure* structure)
+ : m_structure(structure)
+ {
+ }
+
+ inline JSCell::~JSCell()
+ {
+ }
+
+ inline bool JSCell::isNumber() const
+ {
+ return Heap::isNumber(const_cast<JSCell*>(this));
+ }
+
+ inline bool JSCell::isObject() const
+ {
+ return m_structure->typeInfo().type() == ObjectType;
+ }
+
+ inline bool JSCell::isString() const
+ {
+ return m_structure->typeInfo().type() == StringType;
+ }
+
+ inline Structure* JSCell::structure() const
+ {
+ return m_structure;
+ }
+
+ inline bool JSCell::marked() const
+ {
+ return Heap::isCellMarked(this);
+ }
+
+ inline void JSCell::mark()
+ {
+ return Heap::markCell(this);
+ }
+
+ ALWAYS_INLINE JSCell* JSValuePtr::asCell() const
+ {
+ ASSERT(isCell());
+ return m_ptr;
+ }
+
+ inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+ {
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocate(size);
+#else
+ return globalData->heap.allocate(size);
+#endif
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ inline bool JSValuePtr::isString() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isString();
+ }
+
+ inline bool JSValuePtr::isGetterSetter() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter();
+ }
+
+ inline bool JSValuePtr::isObject() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isObject();
+ }
+
+ inline bool JSValuePtr::getString(UString& s) const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s);
+ }
+
+ inline UString JSValuePtr::getString() const
+ {
+ return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString();
+ }
+
+ inline JSObject* JSValuePtr::getObject() const
+ {
+ return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject();
+ }
+
+ inline CallType JSValuePtr::getCallData(CallData& callData)
+ {
+ return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData);
+ }
+
+ inline ConstructType JSValuePtr::getConstructData(ConstructData& constructData)
+ {
+ return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData);
+ }
+
+ ALWAYS_INLINE bool JSValuePtr::getUInt32(uint32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getUInt32(asValue(), v) : asCell()->getUInt32(v);
+ }
+
+ ALWAYS_INLINE bool JSValuePtr::getTruncatedInt32(int32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedInt32(asValue(), v) : asCell()->getTruncatedInt32(v);
+ }
+
+ inline bool JSValuePtr::getTruncatedUInt32(uint32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v);
+ }
+
+ inline void JSValuePtr::mark()
+ {
+ asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
+ }
+
+ inline bool JSValuePtr::marked() const
+ {
+ return JSImmediate::isImmediate(asValue()) || asCell()->marked();
+ }
+
+ inline JSValuePtr JSValuePtr::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType);
+ }
+
+ inline bool JSValuePtr::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& value)
+ {
+ if (JSImmediate::isImmediate(asValue())) {
+ number = JSImmediate::toDouble(asValue());
+ value = asValue();
+ return true;
+ }
+ return asCell()->getPrimitiveNumber(exec, number, value);
+ }
+
+ inline bool JSValuePtr::toBoolean(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec);
+ }
+
+ ALWAYS_INLINE double JSValuePtr::toNumber(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec);
+ }
+
+ inline UString JSValuePtr::toString(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec);
+ }
+
+ inline JSObject* JSValuePtr::toObject(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec);
+ }
+
+ inline JSObject* JSValuePtr::toThisObject(ExecState* exec) const
+ {
+ if (UNLIKELY(JSImmediate::isImmediate(asValue())))
+ return JSImmediate::toThisObject(asValue(), exec);
+ return asCell()->toThisObject(exec);
+ }
+
+ inline bool JSValuePtr::needsThisConversion() const
+ {
+ if (UNLIKELY(JSImmediate::isImmediate(asValue())))
+ return true;
+ return asCell()->structure()->typeInfo().needsThisConversion();
+ }
+
+ inline UString JSValuePtr::toThisString(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec);
+ }
+
+ inline JSValuePtr JSValuePtr::getJSNumber()
+ {
+ return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber();
+ }
+
+} // namespace JSC
+
+#endif // JSCell_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSFunction.h"
+
+#include "CodeBlock.h"
+#include "CommonIdentifiers.h"
+#include "CallFrame.h"
+#include "FunctionPrototype.h"
+#include "JSGlobalObject.h"
+#include "Interpreter.h"
+#include "ObjectPrototype.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "ScopeChainMark.h"
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSFunction);
+
+const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
+
+JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode)
+ : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name)
+ , m_body(body)
+ , m_scopeChain(scopeChainNode)
+{
+}
+
+JSFunction::~JSFunction()
+{
+#if ENABLE(JIT)
+ // JIT code for other functions may have had calls linked directly to the code for this function; these links
+ // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
+ // this memory is freed and may be reused (potentially for another, different JSFunction).
+ if (m_body && m_body->isGenerated())
+ m_body->generatedBytecode().unlinkCallers();
+#endif
+}
+
+void JSFunction::mark()
+{
+ Base::mark();
+ m_body->mark();
+ m_scopeChain.mark();
+}
+
+CallType JSFunction::getCallData(CallData& callData)
+{
+ callData.js.functionBody = m_body.get();
+ callData.js.scopeChain = m_scopeChain.node();
+ return CallTypeJS;
+}
+
+JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args)
+{
+ return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot());
+}
+
+JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return exec->interpreter()->retrieveArguments(exec, thisObj);
+}
+
+JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return exec->interpreter()->retrieveCaller(exec, thisObj);
+}
+
+JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return jsNumber(exec, thisObj->m_body->parameterCount());
+}
+
+bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().prototype) {
+ JSValuePtr* location = getDirectLocation(propertyName);
+
+ if (!location) {
+ JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure());
+ prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
+ putDirect(exec->propertyNames().prototype, prototype, DontDelete);
+ location = getDirectLocation(propertyName);
+ }
+
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ }
+
+ if (propertyName == exec->propertyNames().arguments) {
+ slot.setCustom(this, argumentsGetter);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().caller) {
+ slot.setCustom(this, callerGetter);
+ return true;
+ }
+
+ return Base::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ return;
+ Base::put(exec, propertyName, value, slot);
+}
+
+bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ return false;
+ return Base::deleteProperty(exec, propertyName);
+}
+
+// ECMA 13.2.2 [[Construct]]
+ConstructType JSFunction::getConstructData(ConstructData& constructData)
+{
+ constructData.js.functionBody = m_body.get();
+ constructData.js.scopeChain = m_scopeChain.node();
+ return ConstructTypeJS;
+}
+
+JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
+{
+ Structure* structure;
+ JSValuePtr prototype = get(exec, exec->propertyNames().prototype);
+ if (prototype.isObject())
+ structure = asObject(prototype)->inheritorID();
+ else
+ structure = exec->lexicalGlobalObject()->emptyObjectStructure();
+ JSObject* thisObj = new (exec) JSObject(structure);
+
+ JSValuePtr result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot());
+ if (exec->hadException() || !result.isObject())
+ return thisObj;
+ return asObject(result);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSFunction_h
+#define JSFunction_h
+
+#include "InternalFunction.h"
+#include "JSVariableObject.h"
+#include "SymbolTable.h"
+#include "Nodes.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+ class FunctionBodyNode;
+ class FunctionPrototype;
+ class JSActivation;
+ class JSGlobalObject;
+
+ class JSFunction : public InternalFunction {
+ friend class JIT;
+ friend class Interpreter;
+
+ typedef InternalFunction Base;
+
+ JSFunction(PassRefPtr<Structure> structure)
+ : InternalFunction(structure)
+ , m_scopeChain(NoScopeChain())
+ {
+ }
+
+ public:
+ JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
+ ~JSFunction();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ JSObject* construct(ExecState*, const ArgList&);
+ JSValuePtr call(ExecState*, JSValuePtr thisValue, const ArgList&);
+
+ void setScope(const ScopeChain& scopeChain) { m_scopeChain = scopeChain; }
+ ScopeChain& scope() { return m_scopeChain; }
+
+ void setBody(FunctionBodyNode* body) { m_body = body; }
+ void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; }
+ FunctionBodyNode* body() const { return m_body.get(); }
+
+ virtual void mark();
+
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValuePtr callerGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValuePtr lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ RefPtr<FunctionBodyNode> m_body;
+ ScopeChain m_scopeChain;
+ };
+
+ JSFunction* asFunction(JSValuePtr);
+
+ inline JSFunction* asFunction(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&JSFunction::info));
+ return static_cast<JSFunction*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // JSFunction_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSGlobalData.h"
+
+#include "ArgList.h"
+#include "Collector.h"
+#include "CommonIdentifiers.h"
+#include "FunctionConstructor.h"
+#include "Interpreter.h"
+#include "JSActivation.h"
+#include "JSClassRef.h"
+#include "JSLock.h"
+#include "JSNotAnObject.h"
+#include "JSStaticScopeObject.h"
+#include "Parser.h"
+#include "Lexer.h"
+#include "Lookup.h"
+#include "Nodes.h"
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <wtf/Threading.h>
+#endif
+
+#if PLATFORM(MAC)
+#include "ProfilerServer.h"
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+extern const HashTable arrayTable;
+extern const HashTable dateTable;
+extern const HashTable mathTable;
+extern const HashTable numberTable;
+extern const HashTable regExpTable;
+extern const HashTable regExpConstructorTable;
+extern const HashTable stringTable;
+
+JSGlobalData::JSGlobalData(bool isShared)
+ : initializingLazyNumericCompareFunction(false)
+ , interpreter(new Interpreter)
+ , exception(noValue())
+ , arrayTable(new HashTable(JSC::arrayTable))
+ , dateTable(new HashTable(JSC::dateTable))
+ , mathTable(new HashTable(JSC::mathTable))
+ , numberTable(new HashTable(JSC::numberTable))
+ , regExpTable(new HashTable(JSC::regExpTable))
+ , regExpConstructorTable(new HashTable(JSC::regExpConstructorTable))
+ , stringTable(new HashTable(JSC::stringTable))
+ , activationStructure(JSActivation::createStructure(jsNull()))
+ , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
+ , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
+ , stringStructure(JSString::createStructure(jsNull()))
+ , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
+ , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ , numberStructure(JSNumberCell::createStructure(jsNull()))
+#endif
+ , identifierTable(createIdentifierTable())
+ , propertyNames(new CommonIdentifiers(this))
+ , emptyList(new ArgList)
+ , newParserObjects(0)
+ , parserObjectExtraRefCounts(0)
+ , lexer(new Lexer(this))
+ , parser(new Parser)
+ , head(0)
+ , dynamicGlobalObject(0)
+ , isSharedInstance(isShared)
+ , clientData(0)
+ , scopeNodeBeingReparsed(0)
+ , heap(this)
+{
+#if PLATFORM(MAC)
+ startProfilerServerIfNeeded();
+#endif
+ interpreter->initialize(this);
+}
+
+JSGlobalData::~JSGlobalData()
+{
+ // By the time this is destroyed, heap.destroy() must already have been called.
+
+ delete interpreter;
+#ifndef NDEBUG
+ // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
+ interpreter = 0;
+#endif
+
+ arrayTable->deleteTable();
+ dateTable->deleteTable();
+ mathTable->deleteTable();
+ numberTable->deleteTable();
+ regExpTable->deleteTable();
+ regExpConstructorTable->deleteTable();
+ stringTable->deleteTable();
+ delete arrayTable;
+ delete dateTable;
+ delete mathTable;
+ delete numberTable;
+ delete regExpTable;
+ delete regExpConstructorTable;
+ delete stringTable;
+
+ delete parser;
+ delete lexer;
+
+ deleteAllValues(opaqueJSClassData);
+
+ delete emptyList;
+
+ delete propertyNames;
+ deleteIdentifierTable(identifierTable);
+
+ delete newParserObjects;
+ delete parserObjectExtraRefCounts;
+
+ delete clientData;
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::create()
+{
+ return adoptRef(new JSGlobalData);
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
+{
+#ifndef NDEBUG
+ Structure::startIgnoringLeaks();
+ RefPtr<JSGlobalData> data = create();
+ Structure::stopIgnoringLeaks();
+ return data.release();
+#else
+ return create();
+#endif
+}
+
+bool JSGlobalData::sharedInstanceExists()
+{
+ return sharedInstanceInternal();
+}
+
+JSGlobalData& JSGlobalData::sharedInstance()
+{
+ JSGlobalData*& instance = sharedInstanceInternal();
+ if (!instance) {
+ instance = new JSGlobalData(true);
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ instance->makeUsableFromMultipleThreads();
+#endif
+ }
+ return *instance;
+}
+
+JSGlobalData*& JSGlobalData::sharedInstanceInternal()
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+ static JSGlobalData* sharedInstance;
+ return sharedInstance;
+}
+
+// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
+const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
+{
+ if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
+ initializingLazyNumericCompareFunction = true;
+ RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
+ RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get());
+ lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
+ initializingLazyNumericCompareFunction = false;
+ }
+
+ return lazyNumericCompareFunction;
+}
+
+JSGlobalData::ClientData::~ClientData()
+{
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSGlobalData_h
+#define JSGlobalData_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include "Collector.h"
+#include "ExecutableAllocator.h"
+#include "SmallStrings.h"
+#include "JSValue.h"
+
+struct OpaqueJSClass;
+struct OpaqueJSClassContextData;
+
+namespace JSC {
+
+ class ArgList;
+ class CommonIdentifiers;
+ class Heap;
+ class IdentifierTable;
+ class Instruction;
+ class Interpreter;
+ class JSGlobalObject;
+ class JSObject;
+ class Lexer;
+ class Parser;
+ class ParserRefCounted;
+ class ScopeNode;
+ class Structure;
+ class UString;
+ struct HashTable;
+
+ class JSGlobalData : public RefCounted<JSGlobalData> {
+ public:
+ static bool sharedInstanceExists();
+ static JSGlobalData& sharedInstance();
+
+ static PassRefPtr<JSGlobalData> create();
+ static PassRefPtr<JSGlobalData> createLeaked();
+ ~JSGlobalData();
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ // Will start tracking threads that use the heap, which is resource-heavy.
+ void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); }
+#endif
+
+ const Vector<Instruction>& numericCompareFunction(ExecState*);
+ Vector<Instruction> lazyNumericCompareFunction;
+ bool initializingLazyNumericCompareFunction;
+
+ Interpreter* interpreter;
+
+ JSValuePtr exception;
+#if ENABLE(JIT)
+ void* exceptionLocation;
+#endif
+
+ const HashTable* arrayTable;
+ const HashTable* dateTable;
+ const HashTable* mathTable;
+ const HashTable* numberTable;
+ const HashTable* regExpTable;
+ const HashTable* regExpConstructorTable;
+ const HashTable* stringTable;
+
+ RefPtr<Structure> activationStructure;
+ RefPtr<Structure> interruptedExecutionErrorStructure;
+ RefPtr<Structure> staticScopeStructure;
+ RefPtr<Structure> stringStructure;
+ RefPtr<Structure> notAnObjectErrorStubStructure;
+ RefPtr<Structure> notAnObjectStructure;
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ RefPtr<Structure> numberStructure;
+#endif
+
+ IdentifierTable* identifierTable;
+ CommonIdentifiers* propertyNames;
+ const ArgList* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
+
+ SmallStrings smallStrings;
+
+ HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
+
+ HashSet<ParserRefCounted*>* newParserObjects;
+ HashCountedSet<ParserRefCounted*>* parserObjectExtraRefCounts;
+
+ Lexer* lexer;
+ Parser* parser;
+
+ JSGlobalObject* head;
+ JSGlobalObject* dynamicGlobalObject;
+
+ bool isSharedInstance;
+
+ struct ClientData {
+ virtual ~ClientData() = 0;
+ };
+
+ ClientData* clientData;
+
+ HashSet<JSObject*> arrayVisitedElements;
+
+ ScopeNode* scopeNodeBeingReparsed;
+
+ Heap heap;
+#if ENABLE(ASSEMBLER)
+ PassRefPtr<ExecutablePool> poolForSize(size_t n) { return m_executableAllocator.poolForSize(n); }
+#endif
+ private:
+ JSGlobalData(bool isShared = false);
+#if ENABLE(ASSEMBLER)
+ ExecutableAllocator m_executableAllocator;
+#endif
+
+ static JSGlobalData*& sharedInstanceInternal();
+ };
+
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSGlobalObject.h"
+
+#include "JSCallbackConstructor.h"
+#include "JSCallbackFunction.h"
+#include "JSCallbackObject.h"
+
+#include "Arguments.h"
+#include "ArrayConstructor.h"
+#include "ArrayPrototype.h"
+#include "BooleanConstructor.h"
+#include "BooleanPrototype.h"
+#include "CodeBlock.h"
+#include "DateConstructor.h"
+#include "DatePrototype.h"
+#include "ErrorConstructor.h"
+#include "ErrorPrototype.h"
+#include "FunctionConstructor.h"
+#include "FunctionPrototype.h"
+#include "GlobalEvalFunction.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSLock.h"
+#include "Interpreter.h"
+#include "MathObject.h"
+#include "NativeErrorConstructor.h"
+#include "NativeErrorPrototype.h"
+#include "NumberConstructor.h"
+#include "NumberPrototype.h"
+#include "ObjectConstructor.h"
+#include "ObjectPrototype.h"
+#include "Profiler.h"
+#include "PrototypeFunction.h"
+#include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "ScopeChainMark.h"
+#include "StringConstructor.h"
+#include "StringPrototype.h"
+#include "Debugger.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject);
+
+// Default number of ticks before a timeout check should be done.
+static const int initialTickCountThreshold = 255;
+
+// Preferred number of milliseconds between each timeout check
+static const int preferredScriptCheckTimeInterval = 1000;
+
+static inline void markIfNeeded(JSValuePtr v)
+{
+ if (v && !v.marked())
+ v.mark();
+}
+
+static inline void markIfNeeded(const RefPtr<Structure>& s)
+{
+ if (s)
+ s->mark();
+}
+
+JSGlobalObject::~JSGlobalObject()
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+
+ if (d()->debugger)
+ d()->debugger->detach(this);
+
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (UNLIKELY(*profiler != 0)) {
+ (*profiler)->stopProfiling(globalExec(), UString());
+ }
+
+ d()->next->d()->prev = d()->prev;
+ d()->prev->d()->next = d()->next;
+ JSGlobalObject*& headObject = head();
+ if (headObject == this)
+ headObject = d()->next;
+ if (headObject == this)
+ headObject = 0;
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->clearGlobalObject();
+
+ RegisterFile& registerFile = globalData()->interpreter->registerFile();
+ if (registerFile.globalObject() == this) {
+ registerFile.setGlobalObject(0);
+ registerFile.setNumGlobals(0);
+ }
+ delete d();
+}
+
+void JSGlobalObject::init(JSObject* thisValue)
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+
+ d()->globalData = Heap::heap(this)->globalData();
+ d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), thisValue);
+
+ JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
+
+ if (JSGlobalObject*& headObject = head()) {
+ d()->prev = headObject;
+ d()->next = headObject->d()->next;
+ headObject->d()->next->d()->prev = this;
+ headObject->d()->next = this;
+ } else
+ headObject = d()->next = d()->prev = this;
+
+ d()->recursion = 0;
+ d()->debugger = 0;
+
+ d()->profileGroup = 0;
+
+ reset(prototype());
+}
+
+void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePut(propertyName, value))
+ return;
+ JSVariableObject::put(exec, propertyName, value, slot);
+}
+
+void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ JSValuePtr valueBefore = getDirect(propertyName);
+ PutPropertySlot slot;
+ JSVariableObject::put(exec, propertyName, value, slot);
+ if (!valueBefore) {
+ JSValuePtr valueAfter = getDirect(propertyName);
+ if (valueAfter)
+ putDirect(propertyName, valueAfter, attributes);
+ }
+}
+
+void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
+{
+ PropertySlot slot;
+ if (!symbolTableGet(propertyName, slot))
+ JSVariableObject::defineGetter(exec, propertyName, getterFunc);
+}
+
+void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
+{
+ PropertySlot slot;
+ if (!symbolTableGet(propertyName, slot))
+ JSVariableObject::defineSetter(exec, propertyName, setterFunc);
+}
+
+static inline JSObject* lastInPrototypeChain(JSObject* object)
+{
+ JSObject* o = object;
+ while (o->prototype().isObject())
+ o = asObject(o->prototype());
+ return o;
+}
+
+void JSGlobalObject::reset(JSValuePtr prototype)
+{
+ ExecState* exec = JSGlobalObject::globalExec();
+
+ // Prototypes
+
+ d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created.
+ d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype);
+ d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get());
+ d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get());
+ d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype);
+
+ d()->emptyObjectStructure = d()->objectPrototype->inheritorID();
+
+ d()->functionStructure = JSFunction::createStructure(d()->functionPrototype);
+ d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype);
+ d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype);
+ d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype);
+ d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructure(d()->objectPrototype);
+
+ d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructure(d()->objectPrototype));
+ d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype);
+ d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype);
+
+ d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructure(d()->objectPrototype));
+ d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype);
+
+ d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype);
+
+ d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype);
+
+ d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructure(d()->objectPrototype));
+ d()->dateStructure = DateInstance::createStructure(d()->datePrototype);
+
+ d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype);
+
+ ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
+
+ RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype);
+
+ NativeErrorPrototype* evalErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "EvalError", "EvalError");
+ NativeErrorPrototype* rangeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "RangeError", "RangeError");
+ NativeErrorPrototype* referenceErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "ReferenceError", "ReferenceError");
+ NativeErrorPrototype* syntaxErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "SyntaxError", "SyntaxError");
+ NativeErrorPrototype* typeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "TypeError", "TypeError");
+ NativeErrorPrototype* URIErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "URIError", "URIError");
+
+ // Constructors
+
+ JSValuePtr objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
+ JSValuePtr functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
+ JSValuePtr arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
+ JSValuePtr stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
+ JSValuePtr booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
+ JSValuePtr numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
+ JSValuePtr dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
+
+ d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype);
+
+ d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructure(d()->functionPrototype), errorPrototype);
+
+ RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype);
+
+ d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, evalErrorPrototype);
+ d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, rangeErrorPrototype);
+ d()->referenceErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, referenceErrorPrototype);
+ d()->syntaxErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, syntaxErrorPrototype);
+ d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, typeErrorPrototype);
+ d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype);
+
+ d()->objectPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
+ d()->functionPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
+ d()->arrayPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
+ d()->booleanPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
+ d()->stringPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
+ d()->numberPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
+ d()->datePrototype->putDirectWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
+ d()->regExpPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
+ errorPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
+
+ evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum);
+ rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum);
+ referenceErrorPrototype->putDirect(exec->propertyNames().constructor, d()->referenceErrorConstructor, DontEnum);
+ syntaxErrorPrototype->putDirect(exec->propertyNames().constructor, d()->syntaxErrorConstructor, DontEnum);
+ typeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->typeErrorConstructor, DontEnum);
+ URIErrorPrototype->putDirect(exec->propertyNames().constructor, d()->URIErrorConstructor, DontEnum);
+
+ // Set global constructors
+
+ // FIXME: These properties could be handled by a static hash table.
+
+ putDirectWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
+
+ // Set global values.
+ GlobalPropertyInfo staticGlobals[] = {
+ GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete)
+ };
+
+ addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
+
+ // Set global functions.
+
+ d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructure(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this);
+ putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum);
+#ifndef NDEBUG
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum);
+#endif
+
+ resetPrototype(prototype);
+}
+
+// Set prototype, and also insert the object prototype at the end of the chain.
+void JSGlobalObject::resetPrototype(JSValuePtr prototype)
+{
+ setPrototype(prototype);
+ lastInPrototypeChain(this)->setPrototype(d()->objectPrototype);
+}
+
+void JSGlobalObject::setTimeoutTime(unsigned timeoutTime)
+{
+ globalData()->interpreter->setTimeoutTime(timeoutTime);
+}
+
+void JSGlobalObject::startTimeoutCheck()
+{
+ globalData()->interpreter->startTimeoutCheck();
+}
+
+void JSGlobalObject::stopTimeoutCheck()
+{
+ globalData()->interpreter->stopTimeoutCheck();
+}
+
+void JSGlobalObject::mark()
+{
+ JSVariableObject::mark();
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->mark();
+
+ RegisterFile& registerFile = globalData()->interpreter->registerFile();
+ if (registerFile.globalObject() == this)
+ registerFile.markGlobals(&globalData()->heap);
+
+ markIfNeeded(d()->regExpConstructor);
+ markIfNeeded(d()->errorConstructor);
+ markIfNeeded(d()->evalErrorConstructor);
+ markIfNeeded(d()->rangeErrorConstructor);
+ markIfNeeded(d()->referenceErrorConstructor);
+ markIfNeeded(d()->syntaxErrorConstructor);
+ markIfNeeded(d()->typeErrorConstructor);
+ markIfNeeded(d()->URIErrorConstructor);
+
+ markIfNeeded(d()->evalFunction);
+
+ markIfNeeded(d()->objectPrototype);
+ markIfNeeded(d()->functionPrototype);
+ markIfNeeded(d()->arrayPrototype);
+ markIfNeeded(d()->booleanPrototype);
+ markIfNeeded(d()->stringPrototype);
+ markIfNeeded(d()->numberPrototype);
+ markIfNeeded(d()->datePrototype);
+ markIfNeeded(d()->regExpPrototype);
+
+ markIfNeeded(d()->errorStructure);
+
+ // No need to mark the other structures, because their prototypes are all
+ // guaranteed to be referenced elsewhere.
+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t size = d()->registerArraySize;
+ for (size_t i = 0; i < size; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+}
+
+ExecState* JSGlobalObject::globalExec()
+{
+ return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize);
+}
+
+bool JSGlobalObject::isDynamicScope() const
+{
+ return true;
+}
+
+void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
+{
+ ASSERT(!d()->registerArray);
+ ASSERT(!d()->registerArraySize);
+
+ int numGlobals = registerFile.numGlobals();
+ if (!numGlobals) {
+ d()->registers = 0;
+ return;
+ }
+
+ Register* registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals);
+ setRegisters(registerArray + numGlobals, registerArray, numGlobals);
+}
+
+void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
+{
+ JSGlobalObject* lastGlobalObject = registerFile.globalObject();
+ if (lastGlobalObject && lastGlobalObject != this)
+ lastGlobalObject->copyGlobalsFrom(registerFile);
+
+ registerFile.setGlobalObject(this);
+ registerFile.setNumGlobals(symbolTable().size());
+
+ if (d()->registerArray) {
+ memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
+ setRegisters(registerFile.start(), 0, 0);
+ }
+}
+
+void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
+{
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocate(size);
+#else
+ return globalData->heap.allocate(size);
+#endif
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSGlobalObject_h
+#define JSGlobalObject_h
+
+#include "JSGlobalData.h"
+#include "JSVariableObject.h"
+#include "NumberPrototype.h"
+#include "StringPrototype.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class ArrayPrototype;
+ class BooleanPrototype;
+ class DatePrototype;
+ class Debugger;
+ class ErrorConstructor;
+ class FunctionPrototype;
+ class GlobalEvalFunction;
+ class NativeErrorConstructor;
+ class ProgramCodeBlock;
+ class RegExpConstructor;
+ class RegExpPrototype;
+ class RegisterFile;
+
+ struct ActivationStackNode;
+ struct HashTable;
+
+ typedef Vector<ExecState*, 16> ExecStateStack;
+
+ class JSGlobalObject : public JSVariableObject {
+ protected:
+ using JSVariableObject::JSVariableObjectData;
+
+ struct JSGlobalObjectData : public JSVariableObjectData {
+ JSGlobalObjectData()
+ : JSVariableObjectData(&symbolTable, 0)
+ , registerArraySize(0)
+ , globalScopeChain(NoScopeChain())
+ , regExpConstructor(0)
+ , errorConstructor(0)
+ , evalErrorConstructor(0)
+ , rangeErrorConstructor(0)
+ , referenceErrorConstructor(0)
+ , syntaxErrorConstructor(0)
+ , typeErrorConstructor(0)
+ , URIErrorConstructor(0)
+ , evalFunction(0)
+ , objectPrototype(0)
+ , functionPrototype(0)
+ , arrayPrototype(0)
+ , booleanPrototype(0)
+ , stringPrototype(0)
+ , numberPrototype(0)
+ , datePrototype(0)
+ , regExpPrototype(0)
+ {
+ }
+
+ virtual ~JSGlobalObjectData()
+ {
+ }
+
+ size_t registerArraySize;
+
+ JSGlobalObject* next;
+ JSGlobalObject* prev;
+
+ Debugger* debugger;
+
+ ScopeChain globalScopeChain;
+ Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
+
+ int recursion;
+
+ RegExpConstructor* regExpConstructor;
+ ErrorConstructor* errorConstructor;
+ NativeErrorConstructor* evalErrorConstructor;
+ NativeErrorConstructor* rangeErrorConstructor;
+ NativeErrorConstructor* referenceErrorConstructor;
+ NativeErrorConstructor* syntaxErrorConstructor;
+ NativeErrorConstructor* typeErrorConstructor;
+ NativeErrorConstructor* URIErrorConstructor;
+
+ GlobalEvalFunction* evalFunction;
+
+ ObjectPrototype* objectPrototype;
+ FunctionPrototype* functionPrototype;
+ ArrayPrototype* arrayPrototype;
+ BooleanPrototype* booleanPrototype;
+ StringPrototype* stringPrototype;
+ NumberPrototype* numberPrototype;
+ DatePrototype* datePrototype;
+ RegExpPrototype* regExpPrototype;
+
+ RefPtr<Structure> argumentsStructure;
+ RefPtr<Structure> arrayStructure;
+ RefPtr<Structure> booleanObjectStructure;
+ RefPtr<Structure> callbackConstructorStructure;
+ RefPtr<Structure> callbackFunctionStructure;
+ RefPtr<Structure> callbackObjectStructure;
+ RefPtr<Structure> dateStructure;
+ RefPtr<Structure> emptyObjectStructure;
+ RefPtr<Structure> errorStructure;
+ RefPtr<Structure> functionStructure;
+ RefPtr<Structure> numberObjectStructure;
+ RefPtr<Structure> prototypeFunctionStructure;
+ RefPtr<Structure> regExpMatchesArrayStructure;
+ RefPtr<Structure> regExpStructure;
+ RefPtr<Structure> stringObjectStructure;
+
+ SymbolTable symbolTable;
+ unsigned profileGroup;
+
+ RefPtr<JSGlobalData> globalData;
+
+ HashSet<ProgramCodeBlock*> codeBlocks;
+ };
+
+ public:
+ void* operator new(size_t, JSGlobalData*);
+
+ explicit JSGlobalObject()
+ : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData)
+ {
+ init(this);
+ }
+
+ protected:
+ JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
+ : JSVariableObject(structure, data)
+ {
+ init(thisValue);
+ }
+
+ public:
+ virtual ~JSGlobalObject();
+
+ virtual void mark();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes);
+
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
+
+ // Linked list of all global objects that use the same JSGlobalData.
+ JSGlobalObject*& head() { return d()->globalData->head; }
+ JSGlobalObject* next() { return d()->next; }
+
+ // The following accessors return pristine values, even if a script
+ // replaces the global object's associated property.
+
+ RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
+
+ ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
+ NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
+ NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
+ NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
+ NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
+ NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
+ NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
+
+ GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
+
+ ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
+ FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
+ ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
+ BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
+ StringPrototype* stringPrototype() const { return d()->stringPrototype; }
+ NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
+ DatePrototype* datePrototype() const { return d()->datePrototype; }
+ RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
+
+ Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
+ Structure* arrayStructure() const { return d()->arrayStructure.get(); }
+ Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
+ Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
+ Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
+ Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
+ Structure* dateStructure() const { return d()->dateStructure.get(); }
+ Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
+ Structure* errorStructure() const { return d()->errorStructure.get(); }
+ Structure* functionStructure() const { return d()->functionStructure.get(); }
+ Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
+ Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
+ Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
+ Structure* regExpStructure() const { return d()->regExpStructure.get(); }
+ Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
+
+ void setProfileGroup(unsigned value) { d()->profileGroup = value; }
+ unsigned profileGroup() const { return d()->profileGroup; }
+
+ void setTimeoutTime(unsigned timeoutTime);
+ void startTimeoutCheck();
+ void stopTimeoutCheck();
+
+ Debugger* debugger() const { return d()->debugger; }
+ void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
+
+ virtual bool supportsProfiling() const { return false; }
+
+ int recursion() { return d()->recursion; }
+ void incRecursion() { ++d()->recursion; }
+ void decRecursion() { --d()->recursion; }
+
+ ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
+
+ virtual bool isGlobalObject() const { return true; }
+
+ virtual ExecState* globalExec();
+
+ virtual bool shouldInterruptScriptBeforeTimeout() const { return false; }
+ virtual bool shouldInterruptScript() const { return true; }
+
+ virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
+
+ virtual bool isDynamicScope() const;
+
+ HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+
+ void copyGlobalsFrom(RegisterFile&);
+ void copyGlobalsTo(RegisterFile&);
+
+ void resetPrototype(JSValuePtr prototype);
+
+ JSGlobalData* globalData() { return d()->globalData.get(); }
+ JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ struct GlobalPropertyInfo {
+ GlobalPropertyInfo(const Identifier& i, JSValuePtr v, unsigned a)
+ : identifier(i)
+ , value(v)
+ , attributes(a)
+ {
+ }
+
+ const Identifier identifier;
+ JSValuePtr value;
+ unsigned attributes;
+ };
+ void addStaticGlobals(GlobalPropertyInfo*, int count);
+
+ private:
+ // FIXME: Fold reset into init.
+ void init(JSObject* thisValue);
+ void reset(JSValuePtr prototype);
+
+ void setRegisters(Register* registers, Register* registerArray, size_t count);
+
+ void* operator new(size_t); // can only be allocated with JSGlobalData
+ };
+
+ JSGlobalObject* asGlobalObject(JSValuePtr);
+
+ inline JSGlobalObject* asGlobalObject(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->isGlobalObject());
+ return static_cast<JSGlobalObject*>(asObject(value));
+ }
+
+ inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
+ {
+ JSVariableObject::setRegisters(registers, registerArray);
+ d()->registerArraySize = count;
+ }
+
+ inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
+ {
+ size_t oldSize = d()->registerArraySize;
+ size_t newSize = oldSize + count;
+ Register* registerArray = new Register[newSize];
+ if (d()->registerArray)
+ memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
+ setRegisters(registerArray + newSize, registerArray, newSize);
+
+ for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
+ GlobalPropertyInfo& global = globals[i];
+ ASSERT(global.attributes & DontDelete);
+ SymbolTableEntry newEntry(index, global.attributes);
+ symbolTable().add(global.identifier.ustring().rep(), newEntry);
+ registerAt(index) = global.value;
+ }
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ return symbolTableGet(propertyName, slot);
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
+ return true;
+ return symbolTableGet(propertyName, slot, slotIsWriteable);
+ }
+
+ inline JSGlobalObject* ScopeChainNode::globalObject() const
+ {
+ const ScopeChainNode* n = this;
+ while (n->next)
+ n = n->next;
+ return asGlobalObject(n->object);
+ }
+
+ inline JSValuePtr Structure::prototypeForLookup(ExecState* exec) const
+ {
+ if (typeInfo().type() == ObjectType)
+ return m_prototype;
+
+ if (typeInfo().type() == StringType)
+ return exec->lexicalGlobalObject()->stringPrototype();
+
+ ASSERT(typeInfo().type() == NumberType);
+ return exec->lexicalGlobalObject()->numberPrototype();
+ }
+
+ inline StructureChain* Structure::prototypeChain(ExecState* exec) const
+ {
+ // We cache our prototype chain so our clients can share it.
+ if (!isValid(exec, m_cachedPrototypeChain.get())) {
+ JSValuePtr prototype = prototypeForLookup(exec);
+ m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
+ }
+ return m_cachedPrototypeChain.get();
+ }
+
+ inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
+ {
+ if (!cachedPrototypeChain)
+ return false;
+
+ JSValuePtr prototype = prototypeForLookup(exec);
+ RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
+ while(*cachedStructure && !prototype.isNull()) {
+ if (asObject(prototype)->structure() != *cachedStructure)
+ return false;
+ ++cachedStructure;
+ prototype = asObject(prototype)->prototype();
+ }
+ return prototype.isNull() && !*cachedStructure;
+ }
+
+ inline JSGlobalObject* ExecState::dynamicGlobalObject()
+ {
+ if (this == lexicalGlobalObject()->globalExec())
+ return lexicalGlobalObject();
+
+ // For any ExecState that's not a globalExec, the
+ // dynamic global object must be set since code is running
+ ASSERT(globalData().dynamicGlobalObject);
+ return globalData().dynamicGlobalObject;
+ }
+
+ class DynamicGlobalObjectScope : Noncopyable {
+ public:
+ DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
+ : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
+ , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
+ {
+ m_dynamicGlobalObjectSlot = dynamicGlobalObject;
+ }
+
+ ~DynamicGlobalObjectScope()
+ {
+ m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
+ }
+
+ private:
+ JSGlobalObject*& m_dynamicGlobalObjectSlot;
+ JSGlobalObject* m_savedDynamicGlobalObject;
+ };
+
+} // namespace JSC
+
+#endif // JSGlobalObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSGlobalObjectFunctions.h"
+
+#include "CallFrame.h"
+#include "GlobalEvalFunction.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "Interpreter.h"
+#include "Parser.h"
+#include "dtoa.h"
+#include "Lexer.h"
+#include "Nodes.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace JSC {
+
+static JSValuePtr encode(ExecState* exec, const ArgList& args, const char* doNotEscape)
+{
+ UString str = args.at(exec, 0).toString(exec);
+ CString cstr = str.UTF8String(true);
+ if (!cstr.c_str())
+ return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
+
+ UString result = "";
+ const char* p = cstr.c_str();
+ for (size_t k = 0; k < cstr.size(); k++, p++) {
+ char c = *p;
+ if (c && strchr(doNotEscape, c))
+ result.append(c);
+ else {
+ char tmp[4];
+ snprintf(tmp, sizeof(tmp), "%%%02X", static_cast<unsigned char>(c));
+ result += tmp;
+ }
+ }
+ return jsString(exec, result);
+}
+
+static JSValuePtr decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
+{
+ UString result = "";
+ UString str = args.at(exec, 0).toString(exec);
+ int k = 0;
+ int len = str.size();
+ const UChar* d = str.data();
+ UChar u = 0;
+ while (k < len) {
+ const UChar* p = d + k;
+ UChar c = *p;
+ if (c == '%') {
+ int charLen = 0;
+ if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
+ const char b0 = Lexer::convertHex(p[1], p[2]);
+ const int sequenceLen = UTF8SequenceLength(b0);
+ if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
+ charLen = sequenceLen * 3;
+ char sequence[5];
+ sequence[0] = b0;
+ for (int i = 1; i < sequenceLen; ++i) {
+ const UChar* q = p + i * 3;
+ if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
+ sequence[i] = Lexer::convertHex(q[1], q[2]);
+ else {
+ charLen = 0;
+ break;
+ }
+ }
+ if (charLen != 0) {
+ sequence[sequenceLen] = 0;
+ const int character = decodeUTF8Sequence(sequence);
+ if (character < 0 || character >= 0x110000)
+ charLen = 0;
+ else if (character >= 0x10000) {
+ // Convert to surrogate pair.
+ result.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
+ u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
+ } else
+ u = static_cast<UChar>(character);
+ }
+ }
+ }
+ if (charLen == 0) {
+ if (strict)
+ return throwError(exec, URIError);
+ // The only case where we don't use "strict" mode is the "unescape" function.
+ // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
+ if (k <= len - 6 && p[1] == 'u'
+ && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
+ && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
+ charLen = 6;
+ u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);
+ }
+ }
+ if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
+ c = u;
+ k += charLen - 1;
+ }
+ }
+ k++;
+ result.append(c);
+ }
+ return jsString(exec, result);
+}
+
+bool isStrWhiteSpace(UChar c)
+{
+ switch (c) {
+ case 0x0009:
+ case 0x000A:
+ case 0x000B:
+ case 0x000C:
+ case 0x000D:
+ case 0x0020:
+ case 0x00A0:
+ case 0x2028:
+ case 0x2029:
+ return true;
+ default:
+ return c > 0xff && isSeparatorSpace(c);
+ }
+}
+
+static int parseDigit(unsigned short c, int radix)
+{
+ int digit = -1;
+
+ if (c >= '0' && c <= '9')
+ digit = c - '0';
+ else if (c >= 'A' && c <= 'Z')
+ digit = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'z')
+ digit = c - 'a' + 10;
+
+ if (digit >= radix)
+ return -1;
+ return digit;
+}
+
+double parseIntOverflow(const char* s, int length, int radix)
+{
+ double number = 0.0;
+ double radixMultiplier = 1.0;
+
+ for (const char* p = s + length - 1; p >= s; p--) {
+ if (radixMultiplier == Inf) {
+ if (*p != '0') {
+ number = Inf;
+ break;
+ }
+ } else {
+ int digit = parseDigit(*p, radix);
+ number += digit * radixMultiplier;
+ }
+
+ radixMultiplier *= radix;
+ }
+
+ return number;
+}
+
+static double parseInt(const UString& s, int radix)
+{
+ int length = s.size();
+ const UChar* data = s.data();
+ int p = 0;
+
+ while (p < length && isStrWhiteSpace(data[p]))
+ ++p;
+
+ double sign = 1;
+ if (p < length) {
+ if (data[p] == '+')
+ ++p;
+ else if (data[p] == '-') {
+ sign = -1;
+ ++p;
+ }
+ }
+
+ if ((radix == 0 || radix == 16) && length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) {
+ radix = 16;
+ p += 2;
+ } else if (radix == 0) {
+ if (p < length && data[p] == '0')
+ radix = 8;
+ else
+ radix = 10;
+ }
+
+ if (radix < 2 || radix > 36)
+ return NaN;
+
+ int firstDigitPosition = p;
+ bool sawDigit = false;
+ double number = 0;
+ while (p < length) {
+ int digit = parseDigit(data[p], radix);
+ if (digit == -1)
+ break;
+ sawDigit = true;
+ number *= radix;
+ number += digit;
+ ++p;
+ }
+
+ if (number >= mantissaOverflowLowerBound) {
+ if (radix == 10)
+ number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);
+ else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
+ number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);
+ }
+
+ if (!sawDigit)
+ return NaN;
+
+ return sign * number;
+}
+
+static double parseFloat(const UString& s)
+{
+ // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
+ // Need to skip any whitespace and then one + or - sign.
+ int length = s.size();
+ const UChar* data = s.data();
+ int p = 0;
+ while (p < length && isStrWhiteSpace(data[p]))
+ ++p;
+
+ if (p < length && (data[p] == '+' || data[p] == '-'))
+ ++p;
+
+ if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X'))
+ return 0;
+
+ return s.toDouble(true /*tolerant*/, false /* NaN for empty string */);
+}
+
+JSValuePtr globalFuncEval(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObject = thisValue.toThisObject(exec);
+ JSObject* unwrappedObject = thisObject->unwrappedObject();
+ if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != function)
+ return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
+
+ JSValuePtr x = args.at(exec, 0);
+ if (!x.isString())
+ return x;
+
+ UString s = x.toString(exec);
+
+ int errLine;
+ UString errMsg;
+
+ SourceCode source = makeSource(s);
+ RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+ if (!evalNode)
+ return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
+
+ return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
+}
+
+JSValuePtr globalFuncParseInt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ JSValuePtr value = args.at(exec, 0);
+ int32_t radix = args.at(exec, 1).toInt32(exec);
+
+ if (value.isNumber() && (radix == 0 || radix == 10)) {
+ if (value.isInt32Fast())
+ return value;
+ double d = value.uncheckedGetNumber();
+ if (isfinite(d))
+ return jsNumber(exec, (d > 0) ? floor(d) : ceil(d));
+ if (isnan(d) || isinf(d))
+ return jsNaN(&exec->globalData());
+ return js0();
+ }
+
+ return jsNumber(exec, parseInt(value.toString(exec), radix));
+}
+
+JSValuePtr globalFuncParseFloat(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, parseFloat(args.at(exec, 0).toString(exec)));
+}
+
+JSValuePtr globalFuncIsNaN(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsBoolean(isnan(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr globalFuncIsFinite(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ double n = args.at(exec, 0).toNumber(exec);
+ return jsBoolean(!isnan(n) && !isinf(n));
+}
+
+JSValuePtr globalFuncDecodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ static const char do_not_unescape_when_decoding_URI[] =
+ "#$&+,/:;=?@";
+
+ return decode(exec, args, do_not_unescape_when_decoding_URI, true);
+}
+
+JSValuePtr globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return decode(exec, args, "", true);
+}
+
+JSValuePtr globalFuncEncodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ static const char do_not_escape_when_encoding_URI[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!#$&'()*+,-./:;=?@_~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI);
+}
+
+JSValuePtr globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ static const char do_not_escape_when_encoding_URI_component[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!'()*-._~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI_component);
+}
+
+JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ static const char do_not_escape[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "*+-./@_";
+
+ UString result = "";
+ UString s;
+ UString str = args.at(exec, 0).toString(exec);
+ const UChar* c = str.data();
+ for (int k = 0; k < str.size(); k++, c++) {
+ int u = c[0];
+ if (u > 255) {
+ char tmp[7];
+ snprintf(tmp, sizeof(tmp), "%%u%04X", u);
+ s = UString(tmp);
+ } else if (u != 0 && strchr(do_not_escape, static_cast<char>(u)))
+ s = UString(c, 1);
+ else {
+ char tmp[4];
+ snprintf(tmp, sizeof(tmp), "%%%02X", u);
+ s = UString(tmp);
+ }
+ result += s;
+ }
+
+ return jsString(exec, result);
+}
+
+JSValuePtr globalFuncUnescape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ UString result = "";
+ UString str = args.at(exec, 0).toString(exec);
+ int k = 0;
+ int len = str.size();
+ while (k < len) {
+ const UChar* c = str.data() + k;
+ UChar u;
+ if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
+ if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {
+ u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);
+ c = &u;
+ k += 5;
+ }
+ } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {
+ u = UChar(Lexer::convertHex(c[1], c[2]));
+ c = &u;
+ k += 2;
+ }
+ k++;
+ result.append(*c);
+ }
+
+ return jsString(exec, result);
+}
+
+#ifndef NDEBUG
+JSValuePtr globalFuncJSCPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ CStringBuffer string;
+ args.at(exec, 0).toString(exec).getCString(string);
+ puts(string.data());
+ return jsUndefined();
+}
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSGlobalObjectFunctions_h
+#define JSGlobalObjectFunctions_h
+
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class JSObject;
+ class JSValuePtr;
+
+ // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there
+ // is a 0.5% reduction.
+
+ JSValuePtr globalFuncEval(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncParseInt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncParseFloat(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncIsNaN(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncIsFinite(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncDecodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncEncodeURI(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncEscape(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValuePtr globalFuncUnescape(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+#ifndef NDEBUG
+ JSValuePtr globalFuncJSCPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+#endif
+
+ static const double mantissaOverflowLowerBound = 9007199254740992.0;
+ double parseIntOverflow(const char*, int length, int radix);
+ bool isStrWhiteSpace(UChar);
+
+} // namespace JSC
+
+#endif // JSGlobalObjectFunctions_h
--- /dev/null
+/*
+ * Copyright (C) 2003-2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSImmediate.h"
+
+#include "BooleanConstructor.h"
+#include "BooleanPrototype.h"
+#include "Error.h"
+#include "ExceptionHelpers.h"
+#include "JSGlobalObject.h"
+#include "JSNotAnObject.h"
+#include "NumberConstructor.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+JSObject* JSImmediate::toThisObject(JSValuePtr v, ExecState* exec)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return constructNumber(exec, v);
+ if (isBoolean(v))
+ return constructBooleanFromImmediateBoolean(exec, v);
+ if (v.isNull())
+ return exec->globalThisValue();
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+JSObject* JSImmediate::toObject(JSValuePtr v, ExecState* exec)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return constructNumber(exec, v);
+ if (isBoolean(v))
+ return constructBooleanFromImmediateBoolean(exec, v);
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+JSObject* JSImmediate::prototype(JSValuePtr v, ExecState* exec)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return exec->lexicalGlobalObject()->numberPrototype();
+ if (isBoolean(v))
+ return exec->lexicalGlobalObject()->booleanPrototype();
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+UString JSImmediate::toString(JSValuePtr v)
+{
+ ASSERT(isImmediate(v));
+ if (isIntegerNumber(v))
+ return UString::from(getTruncatedInt32(v));
+#if USE(ALTERNATE_JSIMMEDIATE)
+ if (isNumber(v)) {
+ ASSERT(isDoubleNumber(v));
+ double value = doubleValue(v);
+ if (value == 0.0) // +0.0 or -0.0
+ return "0";
+ return UString::from(value);
+ }
+#else
+ ASSERT(!isNumber(v));
+#endif
+ if (jsBoolean(false) == v)
+ return "false";
+ if (jsBoolean(true) == v)
+ return "true";
+ if (v.isNull())
+ return "null";
+ ASSERT(v.isUndefined());
+ return "undefined";
+}
+
+NEVER_INLINE double JSImmediate::nonInlineNaN()
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSImmediate_h
+#define JSImmediate_h
+
+#include <wtf/Assertions.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
+#include "JSValue.h"
+#include <limits>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSCell;
+ class JSFastMath;
+ class JSGlobalData;
+ class JSObject;
+ class UString;
+
+ JSValuePtr js0();
+ JSValuePtr jsNull();
+ JSValuePtr jsBoolean(bool b);
+ JSValuePtr jsUndefined();
+ JSValuePtr jsImpossibleValue();
+ JSValuePtr jsNumber(ExecState* exec, double d);
+ JSValuePtr jsNumber(ExecState*, char i);
+ JSValuePtr jsNumber(ExecState*, unsigned char i);
+ JSValuePtr jsNumber(ExecState*, short i);
+ JSValuePtr jsNumber(ExecState*, unsigned short i);
+ JSValuePtr jsNumber(ExecState* exec, int i);
+ JSValuePtr jsNumber(ExecState* exec, unsigned i);
+ JSValuePtr jsNumber(ExecState* exec, long i);
+ JSValuePtr jsNumber(ExecState* exec, unsigned long i);
+ JSValuePtr jsNumber(ExecState* exec, long long i);
+ JSValuePtr jsNumber(ExecState* exec, unsigned long long i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, double d);
+ JSValuePtr jsNumber(JSGlobalData* globalData, short i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, int i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, long i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, long long i);
+ JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i);
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ inline intptr_t reinterpretDoubleToIntptr(double value)
+ {
+ return WTF::bitwise_cast<intptr_t>(value);
+ }
+
+ inline double reinterpretIntptrToDouble(intptr_t value)
+ {
+ return WTF::bitwise_cast<double>(value);
+ }
+#endif
+
+ /*
+ * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
+ * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
+ * because allocator alignment guarantees they will be 00 in cell pointers.
+ *
+ * For example, on a 32 bit system:
+ *
+ * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
+ * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
+ * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
+ * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ]
+ *
+ * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
+ * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
+ * tag used to indicate the exact type.
+ *
+ * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
+ * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
+ * two bits will form an extended tag.
+ *
+ * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1
+ * [ high 30 bits of the value ] [ high bit part of value ]
+ * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10
+ * [ extended 'payload' ] [ extended tag ] [ tag 'other' ]
+ *
+ * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
+ * bit would flag the value as undefined. If neither bits are set, the value is null.
+ *
+ * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
+ * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
+ *
+ * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
+ * For undefined or null immediates the payload is zero.
+ *
+ * Boolean: 000000000000000000000000000V 01 10
+ * [ boolean value ] [ bool ] [ tag 'other' ]
+ * Undefined: 0000000000000000000000000000 10 10
+ * [ zero ] [ undefined ] [ tag 'other' ]
+ * Null: 0000000000000000000000000000 00 10
+ * [ zero ] [ zero ] [ tag 'other' ]
+ */
+
+ /*
+ * On 64-bit platforms, we support an alternative encoding form for immediates, if
+ * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision
+ * floating point values may also be encoded as JSImmediates.
+ *
+ * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
+ * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
+ * can encode a 51-bit payload. Hardware produced and C-library payloads typically
+ * have a payload of zero. We assume that non-zero payloads are available to encode
+ * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
+ * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+ * ranges to encode other values (however there are also other ranges of NaN space that
+ * could have been selected). This range of NaN space is represented by 64-bit numbers
+ * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
+ * valid double-precision numbers will begin fall in these ranges.
+ *
+ * The scheme we have implemented encodes double precision values by adding 2^48 to the
+ * 64-bit integer representation of the number. After this manipulation, no encoded
+ * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
+ *
+ * The top 16-bits denote the type of the encoded JSImmediate:
+ *
+ * Pointer: 0000:PPPP:PPPP:PPPP
+ * 0001:****:****:****
+ * Double:{ ...
+ * FFFE:****:****:****
+ * Integer: FFFF:0000:IIII:IIII
+ *
+ * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000
+ * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined
+ * values are encoded in the same manner as the default format.
+ */
+
+ class JSImmediate {
+ private:
+ friend class JIT;
+ friend class JSValuePtr;
+ friend class JSFastMath;
+ friend JSValuePtr js0();
+ friend JSValuePtr jsNull();
+ friend JSValuePtr jsBoolean(bool b);
+ friend JSValuePtr jsUndefined();
+ friend JSValuePtr jsImpossibleValue();
+ friend JSValuePtr jsNumber(ExecState* exec, double d);
+ friend JSValuePtr jsNumber(ExecState*, char i);
+ friend JSValuePtr jsNumber(ExecState*, unsigned char i);
+ friend JSValuePtr jsNumber(ExecState*, short i);
+ friend JSValuePtr jsNumber(ExecState*, unsigned short i);
+ friend JSValuePtr jsNumber(ExecState* exec, int i);
+ friend JSValuePtr jsNumber(ExecState* exec, unsigned i);
+ friend JSValuePtr jsNumber(ExecState* exec, long i);
+ friend JSValuePtr jsNumber(ExecState* exec, unsigned long i);
+ friend JSValuePtr jsNumber(ExecState* exec, long long i);
+ friend JSValuePtr jsNumber(ExecState* exec, unsigned long long i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, double d);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, short i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned short i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, int i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, long i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, long long i);
+ friend JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i);
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ // If all bits in the mask are set, this indicates an integer number,
+ // if any but not all are set this value is a double precision number.
+ static const intptr_t TagTypeNumber = 0xffff000000000000ll;
+ // This value is 2^48, used to encode doubles such that the encoded value will begin
+ // with a 16-bit pattern within the range 0x0001..0xFFFE.
+ static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
+#else
+ static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
+#endif
+ static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer
+ static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther;
+
+ static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits
+ static const intptr_t ExtendedTagBitBool = 0x4;
+ static const intptr_t ExtendedTagBitUndefined = 0x8;
+
+ static const intptr_t FullTagTypeMask = TagMask | ExtendedTagMask;
+ static const intptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool;
+ static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
+ static const intptr_t FullTagTypeNull = TagBitTypeOther;
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static const int32_t IntegerPayloadShift = 0;
+#else
+ static const int32_t IntegerPayloadShift = 1;
+#endif
+ static const int32_t ExtendedPayloadShift = 4;
+
+ static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
+
+ static const int32_t signBit = 0x80000000;
+
+ static ALWAYS_INLINE bool isImmediate(JSValuePtr v)
+ {
+ return rawValue(v) & TagMask;
+ }
+
+ static ALWAYS_INLINE bool isNumber(JSValuePtr v)
+ {
+ return rawValue(v) & TagTypeNumber;
+ }
+
+ static ALWAYS_INLINE bool isIntegerNumber(JSValuePtr v)
+ {
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
+#else
+ return isNumber(v);
+#endif
+ }
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static ALWAYS_INLINE bool isDoubleNumber(JSValuePtr v)
+ {
+ return isNumber(v) && !isIntegerNumber(v);
+ }
+#endif
+
+ static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValuePtr v)
+ {
+ // A single mask to check for the sign bit and the number tag all at once.
+ return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
+ }
+
+ static ALWAYS_INLINE bool isBoolean(JSValuePtr v)
+ {
+ return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
+ }
+
+ static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v)
+ {
+ // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
+ return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
+ }
+
+ static JSValuePtr from(char);
+ static JSValuePtr from(signed char);
+ static JSValuePtr from(unsigned char);
+ static JSValuePtr from(short);
+ static JSValuePtr from(unsigned short);
+ static JSValuePtr from(int);
+ static JSValuePtr from(unsigned);
+ static JSValuePtr from(long);
+ static JSValuePtr from(unsigned long);
+ static JSValuePtr from(long long);
+ static JSValuePtr from(unsigned long long);
+ static JSValuePtr from(double);
+
+ static ALWAYS_INLINE bool isEitherImmediate(JSValuePtr v1, JSValuePtr v2)
+ {
+ return (rawValue(v1) | rawValue(v2)) & TagMask;
+ }
+
+ static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2)
+ {
+ return isImmediate(v1) & isImmediate(v2);
+ }
+
+ static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
+#else
+ return rawValue(v1) & rawValue(v2) & TagTypeNumber;
+#endif
+ }
+
+ static double toDouble(JSValuePtr);
+ static bool toBoolean(JSValuePtr);
+ static JSObject* toObject(JSValuePtr, ExecState*);
+ static JSObject* toThisObject(JSValuePtr, ExecState*);
+ static UString toString(JSValuePtr);
+
+ static bool getUInt32(JSValuePtr, uint32_t&);
+ static bool getTruncatedInt32(JSValuePtr, int32_t&);
+ static bool getTruncatedUInt32(JSValuePtr, uint32_t&);
+
+ static int32_t getTruncatedInt32(JSValuePtr);
+ static uint32_t getTruncatedUInt32(JSValuePtr);
+
+ static JSValuePtr trueImmediate();
+ static JSValuePtr falseImmediate();
+ static JSValuePtr undefinedImmediate();
+ static JSValuePtr nullImmediate();
+ static JSValuePtr zeroImmediate();
+ static JSValuePtr oneImmediate();
+
+ static JSValuePtr impossibleValue();
+
+ static JSObject* prototype(JSValuePtr, ExecState*);
+
+ private:
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static const int minImmediateInt = ((-INT_MAX) - 1);
+ static const int maxImmediateInt = INT_MAX;
+#else
+ static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
+ static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
+#endif
+ static const unsigned maxImmediateUInt = maxImmediateInt;
+
+ static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer)
+ {
+ return JSValuePtr::makeImmediate(integer);
+ }
+
+ // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the
+ // integer doesn't interfere with the tag bits in the upper word. In the default encoding,
+ // if intptr_t id larger then int32_t we sign extend the value through the upper word.
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static ALWAYS_INLINE JSValuePtr makeInt(uint32_t value)
+#else
+ static ALWAYS_INLINE JSValuePtr makeInt(int32_t value)
+#endif
+ {
+ return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
+ }
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static ALWAYS_INLINE JSValuePtr makeDouble(double value)
+ {
+ return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
+ }
+#endif
+
+ static ALWAYS_INLINE JSValuePtr makeBool(bool b)
+ {
+ return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
+ }
+
+ static ALWAYS_INLINE JSValuePtr makeUndefined()
+ {
+ return makeValue(FullTagTypeUndefined);
+ }
+
+ static ALWAYS_INLINE JSValuePtr makeNull()
+ {
+ return makeValue(FullTagTypeNull);
+ }
+
+ template<typename T>
+ static JSValuePtr fromNumberOutsideIntegerRange(T);
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ static ALWAYS_INLINE double doubleValue(JSValuePtr v)
+ {
+ return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
+ }
+#endif
+
+ static ALWAYS_INLINE int32_t intValue(JSValuePtr v)
+ {
+ return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
+ }
+
+ static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v)
+ {
+ return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
+ }
+
+ static ALWAYS_INLINE bool boolValue(JSValuePtr v)
+ {
+ return rawValue(v) & ExtendedPayloadBitBoolValue;
+ }
+
+ static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v)
+ {
+ return v.immediateValue();
+ }
+
+ static double nonInlineNaN();
+ };
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::trueImmediate() { return makeBool(true); }
+ ALWAYS_INLINE JSValuePtr JSImmediate::falseImmediate() { return makeBool(false); }
+ ALWAYS_INLINE JSValuePtr JSImmediate::undefinedImmediate() { return makeUndefined(); }
+ ALWAYS_INLINE JSValuePtr JSImmediate::nullImmediate() { return makeNull(); }
+ ALWAYS_INLINE JSValuePtr JSImmediate::zeroImmediate() { return makeInt(0); }
+ ALWAYS_INLINE JSValuePtr JSImmediate::oneImmediate() { return makeInt(1); }
+
+ // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
+ ALWAYS_INLINE JSValuePtr JSImmediate::impossibleValue() { return makeValue(0x4); }
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ inline bool doubleToBoolean(double value)
+ {
+ return value < 0.0 || value > 0.0;
+ }
+
+ ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
+ {
+ ASSERT(isImmediate(v));
+ return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
+ : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
+ }
+#else
+ ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
+ {
+ ASSERT(isImmediate(v));
+ return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
+ }
+#endif
+
+ ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v)
+ {
+ // FIXME: should probably be asserting isPositiveIntegerNumber here.
+ ASSERT(isIntegerNumber(v));
+ return intValue(v);
+ }
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ template<typename T>
+ inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T value)
+ {
+ return makeDouble(static_cast<double>(value));
+ }
+#else
+ template<typename T>
+ inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T)
+ {
+ return noValue();
+ }
+#endif
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(short i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(int i)
+ {
+#if !USE(ALTERNATE_JSIMMEDIATE)
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return fromNumberOutsideIntegerRange(i);
+#endif
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i)
+ {
+ if (i > maxImmediateUInt)
+ return fromNumberOutsideIntegerRange(i);
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(long i)
+ {
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return fromNumberOutsideIntegerRange(i);
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i)
+ {
+ if (i > maxImmediateUInt)
+ return fromNumberOutsideIntegerRange(i);
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i)
+ {
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return noValue();
+ return makeInt(static_cast<intptr_t>(i));
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i)
+ {
+ if (i > maxImmediateUInt)
+ return fromNumberOutsideIntegerRange(i);
+ return makeInt(static_cast<intptr_t>(i));
+ }
+
+ ALWAYS_INLINE JSValuePtr JSImmediate::from(double d)
+ {
+ const int intVal = static_cast<int>(d);
+
+ // Check for data loss from conversion to int.
+ if (intVal != d || (!intVal && signbit(d)))
+ return fromNumberOutsideIntegerRange(d);
+
+ return from(intVal);
+ }
+
+ ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v)
+ {
+ ASSERT(isIntegerNumber(v));
+ return intValue(v);
+ }
+
+ ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v)
+ {
+ ASSERT(isImmediate(v));
+
+ if (isIntegerNumber(v))
+ return intValue(v);
+
+#if USE(ALTERNATE_JSIMMEDIATE)
+ if (isNumber(v)) {
+ ASSERT(isDoubleNumber(v));
+ return doubleValue(v);
+ }
+#else
+ ASSERT(!isNumber(v));
+#endif
+
+ if (rawValue(v) == FullTagTypeUndefined)
+ return nonInlineNaN();
+
+ ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
+ return rawValue(v) >> ExtendedPayloadShift;
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i)
+ {
+ i = uintValue(v);
+ return isPositiveIntegerNumber(v);
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i)
+ {
+ i = intValue(v);
+ return isIntegerNumber(v);
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i)
+ {
+ return getUInt32(v, i);
+ }
+
+ inline JSValuePtr js0()
+ {
+ return JSImmediate::zeroImmediate();
+ }
+
+ inline JSValuePtr jsNull()
+ {
+ return JSImmediate::nullImmediate();
+ }
+
+ inline JSValuePtr jsBoolean(bool b)
+ {
+ return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
+ }
+
+ inline JSValuePtr jsUndefined()
+ {
+ return JSImmediate::undefinedImmediate();
+ }
+
+ inline JSValuePtr jsImpossibleValue()
+ {
+ return JSImmediate::impossibleValue();
+ }
+
+ // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32().
+ int32_t toInt32(double);
+ uint32_t toUInt32(double);
+ int32_t toInt32SlowCase(double, bool& ok);
+ uint32_t toUInt32SlowCase(double, bool& ok);
+
+ inline bool JSValuePtr::isUndefined() const
+ {
+ return asValue() == jsUndefined();
+ }
+
+ inline bool JSValuePtr::isNull() const
+ {
+ return asValue() == jsNull();
+ }
+
+ inline bool JSValuePtr::isUndefinedOrNull() const
+ {
+ return JSImmediate::isUndefinedOrNull(asValue());
+ }
+
+ inline bool JSValuePtr::isBoolean() const
+ {
+ return JSImmediate::isBoolean(asValue());
+ }
+
+ inline bool JSValuePtr::getBoolean(bool& v) const
+ {
+ if (JSImmediate::isBoolean(asValue())) {
+ v = JSImmediate::toBoolean(asValue());
+ return true;
+ }
+
+ return false;
+ }
+
+ inline bool JSValuePtr::getBoolean() const
+ {
+ return asValue() == jsBoolean(true);
+ }
+
+ ALWAYS_INLINE int32_t JSValuePtr::toInt32(ExecState* exec) const
+ {
+ int32_t i;
+ if (getTruncatedInt32(i))
+ return i;
+ bool ignored;
+ return toInt32SlowCase(toNumber(exec), ignored);
+ }
+
+ inline uint32_t JSValuePtr::toUInt32(ExecState* exec) const
+ {
+ uint32_t i;
+ if (getTruncatedUInt32(i))
+ return i;
+ bool ignored;
+ return toUInt32SlowCase(toNumber(exec), ignored);
+ }
+
+ inline int32_t toInt32(double val)
+ {
+ if (!(val >= -2147483648.0 && val < 2147483648.0)) {
+ bool ignored;
+ return toInt32SlowCase(val, ignored);
+ }
+ return static_cast<int32_t>(val);
+ }
+
+ inline uint32_t toUInt32(double val)
+ {
+ if (!(val >= 0.0 && val < 4294967296.0)) {
+ bool ignored;
+ return toUInt32SlowCase(val, ignored);
+ }
+ return static_cast<uint32_t>(val);
+ }
+
+ inline int32_t JSValuePtr::toInt32(ExecState* exec, bool& ok) const
+ {
+ int32_t i;
+ if (getTruncatedInt32(i)) {
+ ok = true;
+ return i;
+ }
+ return toInt32SlowCase(toNumber(exec), ok);
+ }
+
+ inline uint32_t JSValuePtr::toUInt32(ExecState* exec, bool& ok) const
+ {
+ uint32_t i;
+ if (getTruncatedUInt32(i)) {
+ ok = true;
+ return i;
+ }
+ return toUInt32SlowCase(toNumber(exec), ok);
+ }
+
+ inline bool JSValuePtr::isCell() const
+ {
+ return !JSImmediate::isImmediate(asValue());
+ }
+
+ inline bool JSValuePtr::isInt32Fast() const
+ {
+ return JSImmediate::isIntegerNumber(asValue());
+ }
+
+ inline int32_t JSValuePtr::getInt32Fast() const
+ {
+ ASSERT(isInt32Fast());
+ return JSImmediate::getTruncatedInt32(asValue());
+ }
+
+ inline bool JSValuePtr::isUInt32Fast() const
+ {
+ return JSImmediate::isPositiveIntegerNumber(asValue());
+ }
+
+ inline uint32_t JSValuePtr::getUInt32Fast() const
+ {
+ ASSERT(isUInt32Fast());
+ return JSImmediate::getTruncatedUInt32(asValue());
+ }
+
+ inline JSValuePtr JSValuePtr::makeInt32Fast(int32_t i)
+ {
+ return JSImmediate::from(i);
+ }
+
+ inline bool JSValuePtr::areBothInt32Fast(JSValuePtr v1, JSValuePtr v2)
+ {
+ return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
+ }
+
+ class JSFastMath {
+ public:
+ static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValuePtr v1, JSValuePtr v2)
+ {
+ return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
+ }
+
+ static ALWAYS_INLINE JSValuePtr equal(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastBitwiseOperations(v1, v2));
+ return jsBoolean(v1 == v2);
+ }
+
+ static ALWAYS_INLINE JSValuePtr notEqual(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastBitwiseOperations(v1, v2));
+ return jsBoolean(v1 != v2);
+ }
+
+ static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastBitwiseOperations(v1, v2));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
+ }
+
+ static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastBitwiseOperations(v1, v2));
+ return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
+ }
+
+ static ALWAYS_INLINE JSValuePtr orImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastBitwiseOperations(v1, v2));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
+ }
+
+ static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2)
+ {
+ return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
+ }
+
+ static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2)
+ {
+ return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
+ }
+
+ static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift)
+ {
+ ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
+#if USE(ALTERNATE_JSIMMEDIATE)
+ return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber);
+#else
+ return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
+#endif
+ }
+
+ static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v)
+ {
+ // Number is non-negative and an operation involving two of these can't overflow.
+ // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
+ return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber;
+ }
+
+ static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValuePtr v1, JSValuePtr v2)
+ {
+ // Number is non-negative and an operation involving two of these can't overflow.
+ // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
+ return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2);
+ }
+
+ static ALWAYS_INLINE JSValuePtr addImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastAdditiveOperations(v1, v2));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
+ }
+
+ static ALWAYS_INLINE JSValuePtr subImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(canDoFastAdditiveOperations(v1, v2));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
+ }
+
+ static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v)
+ {
+ ASSERT(canDoFastAdditiveOperations(v));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
+ }
+
+ static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v)
+ {
+ ASSERT(canDoFastAdditiveOperations(v));
+ return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
+ }
+ };
+
+} // namespace JSC
+
+#endif // JSImmediate_h
--- /dev/null
+/*
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the NU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA
+ *
+ */
+
+#include "config.h"
+#include "JSLock.h"
+
+#include "Collector.h"
+#include "CallFrame.h"
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+namespace JSC {
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+// Acquire this mutex before accessing lock-related data.
+static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
+pthread_key_t JSLockCount;
+
+static void createJSLockCount()
+{
+ pthread_key_create(&JSLockCount, 0);
+}
+
+pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
+
+// Lock nesting count.
+intptr_t JSLock::lockCount()
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount));
+}
+
+static void setLockCount(intptr_t count)
+{
+ ASSERT(count >= 0);
+ pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
+}
+
+JSLock::JSLock(ExecState* exec)
+ : m_lockingForReal(exec->globalData().isSharedInstance)
+{
+ lock(m_lockingForReal);
+}
+
+void JSLock::lock(bool lockForReal)
+{
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockForReal)
+ return;
+#endif
+
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ intptr_t currentLockCount = lockCount();
+ if (!currentLockCount && lockForReal) {
+ int result;
+ result = pthread_mutex_lock(&JSMutex);
+ ASSERT(!result);
+ }
+ setLockCount(currentLockCount + 1);
+}
+
+void JSLock::unlock(bool lockForReal)
+{
+ ASSERT(lockCount());
+
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockForReal)
+ return;
+#endif
+
+ intptr_t newLockCount = lockCount() - 1;
+ setLockCount(newLockCount);
+ if (!newLockCount && lockForReal) {
+ int result;
+ result = pthread_mutex_unlock(&JSMutex);
+ ASSERT(!result);
+ }
+}
+
+void JSLock::lock(ExecState* exec)
+{
+ lock(exec->globalData().isSharedInstance);
+}
+
+void JSLock::unlock(ExecState* exec)
+{
+ unlock(exec->globalData().isSharedInstance);
+}
+
+bool JSLock::currentThreadIsHoldingLock()
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+ return !!pthread_getspecific(JSLockCount);
+}
+
+// This is fairly nasty. We allow multiple threads to run on the same
+// context, and we do not require any locking semantics in doing so -
+// clients of the API may simply use the context from multiple threads
+// concurently, and assume this will work. In order to make this work,
+// We lock the context when a thread enters, and unlock it when it leaves.
+// However we do not only unlock when the thread returns from its
+// entry point (evaluate script or call function), we also unlock the
+// context if the thread leaves JSC by making a call out to an external
+// function through a callback.
+//
+// All threads using the context share the same JS stack (the RegisterFile).
+// Whenever a thread calls into JSC it starts using the RegisterFile from the
+// previous 'high water mark' - the maximum point the stack has ever grown to
+// (returned by RegisterFile::end()). So if a first thread calls out to a
+// callback, and a second thread enters JSC, then also exits by calling out
+// to a callback, we can be left with stackframes from both threads in the
+// RegisterFile. As such, a problem may occur should the first thread's
+// callback complete first, and attempt to return to JSC. Were we to allow
+// this to happen, and were its stack to grow further, then it may potentially
+// write over the second thread's call frames.
+//
+// In avoid JS stack corruption we enforce a policy of only ever allowing two
+// threads to use a JS context concurrently, and only allowing the second of
+// these threads to execute until it has completed and fully returned from its
+// outermost call into JSC. We enforce this policy using 'lockDropDepth'. The
+// first time a thread exits it will call DropAllLocks - which will do as expected
+// and drop locks allowing another thread to enter. Should another thread, or the
+// same thread again, enter JSC (through evaluate script or call function), and exit
+// again through a callback, then the locks will not be dropped when DropAllLocks
+// is called (since lockDropDepth is non-zero). Since this thread is still holding
+// the locks, only it will re able to re-enter JSC (either be returning from the
+// callback, or by re-entering through another call to evaulate script or call
+// function).
+//
+// This policy is slightly more restricive than it needs to be for correctness -
+// we could validly allow futher entries into JSC from other threads, we only
+// need ensure that callbacks return in the reverse chronological order of the
+// order in which they were made - though implementing the less restrictive policy
+// would likely increase complexity and overhead.
+//
+static unsigned lockDropDepth = 0;
+
+JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
+ : m_lockingForReal(exec->globalData().isSharedInstance)
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ if (lockDropDepth++) {
+ m_lockCount = 0;
+ return;
+ }
+
+ m_lockCount = JSLock::lockCount();
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::unlock(m_lockingForReal);
+}
+
+JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
+ : m_lockingForReal(lockingForReal)
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ if (lockDropDepth++) {
+ m_lockCount = 0;
+ return;
+ }
+
+ // It is necessary to drop even "unreal" locks, because having a non-zero lock count
+ // will prevent a real lock from being taken.
+
+ m_lockCount = JSLock::lockCount();
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::unlock(m_lockingForReal);
+}
+
+JSLock::DropAllLocks::~DropAllLocks()
+{
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::lock(m_lockingForReal);
+
+ --lockDropDepth;
+}
+
+#else
+
+JSLock::JSLock(ExecState*)
+ : m_lockingForReal(false)
+{
+}
+
+// If threading support is off, set the lock count to a constant value of 1 so ssertions
+// that the lock is held don't fail
+intptr_t JSLock::lockCount()
+{
+ return 1;
+}
+
+bool JSLock::currentThreadIsHoldingLock()
+{
+ return true;
+}
+
+void JSLock::lock(bool)
+{
+}
+
+void JSLock::unlock(bool)
+{
+}
+
+void JSLock::lock(ExecState*)
+{
+}
+
+void JSLock::unlock(ExecState*)
+{
+}
+
+JSLock::DropAllLocks::DropAllLocks(ExecState*)
+{
+}
+
+JSLock::DropAllLocks::DropAllLocks(bool)
+{
+}
+
+JSLock::DropAllLocks::~DropAllLocks()
+{
+}
+
+#endif // USE(MULTIPLE_THREADS)
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2005, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSLock_h
+#define JSLock_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+ // To make it safe to use JavaScript on multiple threads, it is
+ // important to lock before doing anything that allocates a
+ // JavaScript data structure or that interacts with shared state
+ // such as the protect count hash table. The simplest way to lock
+ // is to create a local JSLock object in the scope where the lock
+ // must be held. The lock is recursive so nesting is ok. The JSLock
+ // object also acts as a convenience short-hand for running important
+ // initialization routines.
+
+ // To avoid deadlock, sometimes it is necessary to temporarily
+ // release the lock. Since it is recursive you actually have to
+ // release all locks held by your thread. This is safe to do if
+ // you are executing code that doesn't require the lock, and you
+ // reacquire the right number of locks at the end. You can do this
+ // by constructing a locally scoped JSLock::DropAllLocks object. The
+ // DropAllLocks object takes care to release the JSLock only if your
+ // thread acquired it to begin with.
+
+ // For contexts other than the single shared one, implicit locking is not done,
+ // but we still need to perform all the counting in order to keep debug
+ // assertions working, so that clients that use the shared context don't break.
+
+ class ExecState;
+
+ class JSLock : Noncopyable {
+ public:
+ JSLock(ExecState*);
+
+ JSLock(bool lockingForReal)
+ : m_lockingForReal(lockingForReal)
+ {
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockingForReal)
+ return;
+#endif
+ lock(lockingForReal);
+ }
+
+ ~JSLock()
+ {
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!m_lockingForReal)
+ return;
+#endif
+ unlock(m_lockingForReal);
+ }
+
+ static void lock(bool);
+ static void unlock(bool);
+ static void lock(ExecState*);
+ static void unlock(ExecState*);
+
+ static intptr_t lockCount();
+ static bool currentThreadIsHoldingLock();
+
+ bool m_lockingForReal;
+
+ class DropAllLocks : Noncopyable {
+ public:
+ DropAllLocks(ExecState* exec);
+ DropAllLocks(bool);
+ ~DropAllLocks();
+
+ private:
+ intptr_t m_lockCount;
+ bool m_lockingForReal;
+ };
+ };
+
+} // namespace
+
+#endif // JSLock_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "JSNotAnObject.h"
+
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
+
+// JSValue methods
+JSValuePtr JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+}
+
+bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValuePtr&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::toBoolean(ExecState* exec) const
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+double JSNotAnObject::toNumber(ExecState* exec) const
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return NaN;
+}
+
+UString JSNotAnObject::toString(ExecState* exec) const
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return "";
+}
+
+JSObject* JSNotAnObject::toObject(ExecState* exec) const
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+}
+
+// Marking
+void JSNotAnObject::mark()
+{
+ JSCell::mark();
+ if (!m_exception->marked())
+ m_exception->mark();
+}
+
+// JSObject methods
+bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValuePtr, PutPropertySlot&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+}
+
+void JSNotAnObject::put(ExecState* exec, unsigned, JSValuePtr)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+}
+
+bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSNotAnObject_h
+#define JSNotAnObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class JSNotAnObjectErrorStub : public JSObject {
+ public:
+ JSNotAnObjectErrorStub(ExecState* exec, bool isNull)
+ : JSObject(exec->globalData().notAnObjectErrorStubStructure)
+ , m_isNull(isNull)
+ {
+ }
+
+ bool isNull() const { return m_isNull; }
+
+ private:
+ virtual bool isNotAnObjectErrorStub() const { return true; }
+
+ bool m_isNull;
+ };
+
+ // This unholy class is used to allow us to avoid multiple exception checks
+ // in certain SquirrelFish bytecodes -- effectively it just silently consumes
+ // any operations performed on the result of a failed toObject call.
+ class JSNotAnObject : public JSObject {
+ public:
+ JSNotAnObject(ExecState* exec, JSNotAnObjectErrorStub* exception)
+ : JSObject(exec->globalData().notAnObjectStructure)
+ , m_exception(exception)
+ {
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ // JSValue methods
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ // Marking
+ virtual void mark();
+
+ // JSObject methods
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValuePtr);
+
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSNotAnObjectErrorStub* m_exception;
+ };
+
+} // namespace JSC
+
+#endif // JSNotAnObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSNumberCell.h"
+
+#include "NumberObject.h"
+#include "UString.h"
+
+namespace JSC {
+
+#if !USE(ALTERNATE_JSIMMEDIATE)
+
+JSValuePtr JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ return const_cast<JSNumberCell*>(this);
+}
+
+bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+{
+ number = m_value;
+ value = this;
+ return true;
+}
+
+bool JSNumberCell::toBoolean(ExecState*) const
+{
+ return m_value < 0.0 || m_value > 0.0; // false for NaN
+}
+
+double JSNumberCell::toNumber(ExecState*) const
+{
+ return m_value;
+}
+
+UString JSNumberCell::toString(ExecState*) const
+{
+ if (m_value == 0.0) // +0.0 or -0.0
+ return "0";
+ return UString::from(m_value);
+}
+
+UString JSNumberCell::toThisString(ExecState*) const
+{
+ if (m_value == 0.0) // +0.0 or -0.0
+ return "0";
+ return UString::from(m_value);
+}
+
+JSObject* JSNumberCell::toObject(ExecState* exec) const
+{
+ return constructNumber(exec, const_cast<JSNumberCell*>(this));
+}
+
+JSObject* JSNumberCell::toThisObject(ExecState* exec) const
+{
+ return constructNumber(exec, const_cast<JSNumberCell*>(this));
+}
+
+bool JSNumberCell::getUInt32(uint32_t& uint32) const
+{
+ uint32 = static_cast<uint32_t>(m_value);
+ return uint32 == m_value;
+}
+
+bool JSNumberCell::getTruncatedInt32(int32_t& int32) const
+{
+ if (!(m_value >= -2147483648.0 && m_value < 2147483648.0))
+ return false;
+ int32 = static_cast<int32_t>(m_value);
+ return true;
+}
+
+bool JSNumberCell::getTruncatedUInt32(uint32_t& uint32) const
+{
+ if (!(m_value >= 0.0 && m_value < 4294967296.0))
+ return false;
+ uint32 = static_cast<uint32_t>(m_value);
+ return true;
+}
+
+JSValuePtr JSNumberCell::getJSNumber()
+{
+ return this;
+}
+
+JSValuePtr jsNumberCell(ExecState* exec, double d)
+{
+ return new (exec) JSNumberCell(exec, d);
+}
+
+JSValuePtr jsNumberCell(JSGlobalData* globalData, double d)
+{
+ return new (globalData) JSNumberCell(globalData, d);
+}
+
+#else
+
+JSValuePtr jsNumberCell(ExecState*, double)
+{
+ ASSERT_NOT_REACHED();
+ return noValue();
+}
+
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSNumberCell_h
+#define JSNumberCell_h
+
+#include "CallFrame.h"
+#include "JSCell.h"
+#include "JSImmediate.h"
+#include "Collector.h"
+#include "UString.h"
+#include <stddef.h> // for size_t
+
+namespace JSC {
+
+ extern const double NaN;
+ extern const double Inf;
+
+ JSValuePtr jsNumberCell(ExecState*, double);
+
+#if !USE(ALTERNATE_JSIMMEDIATE)
+
+ class Identifier;
+ class JSCell;
+ class JSObject;
+ class JSString;
+ class PropertySlot;
+
+ struct ClassInfo;
+ struct Instruction;
+
+ class JSNumberCell : public JSCell {
+ friend class JIT;
+ friend JSValuePtr jsNumberCell(JSGlobalData*, double);
+ friend JSValuePtr jsNumberCell(ExecState*, double);
+ public:
+ double value() const { return m_value; }
+
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual UString toThisString(ExecState*) const;
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual JSValuePtr getJSNumber();
+
+ void* operator new(size_t size, ExecState* exec)
+ {
+ #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return exec->heap()->inlineAllocateNumber(size);
+ #else
+ return exec->heap()->allocateNumber(size);
+ #endif
+ }
+
+ void* operator new(size_t size, JSGlobalData* globalData)
+ {
+ #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocateNumber(size);
+ #else
+ return globalData->heap.allocateNumber(size);
+ #endif
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
+
+ private:
+ JSNumberCell(JSGlobalData* globalData, double value)
+ : JSCell(globalData->numberStructure.get())
+ , m_value(value)
+ {
+ }
+
+ JSNumberCell(ExecState* exec, double value)
+ : JSCell(exec->globalData().numberStructure.get())
+ , m_value(value)
+ {
+ }
+
+ virtual bool getUInt32(uint32_t&) const;
+ virtual bool getTruncatedInt32(int32_t&) const;
+ virtual bool getTruncatedUInt32(uint32_t&) const;
+
+ double m_value;
+ };
+
+ JSValuePtr jsNumberCell(JSGlobalData*, double);
+
+ inline bool isNumberCell(JSValuePtr v)
+ {
+ return v.isCell() && v.asCell()->isNumber();
+ }
+
+ inline JSNumberCell* asNumberCell(JSValuePtr v)
+ {
+ ASSERT(isNumberCell(v));
+ return static_cast<JSNumberCell*>(v.asCell());
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, double d)
+ {
+ JSValuePtr v = JSImmediate::from(d);
+ return v ? v : jsNumberCell(exec, d);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, int i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, double d)
+ {
+ JSValuePtr v = JSImmediate::from(d);
+ return v ? v : jsNumberCell(globalData, d);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ }
+
+ inline bool JSValuePtr::isDoubleNumber() const
+ {
+ return isNumberCell(asValue());
+ }
+
+ inline double JSValuePtr::getDoubleNumber() const
+ {
+ return asNumberCell(asValue())->value();
+ }
+
+ inline bool JSValuePtr::isNumber() const
+ {
+ return JSImmediate::isNumber(asValue()) || isDoubleNumber();
+ }
+
+ inline double JSValuePtr::uncheckedGetNumber() const
+ {
+ ASSERT(isNumber());
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber();
+ }
+
+#else
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, double d)
+ {
+ JSValuePtr v = JSImmediate::from(d);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, int i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long long i)
+ {
+ JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long long i)
+ {
+ JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, double d)
+ {
+ JSValuePtr v = JSImmediate::from(d);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, int i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long i)
+ {
+ JSValuePtr v = JSImmediate::from(i);
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long long i)
+ {
+ JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ ASSERT(v);
+ return v;
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned long long i)
+ {
+ JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ ASSERT(v);
+ return v;
+ }
+
+ inline bool JSValuePtr::isDoubleNumber() const
+ {
+ return JSImmediate::isDoubleNumber(asValue());
+ }
+
+ inline double JSValuePtr::getDoubleNumber() const
+ {
+ return JSImmediate::doubleValue(asValue());
+ }
+
+ inline bool JSValuePtr::isNumber() const
+ {
+ return JSImmediate::isNumber(asValue());
+ }
+
+ inline double JSValuePtr::uncheckedGetNumber() const
+ {
+ ASSERT(isNumber());
+ return JSImmediate::toDouble(asValue());
+ }
+
+#endif
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, char i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned char i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, short i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned short i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, short i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned short i)
+ {
+ ASSERT(JSImmediate::from(i));
+ return JSImmediate::from(i);
+ }
+
+ inline JSValuePtr jsNaN(ExecState* exec)
+ {
+ return jsNumber(exec, NaN);
+ }
+
+ inline JSValuePtr jsNaN(JSGlobalData* globalData)
+ {
+ return jsNumber(globalData, NaN);
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ ALWAYS_INLINE JSValuePtr JSValuePtr::toJSNumber(ExecState* exec) const
+ {
+ return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
+ }
+
+ inline bool JSValuePtr::getNumber(double &result) const
+ {
+ if (isInt32Fast())
+ result = getInt32Fast();
+ else if (LIKELY(isDoubleNumber()))
+ result = getDoubleNumber();
+ else {
+ ASSERT(!isNumber());
+ return false;
+ }
+ return true;
+ }
+
+ inline bool JSValuePtr::numberToInt32(int32_t& arg)
+ {
+ if (isInt32Fast())
+ arg = getInt32Fast();
+ else if (LIKELY(isDoubleNumber()))
+ arg = JSC::toInt32(getDoubleNumber());
+ else {
+ ASSERT(!isNumber());
+ return false;
+ }
+ return true;
+ }
+
+ inline bool JSValuePtr::numberToUInt32(uint32_t& arg)
+ {
+ if (isUInt32Fast())
+ arg = getUInt32Fast();
+ else if (LIKELY(isDoubleNumber()))
+ arg = JSC::toUInt32(getDoubleNumber());
+ else if (isInt32Fast()) {
+ // FIXME: I think this case can be merged with the uint case; toUInt32SlowCase
+ // on a negative value is equivalent to simple static_casting.
+ bool ignored;
+ arg = toUInt32SlowCase(getInt32Fast(), ignored);
+ } else {
+ ASSERT(!isNumber());
+ return false;
+ }
+ return true;
+ }
+
+} // namespace JSC
+
+#endif // JSNumberCell_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSObject.h"
+
+#include "DatePrototype.h"
+#include "ErrorConstructor.h"
+#include "GetterSetter.h"
+#include "JSGlobalObject.h"
+#include "NativeErrorConstructor.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "Lookup.h"
+#include "Nodes.h"
+#include "Operations.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+
+#define JSOBJECT_MARK_TRACING 0
+
+#if JSOBJECT_MARK_TRACING
+
+#define JSOBJECT_MARK_BEGIN() \
+ static int markStackDepth = 0; \
+ for (int i = 0; i < markStackDepth; i++) \
+ putchar('-'); \
+ printf("%s (%p)\n", className().UTF8String().c_str(), this); \
+ markStackDepth++; \
+
+#define JSOBJECT_MARK_END() \
+ markStackDepth--;
+
+#else // JSOBJECT_MARK_TRACING
+
+#define JSOBJECT_MARK_BEGIN()
+#define JSOBJECT_MARK_END()
+
+#endif // JSOBJECT_MARK_TRACING
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSObject);
+
+void JSObject::mark()
+{
+ JSOBJECT_MARK_BEGIN();
+
+ JSCell::mark();
+ m_structure->mark();
+
+ size_t storageSize = m_structure->propertyStorageSize();
+ for (size_t i = 0; i < storageSize; ++i) {
+ JSValuePtr v = m_propertyStorage[i];
+ if (!v.marked())
+ v.mark();
+ }
+
+ JSOBJECT_MARK_END();
+}
+
+UString JSObject::className() const
+{
+ const ClassInfo* info = classInfo();
+ if (info)
+ return info->className;
+ return "Object";
+}
+
+bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+static void throwSetterError(ExecState* exec)
+{
+ throwError(exec, TypeError, "setting a property that has only a getter");
+}
+
+// ECMA 8.6.2.2
+void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ ASSERT(value);
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
+ if (!value.isObject() && !value.isNull())
+ return;
+
+ JSValuePtr nextPrototypeValue = value;
+ while (nextPrototypeValue && nextPrototypeValue.isObject()) {
+ JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
+ if (nextPrototype == this) {
+ throwError(exec, GeneralError, "cyclic __proto__ value");
+ return;
+ }
+ nextPrototypeValue = nextPrototype->prototype();
+ }
+
+ setPrototype(value);
+ return;
+ }
+
+ // Check if there are any setters or getters in the prototype chain
+ JSValuePtr prototype;
+ for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
+ prototype = obj->prototype();
+ if (prototype.isNull()) {
+ putDirect(propertyName, value, 0, true, slot);
+ return;
+ }
+ }
+
+ unsigned attributes;
+ if ((m_structure->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
+ return;
+
+ for (JSObject* obj = this; ; obj = asObject(prototype)) {
+ if (JSValuePtr gs = obj->getDirect(propertyName)) {
+ if (gs.isGetterSetter()) {
+ JSObject* setterFunc = asGetterSetter(gs)->setter();
+ if (!setterFunc) {
+ throwSetterError(exec);
+ return;
+ }
+
+ CallData callData;
+ CallType callType = setterFunc->getCallData(callData);
+ ArgList args;
+ args.append(value);
+ call(exec, setterFunc, callType, callData, this, args);
+ return;
+ }
+
+ // If there's an existing property on the object or one of its
+ // prototypes it should be replaced, so break here.
+ break;
+ }
+
+ prototype = obj->prototype();
+ if (prototype.isNull())
+ break;
+ }
+
+ putDirect(propertyName, value, 0, true, slot);
+ return;
+}
+
+void JSObject::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+{
+ PutPropertySlot slot;
+ put(exec, Identifier::from(exec, propertyName), value, slot);
+}
+
+void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ putDirect(propertyName, value, attributes);
+}
+
+void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValuePtr value, unsigned attributes)
+{
+ putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
+}
+
+bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+}
+
+bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+}
+
+// ECMA 8.6.2.5
+bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ unsigned attributes;
+ if (m_structure->get(propertyName, attributes) != WTF::notFound) {
+ if ((attributes & DontDelete))
+ return false;
+ removeDirect(propertyName);
+ return true;
+ }
+
+ // Look in the static hashtable of properties
+ const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
+ if (entry && entry->attributes() & DontDelete)
+ return false; // this builtin property can't be deleted
+
+ // FIXME: Should the code here actually do some deletion?
+ return true;
+}
+
+bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName)
+{
+ return deleteProperty(exec, Identifier::from(exec, propertyName));
+}
+
+static ALWAYS_INLINE JSValuePtr callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
+{
+ JSValuePtr function = object->get(exec, propertyName);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return exec->exception();
+
+ // Prevent "toString" and "valueOf" from observing execution if an exception
+ // is pending.
+ if (exec->hadException())
+ return exec->exception();
+
+ JSValuePtr result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
+ ASSERT(!result.isGetterSetter());
+ if (exec->hadException())
+ return exec->exception();
+ if (result.isObject())
+ return noValue();
+ return result;
+}
+
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& result)
+{
+ result = defaultValue(exec, PreferNumber);
+ number = result.toNumber(exec);
+ return !result.isString();
+}
+
+// ECMA 8.6.2.6
+JSValuePtr JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ // Must call toString first for Date objects.
+ if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) {
+ JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
+ if (value)
+ return value;
+ value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
+ if (value)
+ return value;
+ } else {
+ JSValuePtr value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
+ if (value)
+ return value;
+ value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
+ if (value)
+ return value;
+ }
+
+ ASSERT(!exec->hadException());
+
+ return throwError(exec, TypeError, "No default value");
+}
+
+const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
+{
+ for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
+ if (const HashTable* propHashTable = info->propHashTable(exec)) {
+ if (const HashEntry* entry = propHashTable->entry(exec, propertyName))
+ return entry;
+ }
+ }
+ return 0;
+}
+
+void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+{
+ JSValuePtr object = getDirect(propertyName);
+ if (object && object.isGetterSetter()) {
+ ASSERT(m_structure->hasGetterSetterProperties());
+ asGetterSetter(object)->setGetter(getterFunction);
+ return;
+ }
+
+ PutPropertySlot slot;
+ GetterSetter* getterSetter = new (exec) GetterSetter;
+ putDirect(propertyName, getterSetter, None, true, slot);
+
+ // putDirect will change our Structure if we add a new property. For
+ // getters and setters, though, we also need to change our Structure
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty) {
+ if (!m_structure->isDictionary()) {
+ RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
+ setStructure(structure.release());
+ }
+ }
+
+ m_structure->setHasGetterSetterProperties(true);
+ getterSetter->setGetter(getterFunction);
+}
+
+void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+{
+ JSValuePtr object = getDirect(propertyName);
+ if (object && object.isGetterSetter()) {
+ ASSERT(m_structure->hasGetterSetterProperties());
+ asGetterSetter(object)->setSetter(setterFunction);
+ return;
+ }
+
+ PutPropertySlot slot;
+ GetterSetter* getterSetter = new (exec) GetterSetter;
+ putDirect(propertyName, getterSetter, None, true, slot);
+
+ // putDirect will change our Structure if we add a new property. For
+ // getters and setters, though, we also need to change our Structure
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty) {
+ if (!m_structure->isDictionary()) {
+ RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
+ setStructure(structure.release());
+ }
+ }
+
+ m_structure->setHasGetterSetterProperties(true);
+ getterSetter->setSetter(setterFunction);
+}
+
+JSValuePtr JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
+{
+ JSObject* object = this;
+ while (true) {
+ if (JSValuePtr value = object->getDirect(propertyName)) {
+ if (!value.isGetterSetter())
+ return jsUndefined();
+ JSObject* functionObject = asGetterSetter(value)->getter();
+ if (!functionObject)
+ return jsUndefined();
+ return functionObject;
+ }
+
+ if (!object->prototype() || !object->prototype().isObject())
+ return jsUndefined();
+ object = asObject(object->prototype());
+ }
+}
+
+JSValuePtr JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
+{
+ JSObject* object = this;
+ while (true) {
+ if (JSValuePtr value = object->getDirect(propertyName)) {
+ if (!value.isGetterSetter())
+ return jsUndefined();
+ JSObject* functionObject = asGetterSetter(value)->setter();
+ if (!functionObject)
+ return jsUndefined();
+ return functionObject;
+ }
+
+ if (!object->prototype() || !object->prototype().isObject())
+ return jsUndefined();
+ object = asObject(object->prototype());
+ }
+}
+
+bool JSObject::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto)
+{
+ if (!proto.isObject()) {
+ throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
+ return false;
+ }
+
+ if (!value.isObject())
+ return false;
+
+ JSObject* object = asObject(value);
+ while ((object = object->prototype().getObject())) {
+ if (proto == object)
+ return true;
+ }
+ return false;
+}
+
+bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
+{
+ unsigned attributes;
+ if (!getPropertyAttributes(exec, propertyName, attributes))
+ return false;
+ return !(attributes & DontEnum);
+}
+
+bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+{
+ if (m_structure->get(propertyName, attributes) != WTF::notFound)
+ return true;
+
+ // Look in the static hashtable of properties
+ const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
+ if (entry) {
+ attributes = entry->attributes();
+ return true;
+ }
+
+ return false;
+}
+
+void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
+}
+
+bool JSObject::toBoolean(ExecState*) const
+{
+ return true;
+}
+
+double JSObject::toNumber(ExecState* exec) const
+{
+ JSValuePtr primitive = toPrimitive(exec, PreferNumber);
+ if (exec->hadException()) // should be picked up soon in Nodes.cpp
+ return 0.0;
+ return primitive.toNumber(exec);
+}
+
+UString JSObject::toString(ExecState* exec) const
+{
+ JSValuePtr primitive = toPrimitive(exec, PreferString);
+ if (exec->hadException())
+ return "";
+ return primitive.toString(exec);
+}
+
+JSObject* JSObject::toObject(ExecState*) const
+{
+ return const_cast<JSObject*>(this);
+}
+
+JSObject* JSObject::toThisObject(ExecState*) const
+{
+ return const_cast<JSObject*>(this);
+}
+
+JSObject* JSObject::unwrappedObject()
+{
+ return this;
+}
+
+void JSObject::removeDirect(const Identifier& propertyName)
+{
+ size_t offset;
+ if (m_structure->isDictionary()) {
+ offset = m_structure->removePropertyWithoutTransition(propertyName);
+ if (offset != WTF::notFound)
+ m_propertyStorage[offset] = jsUndefined();
+ return;
+ }
+
+ RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset);
+ if (offset != WTF::notFound)
+ m_propertyStorage[offset] = jsUndefined();
+ setStructure(structure.release());
+}
+
+void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
+{
+ putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr);
+}
+
+void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
+{
+ putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
+}
+
+NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValuePtr* location)
+{
+ if (JSObject* getterFunction = asGetterSetter(*location)->getter())
+ slot.setGetterSlot(getterFunction);
+ else
+ slot.setUndefined();
+}
+
+Structure* JSObject::createInheritorID()
+{
+ m_inheritorID = JSObject::createStructure(this);
+ return m_inheritorID.get();
+}
+
+void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
+{
+ allocatePropertyStorageInline(oldSize, newSize);
+}
+
+JSObject* constructEmptyObject(ExecState* exec)
+{
+ return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSObject_h
+#define JSObject_h
+
+#include "ArgList.h"
+#include "ClassInfo.h"
+#include "CommonIdentifiers.h"
+#include "CallFrame.h"
+#include "JSNumberCell.h"
+#include "PropertySlot.h"
+#include "PutPropertySlot.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+
+namespace JSC {
+
+ class InternalFunction;
+ class PropertyNameArray;
+ class Structure;
+ struct HashEntry;
+ struct HashTable;
+
+ // ECMA 262-3 8.6.1
+ // Property attributes
+ enum Attribute {
+ None = 0,
+ ReadOnly = 1 << 1, // property can be only read, not written
+ DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
+ DontDelete = 1 << 3, // property can't be deleted
+ Function = 1 << 4, // property is a function - only used by static hashtables
+ };
+
+ typedef JSValuePtr* PropertyStorage;
+
+ class JSObject : public JSCell {
+ friend class BatchedTransitionOptimizer;
+ friend class JIT;
+ friend class JSCell;
+
+ public:
+ explicit JSObject(PassRefPtr<Structure>);
+
+ virtual void mark();
+
+ // The inline virtual destructor cannot be the first virtual function declared
+ // in the class as it results in the vtable being generated as a weak symbol
+ virtual ~JSObject();
+
+ bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
+
+ JSValuePtr prototype() const;
+ void setPrototype(JSValuePtr prototype);
+
+ void setStructure(PassRefPtr<Structure>);
+ Structure* inheritorID();
+
+ PropertyStorage& propertyStorage() { return m_propertyStorage; }
+
+ virtual UString className() const;
+
+ JSValuePtr get(ExecState*, const Identifier& propertyName) const;
+ JSValuePtr get(ExecState*, unsigned propertyName) const;
+
+ bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValuePtr value);
+
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes);
+ virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValuePtr value, unsigned attributes);
+
+ bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
+
+ bool hasProperty(ExecState*, const Identifier& propertyName) const;
+ bool hasProperty(ExecState*, unsigned propertyName) const;
+ bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
+
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual JSValuePtr defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual bool hasInstance(ExecState*, JSValuePtr, JSValuePtr prototypeProperty);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual JSObject* unwrappedObject();
+
+ virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+
+ // This get function only looks at the property map.
+ JSValuePtr getDirect(const Identifier& propertyName) const
+ {
+ size_t offset = m_structure->get(propertyName);
+ return offset != WTF::notFound ? m_propertyStorage[offset] : noValue();
+ }
+
+ JSValuePtr* getDirectLocation(const Identifier& propertyName)
+ {
+ size_t offset = m_structure->get(propertyName);
+ return offset != WTF::notFound ? locationForOffset(offset) : 0;
+ }
+
+ JSValuePtr* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
+ {
+ size_t offset = m_structure->get(propertyName, attributes);
+ return offset != WTF::notFound ? locationForOffset(offset) : 0;
+ }
+
+ size_t offsetForLocation(JSValuePtr* location)
+ {
+ return location - m_propertyStorage;
+ }
+
+ JSValuePtr* locationForOffset(size_t offset)
+ {
+ return &m_propertyStorage[offset];
+ }
+
+ void transitionTo(Structure*);
+
+ void removeDirect(const Identifier& propertyName);
+ bool hasCustomProperties() { return !m_structure->isEmpty(); }
+ bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
+
+ void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0);
+ void putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+ void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+ void putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attr = 0);
+ void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+
+ // Fast access to known property offsets.
+ JSValuePtr getDirectOffset(size_t offset) { return m_propertyStorage[offset]; }
+ void putDirectOffset(size_t offset, JSValuePtr value) { m_propertyStorage[offset] = value; }
+
+ void fillGetterPropertySlot(PropertySlot&, JSValuePtr* location);
+
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+ virtual JSValuePtr lookupGetter(ExecState*, const Identifier& propertyName);
+ virtual JSValuePtr lookupSetter(ExecState*, const Identifier& propertyName);
+
+ virtual bool isGlobalObject() const { return false; }
+ virtual bool isVariableObject() const { return false; }
+ virtual bool isActivationObject() const { return false; }
+ virtual bool isWatchdogException() const { return false; }
+ virtual bool isNotAnObjectErrorStub() const { return false; }
+
+ void allocatePropertyStorage(size_t oldSize, size_t newSize);
+ void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
+ bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; }
+
+ static const size_t inlineStorageCapacity = 2;
+ static const size_t nonInlineBaseStorageCapacity = 16;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ }
+
+ protected:
+ bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+
+ private:
+ bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
+ Structure* createInheritorID();
+
+ RefPtr<Structure> m_inheritorID;
+
+ PropertyStorage m_propertyStorage;
+ JSValuePtr m_inlineStorage[inlineStorageCapacity];
+ };
+
+ JSObject* asObject(JSValuePtr);
+
+ JSObject* constructEmptyObject(ExecState*);
+
+inline JSObject* asObject(JSValuePtr value)
+{
+ ASSERT(asCell(value)->isObject());
+ return static_cast<JSObject*>(asCell(value));
+}
+
+inline JSObject::JSObject(PassRefPtr<Structure> structure)
+ : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
+ , m_propertyStorage(m_inlineStorage)
+{
+ ASSERT(m_structure);
+ ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
+ ASSERT(m_structure->isEmpty());
+ ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
+}
+
+inline JSObject::~JSObject()
+{
+ ASSERT(m_structure);
+ if (m_propertyStorage != m_inlineStorage)
+ delete [] m_propertyStorage;
+ m_structure->deref();
+}
+
+inline JSValuePtr JSObject::prototype() const
+{
+ return m_structure->storedPrototype();
+}
+
+inline void JSObject::setPrototype(JSValuePtr prototype)
+{
+ ASSERT(prototype);
+ RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype);
+ setStructure(newStructure.release());
+}
+
+inline void JSObject::setStructure(PassRefPtr<Structure> structure)
+{
+ m_structure->deref();
+ m_structure = structure.releaseRef(); // ~JSObject balances this ref()
+}
+
+inline Structure* JSObject::inheritorID()
+{
+ if (m_inheritorID)
+ return m_inheritorID.get();
+ return createInheritorID();
+}
+
+inline bool JSCell::isObject(const ClassInfo* info) const
+{
+ for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
+ if (ci == info)
+ return true;
+ }
+ return false;
+}
+
+// this method is here to be after the inline declaration of JSCell::isObject
+inline bool JSValuePtr::isObject(const ClassInfo* classInfo) const
+{
+ return isCell() && asCell()->isObject(classInfo);
+}
+
+ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (JSValuePtr* location = getDirectLocation(propertyName)) {
+ if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter())
+ fillGetterPropertySlot(slot, location);
+ else
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ return true;
+ }
+
+ // non-standard Netscape extension
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValue(prototype());
+ return true;
+ }
+
+ return false;
+}
+
+ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+{
+ unsigned attributes;
+ if (JSValuePtr* location = getDirectLocation(propertyName, attributes)) {
+ if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) {
+ slotIsWriteable = false;
+ fillGetterPropertySlot(slot, location);
+ } else {
+ slotIsWriteable = !(attributes & ReadOnly);
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ }
+ return true;
+ }
+
+ // non-standard Netscape extension
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValue(prototype());
+ slotIsWriteable = false;
+ return true;
+ }
+
+ return false;
+}
+
+// It may seem crazy to inline a function this large, especially a virtual function,
+// but it makes a big difference to property lookup that derived classes can inline their
+// base class call to this.
+ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return inlineGetOwnPropertySlot(exec, propertyName, slot);
+}
+
+ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (structure()->typeInfo().hasStandardGetOwnPropertySlot())
+ return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
+ return getOwnPropertySlot(exec, propertyName, slot);
+}
+
+// It may seem crazy to inline a function this large but it makes a big difference
+// since this is function very hot in variable lookup
+inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ JSObject* object = this;
+ while (true) {
+ if (object->fastGetOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ JSValuePtr prototype = object->prototype();
+ if (!prototype.isObject())
+ return false;
+ object = asObject(prototype);
+ }
+}
+
+inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ JSObject* object = this;
+ while (true) {
+ if (object->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ JSValuePtr prototype = object->prototype();
+ if (!prototype.isObject())
+ return false;
+ object = asObject(prototype);
+ }
+}
+
+inline JSValuePtr JSObject::get(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot(this);
+ if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+
+ return jsUndefined();
+}
+
+inline JSValuePtr JSObject::get(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot(this);
+ if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+
+ return jsUndefined();
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attr)
+{
+ PutPropertySlot slot;
+ putDirect(propertyName, value, attr, false, slot);
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValuePtr value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (m_structure->isDictionary()) {
+ unsigned currentAttributes;
+ size_t offset = m_structure->get(propertyName, currentAttributes);
+ if (offset != WTF::notFound) {
+ if (checkReadOnly && currentAttributes & ReadOnly)
+ return;
+ m_propertyStorage[offset] = value;
+ slot.setExistingProperty(this, offset);
+ return;
+ }
+
+ size_t currentCapacity = m_structure->propertyStorageCapacity();
+ offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
+ if (currentCapacity != m_structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+
+ ASSERT(offset < m_structure->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+ slot.setNewProperty(this, offset);
+ return;
+ }
+
+ size_t offset;
+ size_t currentCapacity = m_structure->propertyStorageCapacity();
+ if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, offset)) {
+ if (currentCapacity != structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+
+ ASSERT(offset < structure->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+ slot.setNewProperty(this, offset);
+ slot.setWasTransition(true);
+ setStructure(structure.release());
+ return;
+ }
+
+ unsigned currentAttributes;
+ offset = m_structure->get(propertyName, currentAttributes);
+ if (offset != WTF::notFound) {
+ if (checkReadOnly && currentAttributes & ReadOnly)
+ return;
+ m_propertyStorage[offset] = value;
+ slot.setExistingProperty(this, offset);
+ return;
+ }
+
+ RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, offset);
+ if (currentCapacity != structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+
+ ASSERT(offset < structure->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+ slot.setNewProperty(this, offset);
+ slot.setWasTransition(true);
+ setStructure(structure.release());
+}
+
+inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ size_t currentCapacity = m_structure->propertyStorageCapacity();
+ size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
+ if (currentCapacity != m_structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+}
+
+inline void JSObject::transitionTo(Structure* newStructure)
+{
+ if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
+ allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+ setStructure(newStructure);
+}
+
+inline JSValuePtr JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+{
+ return defaultValue(exec, preferredType);
+}
+
+inline JSValuePtr JSValuePtr::get(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot(asValue());
+ return get(exec, propertyName, slot);
+}
+
+inline JSValuePtr JSValuePtr::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(!isCell())) {
+ JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = asCell();
+ while (true) {
+ if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ ASSERT(cell->isObject());
+ JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype();
+ if (!prototype.isObject())
+ return jsUndefined();
+ cell = asObject(prototype);
+ }
+}
+
+inline JSValuePtr JSValuePtr::get(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot(asValue());
+ return get(exec, propertyName, slot);
+}
+
+inline JSValuePtr JSValuePtr::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(!isCell())) {
+ JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = const_cast<JSCell*>(asCell());
+ while (true) {
+ if (cell->getOwnPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ ASSERT(cell->isObject());
+ JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype();
+ if (!prototype.isObject())
+ return jsUndefined();
+ cell = prototype.asCell();
+ }
+}
+
+inline void JSValuePtr::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ if (UNLIKELY(!isCell())) {
+ JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot);
+ return;
+ }
+ asCell()->put(exec, propertyName, value, slot);
+}
+
+inline void JSValuePtr::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+{
+ if (UNLIKELY(!isCell())) {
+ JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value);
+ return;
+ }
+ asCell()->put(exec, propertyName, value);
+}
+
+ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize)
+{
+ ASSERT(newSize > oldSize);
+
+ JSValuePtr* oldPropertyStorage = m_propertyStorage;
+ m_propertyStorage = new JSValuePtr[newSize];
+
+ for (unsigned i = 0; i < oldSize; ++i)
+ m_propertyStorage[i] = oldPropertyStorage[i];
+
+ if (oldPropertyStorage != m_inlineStorage)
+ delete [] oldPropertyStorage;
+}
+
+} // namespace JSC
+
+#endif // JSObject_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSPropertyNameIterator.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
+
+JSPropertyNameIterator::~JSPropertyNameIterator()
+{
+}
+
+JSValuePtr JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return noValue();
+}
+
+bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValuePtr&)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+bool JSPropertyNameIterator::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double JSPropertyNameIterator::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+UString JSPropertyNameIterator::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+JSObject* JSPropertyNameIterator::toObject(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+void JSPropertyNameIterator::mark()
+{
+ JSCell::mark();
+ if (m_object && !m_object->marked())
+ m_object->mark();
+}
+
+void JSPropertyNameIterator::invalidate()
+{
+ ASSERT(m_position == m_end);
+ m_object = 0;
+ m_data.clear();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSPropertyNameIterator_h
+#define JSPropertyNameIterator_h
+
+#include "JSObject.h"
+#include "JSString.h"
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+ class Identifier;
+ class JSObject;
+
+ class JSPropertyNameIterator : public JSCell {
+ public:
+ static JSPropertyNameIterator* create(ExecState*, JSValuePtr);
+
+ virtual ~JSPropertyNameIterator();
+
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double&, JSValuePtr&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual void mark();
+
+ JSValuePtr next(ExecState*);
+ void invalidate();
+
+ private:
+ JSPropertyNameIterator();
+ JSPropertyNameIterator(JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
+
+ JSObject* m_object;
+ RefPtr<PropertyNameArrayData> m_data;
+ PropertyNameArrayData::const_iterator m_position;
+ PropertyNameArrayData::const_iterator m_end;
+ };
+
+inline JSPropertyNameIterator::JSPropertyNameIterator()
+ : JSCell(0)
+ , m_object(0)
+ , m_position(0)
+ , m_end(0)
+{
+}
+
+inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
+ : JSCell(0)
+ , m_object(object)
+ , m_data(propertyNameArrayData)
+ , m_position(m_data->begin())
+ , m_end(m_data->end())
+{
+}
+
+inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValuePtr v)
+{
+ if (v.isUndefinedOrNull())
+ return new (exec) JSPropertyNameIterator;
+
+ JSObject* o = v.toObject(exec);
+ PropertyNameArray propertyNames(exec);
+ o->getPropertyNames(exec, propertyNames);
+ return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData());
+}
+
+inline JSValuePtr JSPropertyNameIterator::next(ExecState* exec)
+{
+ if (m_position == m_end)
+ return noValue();
+
+ if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec))
+ return jsOwnedString(exec, (*m_position++).ustring());
+
+ do {
+ if (m_object->hasProperty(exec, *m_position))
+ return jsOwnedString(exec, (*m_position++).ustring());
+ m_position++;
+ } while (m_position != m_end);
+
+ return noValue();
+}
+
+} // namespace JSC
+
+#endif // JSPropertyNameIterator_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "JSStaticScopeObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
+
+void JSStaticScopeObject::mark()
+{
+ JSVariableObject::mark();
+
+ if (!d()->registerStore.marked())
+ d()->registerStore.mark();
+}
+
+JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
+{
+ return exec->globalThisValue();
+}
+
+void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&)
+{
+ if (symbolTablePut(propertyName, value))
+ return;
+
+ ASSERT_NOT_REACHED();
+}
+
+void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+{
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ ASSERT_NOT_REACHED();
+}
+
+bool JSStaticScopeObject::isDynamicScope() const
+{
+ return false;
+}
+
+JSStaticScopeObject::~JSStaticScopeObject()
+{
+ ASSERT(d());
+ delete d();
+}
+
+inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
+{
+ return symbolTableGet(propertyName, slot);
+}
+
+inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+{
+ return symbolTableGet(propertyName, slot, slotIsWriteable);
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSStaticScopeObject_h
+#define JSStaticScopeObject_h
+
+#include "JSVariableObject.h"
+
+namespace JSC{
+
+ class JSStaticScopeObject : public JSVariableObject {
+ protected:
+ using JSVariableObject::JSVariableObjectData;
+ struct JSStaticScopeObjectData : public JSVariableObjectData {
+ JSStaticScopeObjectData()
+ : JSVariableObjectData(&symbolTable, ®isterStore + 1)
+ {
+ }
+ SymbolTable symbolTable;
+ Register registerStore;
+ };
+
+ public:
+ JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValuePtr value, unsigned attributes)
+ : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData())
+ {
+ d()->registerStore = value;
+ symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
+ }
+ virtual ~JSStaticScopeObject();
+ virtual void mark();
+ bool isDynamicScope() const;
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
+ void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+
+ private:
+ JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
+ };
+
+}
+
+#endif // JSStaticScopeObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSString.h"
+
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "StringObject.h"
+#include "StringPrototype.h"
+
+namespace JSC {
+
+JSValuePtr JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ return const_cast<JSString*>(this);
+}
+
+bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+{
+ value = this;
+ number = m_value.toDouble();
+ return false;
+}
+
+bool JSString::toBoolean(ExecState*) const
+{
+ return !m_value.isEmpty();
+}
+
+double JSString::toNumber(ExecState*) const
+{
+ return m_value.toDouble();
+}
+
+UString JSString::toString(ExecState*) const
+{
+ return m_value;
+}
+
+UString JSString::toThisString(ExecState*) const
+{
+ return m_value;
+}
+
+JSString* JSString::toThisJSString(ExecState*)
+{
+ return this;
+}
+
+inline StringObject* StringObject::create(ExecState* exec, JSString* string)
+{
+ return new (exec) StringObject(exec->lexicalGlobalObject()->stringObjectStructure(), string);
+}
+
+JSObject* JSString::toObject(ExecState* exec) const
+{
+ return StringObject::create(exec, const_cast<JSString*>(this));
+}
+
+JSObject* JSString::toThisObject(ExecState* exec) const
+{
+ return StringObject::create(exec, const_cast<JSString*>(this));
+}
+
+bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ // The semantics here are really getPropertySlot, not getOwnPropertySlot.
+ // This function should only be called by JSValue::get.
+ if (getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ slot.setBase(this);
+ JSObject* object;
+ for (JSValuePtr prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
+ object = asObject(prototype);
+ if (object->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ }
+ slot.setUndefined();
+ return true;
+}
+
+bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ // The semantics here are really getPropertySlot, not getOwnPropertySlot.
+ // This function should only be called by JSValue::get.
+ if (getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+JSString* jsString(JSGlobalData* globalData, const UString& s)
+{
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s);
+}
+
+JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
+{
+ ASSERT(offset <= static_cast<unsigned>(s.size()));
+ ASSERT(length <= static_cast<unsigned>(s.size()));
+ ASSERT(offset + length <= static_cast<unsigned>(s.size()));
+ if (!length)
+ return globalData->smallStrings.emptyString(globalData);
+ if (length == 1) {
+ UChar c = s.data()[offset];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length));
+}
+
+JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
+{
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSString_h
+#define JSString_h
+
+#include "CommonIdentifiers.h"
+#include "CallFrame.h"
+#include "Identifier.h"
+#include "JSNumberCell.h"
+#include "PropertySlot.h"
+
+namespace JSC {
+
+ class JSString;
+
+ JSString* jsEmptyString(JSGlobalData*);
+ JSString* jsEmptyString(ExecState*);
+ JSString* jsString(JSGlobalData*, const UString&); // returns empty string if passed null string
+ JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
+
+ JSString* jsSingleCharacterString(JSGlobalData*, UChar);
+ JSString* jsSingleCharacterString(ExecState*, UChar);
+ JSString* jsSingleCharacterSubstring(JSGlobalData*, const UString&, unsigned offset);
+ JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset);
+ JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length);
+ JSString* jsSubstring(ExecState*, const UString&, unsigned offset, unsigned length);
+
+ // Non-trivial strings are two or more characters long.
+ // These functions are faster than just calling jsString.
+ JSString* jsNontrivialString(JSGlobalData*, const UString&);
+ JSString* jsNontrivialString(ExecState*, const UString&);
+ JSString* jsNontrivialString(JSGlobalData*, const char*);
+ JSString* jsNontrivialString(ExecState*, const char*);
+
+ // Should be used for strings that are owned by an object that will
+ // likely outlive the JSValue this makes, such as the parse tree or a
+ // DOM object that contains a UString
+ JSString* jsOwnedString(JSGlobalData*, const UString&);
+ JSString* jsOwnedString(ExecState*, const UString&);
+
+ class JSString : public JSCell {
+ friend class JIT;
+ friend class Interpreter;
+
+ public:
+ JSString(JSGlobalData* globalData, const UString& value)
+ : JSCell(globalData->stringStructure.get())
+ , m_value(value)
+ {
+ Heap::heap(this)->reportExtraMemoryCost(value.cost());
+ }
+
+ enum HasOtherOwnerType { HasOtherOwner };
+ JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
+ : JSCell(globalData->stringStructure.get())
+ , m_value(value)
+ {
+ }
+ JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
+ : JSCell(globalData->stringStructure.get())
+ , m_value(value)
+ {
+ }
+
+ const UString& value() const { return m_value; }
+
+ bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
+ JSString* getIndex(JSGlobalData*, unsigned);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
+
+ private:
+ enum VPtrStealingHackType { VPtrStealingHack };
+ JSString(VPtrStealingHackType)
+ : JSCell(0)
+ {
+ }
+
+ virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+
+ // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ UString m_value;
+ };
+
+ JSString* asString(JSValuePtr);
+
+ inline JSString* asString(JSValuePtr value)
+ {
+ ASSERT(asCell(value)->isString());
+ return static_cast<JSString*>(asCell(value));
+ }
+
+ inline JSString* jsEmptyString(JSGlobalData* globalData)
+ {
+ return globalData->smallStrings.emptyString(globalData);
+ }
+
+ inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
+ {
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ return new (globalData) JSString(globalData, UString(&c, 1));
+ }
+
+ inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
+ {
+ ASSERT(offset < static_cast<unsigned>(s.size()));
+ UChar c = s.data()[offset];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, 1));
+ }
+
+ inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
+ {
+ ASSERT(s);
+ ASSERT(s[0]);
+ ASSERT(s[1]);
+ return new (globalData) JSString(globalData, s);
+ }
+
+ inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
+ {
+ ASSERT(s.size() > 1);
+ return new (globalData) JSString(globalData, s);
+ }
+
+ inline JSString* JSString::getIndex(JSGlobalData* globalData, unsigned i)
+ {
+ ASSERT(canGetIndex(i));
+ return jsSingleCharacterSubstring(globalData, m_value, i);
+ }
+
+ inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
+ inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
+ inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
+ inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { return jsSingleCharacterSubstring(&exec->globalData(), s, offset); }
+ inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
+ inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
+ inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); }
+ inline JSString* jsOwnedString(ExecState* exec, const UString& s) { return jsOwnedString(&exec->globalData(), s); }
+
+ ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (propertyName == exec->propertyNames().length) {
+ slot.setValue(jsNumber(exec, m_value.size()));
+ return true;
+ }
+
+ bool isStrictUInt32;
+ unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+ if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
+ slot.setValue(jsSingleCharacterSubstring(exec, m_value, i));
+ return true;
+ }
+
+ return false;
+ }
+
+ ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+ {
+ if (propertyName < static_cast<unsigned>(m_value.size())) {
+ slot.setValue(jsSingleCharacterSubstring(exec, m_value, propertyName));
+ return true;
+ }
+
+ return false;
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ inline JSString* JSValuePtr::toThisJSString(ExecState* exec)
+ {
+ return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec);
+ }
+
+} // namespace JSC
+
+#endif // JSString_h
--- /dev/null
+/*
+ * Copyright (C) 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSType_h
+#define JSType_h
+
+namespace JSC {
+
+ /**
+ * Primitive types
+ */
+ enum JSType {
+ UnspecifiedType = 0,
+ UndefinedType = 1,
+ BooleanType = 2,
+ NumberType = 3,
+ NullType = 4,
+ StringType = 5,
+ ObjectType = 6,
+ GetterSetterType = 7
+ };
+
+} // namespace JSC
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSValue.h"
+
+#include "JSFunction.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+static const double D32 = 4294967296.0;
+
+// ECMA 9.4
+double JSValuePtr::toInteger(ExecState* exec) const
+{
+ if (isInt32Fast())
+ return getInt32Fast();
+ double d = toNumber(exec);
+ return isnan(d) ? 0.0 : trunc(d);
+}
+
+double JSValuePtr::toIntegerPreserveNaN(ExecState* exec) const
+{
+ if (isInt32Fast())
+ return getInt32Fast();
+ return trunc(toNumber(exec));
+}
+
+int32_t toInt32SlowCase(double d, bool& ok)
+{
+ ok = true;
+
+ if (d >= -D32 / 2 && d < D32 / 2)
+ return static_cast<int32_t>(d);
+
+ if (isnan(d) || isinf(d)) {
+ ok = false;
+ return 0;
+ }
+
+ double d32 = fmod(trunc(d), D32);
+ if (d32 >= D32 / 2)
+ d32 -= D32;
+ else if (d32 < -D32 / 2)
+ d32 += D32;
+ return static_cast<int32_t>(d32);
+}
+
+uint32_t toUInt32SlowCase(double d, bool& ok)
+{
+ ok = true;
+
+ if (d >= 0.0 && d < D32)
+ return static_cast<uint32_t>(d);
+
+ if (isnan(d) || isinf(d)) {
+ ok = false;
+ return 0;
+ }
+
+ double d32 = fmod(trunc(d), D32);
+ if (d32 < 0)
+ d32 += D32;
+ return static_cast<uint32_t>(d32);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stddef.h> // for size_t
+#include <stdint.h>
+
+#ifndef JSValue_h
+#define JSValue_h
+
+#include "CallData.h"
+#include "ConstructData.h"
+
+namespace JSC {
+
+ class Identifier;
+ class JSCell;
+ class JSObject;
+ class JSString;
+ class PropertySlot;
+ class PutPropertySlot;
+ class UString;
+
+ struct ClassInfo;
+ struct Instruction;
+
+ enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
+
+ class JSImmediate;
+ class JSValueEncodedAsPointer;
+
+ class JSValuePtr {
+ friend class JSImmediate;
+
+ static JSValuePtr makeImmediate(intptr_t value)
+ {
+ return JSValuePtr(reinterpret_cast<JSCell*>(value));
+ }
+
+ intptr_t immediateValue()
+ {
+ return reinterpret_cast<intptr_t>(m_ptr);
+ }
+
+ public:
+ JSValuePtr()
+ : m_ptr(0)
+ {
+ }
+
+ JSValuePtr(JSCell* ptr)
+ : m_ptr(ptr)
+ {
+ }
+
+ JSValuePtr(const JSCell* ptr)
+ : m_ptr(const_cast<JSCell*>(ptr))
+ {
+ }
+
+ operator bool() const
+ {
+ return m_ptr;
+ }
+
+ bool operator==(const JSValuePtr other) const
+ {
+ return m_ptr == other.m_ptr;
+ }
+
+ bool operator!=(const JSValuePtr other) const
+ {
+ return m_ptr != other.m_ptr;
+ }
+
+ static JSValueEncodedAsPointer* encode(JSValuePtr value)
+ {
+ return reinterpret_cast<JSValueEncodedAsPointer*>(value.m_ptr);
+ }
+
+ static JSValuePtr decode(JSValueEncodedAsPointer* ptr)
+ {
+ return JSValuePtr(reinterpret_cast<JSCell*>(ptr));
+ }
+
+ // Querying the type.
+ bool isUndefined() const;
+ bool isNull() const;
+ bool isUndefinedOrNull() const;
+ bool isBoolean() const;
+ bool isNumber() const;
+ bool isString() const;
+ bool isGetterSetter() const;
+ bool isObject() const;
+ bool isObject(const ClassInfo*) const;
+
+ // Extracting the value.
+ bool getBoolean(bool&) const;
+ bool getBoolean() const; // false if not a boolean
+ bool getNumber(double&) const;
+ double uncheckedGetNumber() const;
+ bool getString(UString&) const;
+ UString getString() const; // null string if not a string
+ JSObject* getObject() const; // 0 if not an object
+
+ CallType getCallData(CallData&);
+ ConstructType getConstructData(ConstructData&);
+
+ // Extracting integer values.
+ bool getUInt32(uint32_t&) const;
+ bool getTruncatedInt32(int32_t&) const;
+ bool getTruncatedUInt32(uint32_t&) const;
+
+ // Basic conversions.
+ JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&);
+
+ bool toBoolean(ExecState*) const;
+
+ // toNumber conversion is expected to be side effect free if an exception has
+ // been set in the ExecState already.
+ double toNumber(ExecState*) const;
+ JSValuePtr toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
+ UString toString(ExecState*) const;
+ JSObject* toObject(ExecState*) const;
+
+ // Integer conversions.
+ // 'x.numberToInt32(output)' is equivalent to 'x.isNumber() && x.toInt32(output)'
+ double toInteger(ExecState*) const;
+ double toIntegerPreserveNaN(ExecState*) const;
+ int32_t toInt32(ExecState*) const;
+ int32_t toInt32(ExecState*, bool& ok) const;
+ bool numberToInt32(int32_t& arg);
+ uint32_t toUInt32(ExecState*) const;
+ uint32_t toUInt32(ExecState*, bool& ok) const;
+ bool numberToUInt32(uint32_t& arg);
+
+ // Fast integer operations; these values return results where the value is trivially available
+ // in a convenient form, for use in optimizations. No assumptions should be made based on the
+ // results of these operations, for example !isInt32Fast() does not necessarily indicate the
+ // result of getNumber will not be 0.
+ bool isInt32Fast() const;
+ int32_t getInt32Fast() const;
+ bool isUInt32Fast() const;
+ uint32_t getUInt32Fast() const;
+ static JSValuePtr makeInt32Fast(int32_t);
+ static bool areBothInt32Fast(JSValuePtr, JSValuePtr);
+
+ // Floating point conversions (this is a convenience method for webcore;
+ // signle precision float is not a representation used in JS or JSC).
+ float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
+
+ // Garbage collection.
+ void mark();
+ bool marked() const;
+
+ // Object operations, with the toObject operation included.
+ JSValuePtr get(ExecState*, const Identifier& propertyName) const;
+ JSValuePtr get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
+ JSValuePtr get(ExecState*, unsigned propertyName) const;
+ JSValuePtr get(ExecState*, unsigned propertyName, PropertySlot&) const;
+ void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ void put(ExecState*, unsigned propertyName, JSValuePtr);
+
+ bool needsThisConversion() const;
+ JSObject* toThisObject(ExecState*) const;
+ UString toThisString(ExecState*) const;
+ JSString* toThisJSString(ExecState*);
+
+ static bool equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2);
+ static bool equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2);
+ static bool equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2);
+ static bool strictEqual(JSValuePtr v1, JSValuePtr v2);
+ static bool strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2);
+ static bool strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2);
+
+ JSValuePtr getJSNumber(); // noValue() if this is not a JSNumber or number object
+
+ bool isCell() const;
+ JSCell* asCell() const;
+
+ private:
+ inline const JSValuePtr asValue() const { return *this; }
+
+ bool isDoubleNumber() const;
+ double getDoubleNumber() const;
+
+ JSCell* m_ptr;
+ };
+
+ inline JSValuePtr noValue()
+ {
+ return JSValuePtr();
+ }
+
+ inline bool operator==(const JSValuePtr a, const JSCell* b) { return a == JSValuePtr(b); }
+ inline bool operator==(const JSCell* a, const JSValuePtr b) { return JSValuePtr(a) == b; }
+
+ inline bool operator!=(const JSValuePtr a, const JSCell* b) { return a != JSValuePtr(b); }
+ inline bool operator!=(const JSCell* a, const JSValuePtr b) { return JSValuePtr(a) != b; }
+
+} // namespace JSC
+
+#endif // JSValue_h
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSVariableObject.h"
+
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (symbolTable().contains(propertyName.ustring().rep()))
+ return false;
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ SymbolTable::const_iterator end = symbolTable().end();
+ for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+ if (!(it->second.getAttributes() & DontEnum))
+ propertyNames.add(Identifier(exec, it->first.get()));
+ }
+
+ JSObject::getPropertyNames(exec, propertyNames);
+}
+
+bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+{
+ SymbolTableEntry entry = symbolTable().get(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ attributes = entry.getAttributes() | DontDelete;
+ return true;
+ }
+ return JSObject::getPropertyAttributes(exec, propertyName, attributes);
+}
+
+bool JSVariableObject::isVariableObject() const
+{
+ return true;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSVariableObject_h
+#define JSVariableObject_h
+
+#include "JSObject.h"
+#include "Register.h"
+#include "SymbolTable.h"
+#include "UnusedParam.h"
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+ class Register;
+
+ class JSVariableObject : public JSObject {
+ friend class JIT;
+
+ public:
+ SymbolTable& symbolTable() const { return *d->symbolTable; }
+
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes) = 0;
+
+ virtual bool deleteProperty(ExecState*, const Identifier&);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual bool isVariableObject() const;
+ virtual bool isDynamicScope() const = 0;
+
+ virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+
+ Register& registerAt(int index) const { return d->registers[index]; }
+
+ protected:
+ // Subclasses of JSVariableObject can subclass this struct to add data
+ // without increasing their own size (since there's a hard limit on the
+ // size of a JSCell).
+ struct JSVariableObjectData {
+ JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
+ : symbolTable(symbolTable)
+ , registers(registers)
+ {
+ ASSERT(symbolTable);
+ }
+
+ SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
+ Register* registers; // "r" in the register file.
+ OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
+
+ private:
+ JSVariableObjectData(const JSVariableObjectData&);
+ JSVariableObjectData& operator=(const JSVariableObjectData&);
+ };
+
+ JSVariableObject(PassRefPtr<Structure> structure, JSVariableObjectData* data)
+ : JSObject(structure)
+ , d(data) // Subclass owns this pointer.
+ {
+ }
+
+ Register* copyRegisterArray(Register* src, size_t count);
+ void setRegisters(Register* r, Register* registerArray);
+
+ bool symbolTableGet(const Identifier&, PropertySlot&);
+ bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ bool symbolTablePut(const Identifier&, JSValuePtr);
+ bool symbolTablePutWithAttributes(const Identifier&, JSValuePtr, unsigned attributes);
+
+ JSVariableObjectData* d;
+ };
+
+ inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ slot.setRegisterSlot(®isterAt(entry.getIndex()));
+ return true;
+ }
+ return false;
+ }
+
+ inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ slot.setRegisterSlot(®isterAt(entry.getIndex()));
+ slotIsWriteable = !entry.isReadOnly();
+ return true;
+ }
+ return false;
+ }
+
+ inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValuePtr value)
+ {
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (entry.isNull())
+ return false;
+ if (entry.isReadOnly())
+ return true;
+ registerAt(entry.getIndex()) = value;
+ return true;
+ }
+
+ inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+ {
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
+ if (iter == symbolTable().end())
+ return false;
+ SymbolTableEntry& entry = iter->second;
+ ASSERT(!entry.isNull());
+ entry.setAttributes(attributes);
+ registerAt(entry.getIndex()) = value;
+ return true;
+ }
+
+ inline Register* JSVariableObject::copyRegisterArray(Register* src, size_t count)
+ {
+ Register* registerArray = new Register[count];
+ memcpy(registerArray, src, count * sizeof(Register));
+
+ return registerArray;
+ }
+
+ inline void JSVariableObject::setRegisters(Register* registers, Register* registerArray)
+ {
+ ASSERT(registerArray != d->registerArray.get());
+ d->registerArray.set(registerArray);
+ d->registers = registers;
+ }
+
+} // namespace JSC
+
+#endif // JSVariableObject_h
--- /dev/null
+/*
+ * Copyright (C) 2006 Maks Orlovich
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
+
+void JSWrapperObject::mark()
+{
+ JSObject::mark();
+ if (m_internalValue && !m_internalValue.marked())
+ m_internalValue.mark();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2006 Maks Orlovich
+ * Copyright (C) 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSWrapperObject_h
+#define JSWrapperObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ // This class is used as a base for classes such as String,
+ // Number, Boolean and Date which are wrappers for primitive types.
+ class JSWrapperObject : public JSObject {
+ protected:
+ explicit JSWrapperObject(PassRefPtr<Structure>);
+
+ public:
+ JSValuePtr internalValue() const { return m_internalValue; }
+ void setInternalValue(JSValuePtr);
+
+ virtual void mark();
+
+ private:
+ JSValuePtr m_internalValue;
+ };
+
+ inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure)
+ : JSObject(structure)
+ , m_internalValue(noValue())
+ {
+ }
+
+ inline void JSWrapperObject::setInternalValue(JSValuePtr value)
+ {
+ ASSERT(value);
+ ASSERT(!value.isObject());
+ m_internalValue = value;
+ }
+
+} // namespace JSC
+
+#endif // JSWrapperObject_h
--- /dev/null
+/*
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "Lookup.h"
+
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+void HashTable::createTable(JSGlobalData* globalData) const
+{
+#if ENABLE(PERFECT_HASH_SIZE)
+ ASSERT(!table);
+ HashEntry* entries = new HashEntry[hashSizeMask + 1];
+ for (int i = 0; i <= hashSizeMask; ++i)
+ entries[i].setKey(0);
+ for (int i = 0; values[i].key; ++i) {
+ UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
+ int hashIndex = identifier->computedHash() & hashSizeMask;
+ ASSERT(!entries[hashIndex].key());
+ entries[hashIndex].initialize(identifier, values[i].attributes, values[i].value1, values[i].value2);
+ }
+ table = entries;
+#else
+ ASSERT(!table);
+ int linkIndex = compactHashSizeMask + 1;
+ HashEntry* entries = new HashEntry[compactSize];
+ for (int i = 0; i < compactSize; ++i)
+ entries[i].setKey(0);
+ for (int i = 0; values[i].key; ++i) {
+ UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
+ int hashIndex = identifier->computedHash() & compactHashSizeMask;
+ HashEntry* entry = &entries[hashIndex];
+
+ if (entry->key()) {
+ while (entry->next()) {
+ entry = entry->next();
+ }
+ ASSERT(linkIndex < compactSize);
+ entry->setNext(&entries[linkIndex++]);
+ entry = entry->next();
+ }
+
+ entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2);
+ }
+ table = entries;
+#endif
+}
+
+void HashTable::deleteTable() const
+{
+ if (table) {
+#if ENABLE(PERFECT_HASH_SIZE)
+ int max = hashSizeMask + 1;
+#else
+ int max = compactSize;
+#endif
+ for (int i = 0; i != max; ++i) {
+ if (UString::Rep* key = table[i].key())
+ key->deref();
+ }
+ delete [] table;
+ table = 0;
+ }
+}
+
+void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
+{
+ ASSERT(entry->attributes() & Function);
+ JSValuePtr* location = thisObj->getDirectLocation(propertyName);
+
+ if (!location) {
+ PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function());
+ thisObj->putDirect(propertyName, function, entry->attributes());
+ location = thisObj->getDirectLocation(propertyName);
+ }
+
+ slot.setValueSlot(thisObj, location, thisObj->offsetForLocation(location));
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef Lookup_h
+#define Lookup_h
+
+#include "CallFrame.h"
+#include "Identifier.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "PropertySlot.h"
+#include <stdio.h>
+#include <wtf/Assertions.h>
+
+// Set ENABLE_PERFECT_HASH_SIZE to 0 to save memory at the
+// cost of speed. Test your platform as results may vary.
+#define ENABLE_PERFECT_HASH_SIZE 1
+
+namespace JSC {
+
+ // Hash table generated by the create_hash_table script.
+ struct HashTableValue {
+ const char* key; // property name
+ unsigned char attributes; // JSObject attributes
+ intptr_t value1;
+ intptr_t value2;
+ };
+
+ // FIXME: There is no reason this get function can't be simpler.
+ // ie. typedef JSValuePtr (*GetFunction)(ExecState*, JSObject* baseObject)
+ typedef PropertySlot::GetValueFunc GetFunction;
+ typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValuePtr value);
+
+ class HashEntry {
+ public:
+ void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
+ {
+ m_key = key;
+ m_attributes = attributes;
+ m_u.store.value1 = v1;
+ m_u.store.value2 = v2;
+#if !ENABLE(PERFECT_HASH_SIZE)
+ m_next = 0;
+#endif
+ }
+
+ void setKey(UString::Rep* key) { m_key = key; }
+ UString::Rep* key() const { return m_key; }
+
+ unsigned char attributes() const { return m_attributes; }
+
+ NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
+ unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
+
+ GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
+ PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
+
+ intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
+
+#if !ENABLE(PERFECT_HASH_SIZE)
+ void setNext(HashEntry *next) { m_next = next; }
+ HashEntry* next() const { return m_next; }
+#endif
+
+ private:
+ UString::Rep* m_key;
+ unsigned char m_attributes; // JSObject attributes
+
+ union {
+ struct {
+ intptr_t value1;
+ intptr_t value2;
+ } store;
+ struct {
+ NativeFunction functionValue;
+ intptr_t length; // number of arguments for function
+ } function;
+ struct {
+ GetFunction get;
+ PutFunction put;
+ } property;
+ struct {
+ intptr_t value;
+ intptr_t unused;
+ } lexer;
+ } m_u;
+
+#if !ENABLE(PERFECT_HASH_SIZE)
+ HashEntry* m_next;
+#endif
+ };
+
+ struct HashTable {
+#if ENABLE(PERFECT_HASH_SIZE)
+ int hashSizeMask; // Precomputed size for the hash table (minus 1).
+#else
+ int compactSize;
+ int compactHashSizeMask;
+#endif
+ const HashTableValue* values; // Fixed values generated by script.
+ mutable const HashEntry* table; // Table allocated at runtime.
+
+ ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
+ {
+ if (!table)
+ createTable(globalData);
+ }
+
+ ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
+ {
+ if (!table)
+ createTable(&exec->globalData());
+ }
+
+ void deleteTable() const;
+
+ // Find an entry in the table, and return the entry.
+ ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
+ {
+ initializeIfNeeded(globalData);
+ return entry(identifier);
+ }
+
+ ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const
+ {
+ initializeIfNeeded(exec);
+ return entry(identifier);
+ }
+
+ private:
+ ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
+ {
+#if ENABLE(PERFECT_HASH_SIZE)
+ ASSERT(table);
+ const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask];
+ if (entry->key() != identifier.ustring().rep())
+ return 0;
+ return entry;
+#else
+ ASSERT(table);
+
+ const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask];
+
+ if (!entry->key())
+ return 0;
+
+ do {
+ if (entry->key() == identifier.ustring().rep())
+ return entry;
+ entry = entry->next();
+ } while (entry);
+
+ return 0;
+#endif
+ }
+
+ // Convert the hash table keys to identifiers.
+ void createTable(JSGlobalData*) const;
+ };
+
+ void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
+
+ /**
+ * This method does it all (looking in the hashtable, checking for function
+ * overrides, creating the function or retrieving from cache, calling
+ * getValueProperty in case of a non-function property, forwarding to parent if
+ * unknown property).
+ */
+ template <class ThisImp, class ParentImp>
+ inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
+ {
+ const HashEntry* entry = table->entry(exec, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+
+ if (entry->attributes() & Function)
+ setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+ else
+ slot.setCustom(thisObj, entry->propertyGetter());
+
+ return true;
+ }
+
+ /**
+ * Simplified version of getStaticPropertySlot in case there are only functions.
+ * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
+ * a dummy getValueProperty.
+ */
+ template <class ParentImp>
+ inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+
+ const HashEntry* entry = table->entry(exec, propertyName);
+ if (!entry)
+ return false;
+
+ setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+ return true;
+ }
+
+ /**
+ * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
+ * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
+ */
+ template <class ThisImp, class ParentImp>
+ inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
+ {
+ const HashEntry* entry = table->entry(exec, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+
+ ASSERT(!(entry->attributes() & Function));
+
+ slot.setCustom(thisObj, entry->propertyGetter());
+ return true;
+ }
+
+ /**
+ * This one is for "put".
+ * It looks up a hash entry for the property to be set. If an entry
+ * is found it sets the value and returns true, else it returns false.
+ */
+ template <class ThisImp>
+ inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj)
+ {
+ const HashEntry* entry = table->entry(exec, propertyName);
+
+ if (!entry)
+ return false;
+
+ if (entry->attributes() & Function) // function: put as override property
+ thisObj->putDirect(propertyName, value);
+ else if (!(entry->attributes() & ReadOnly))
+ entry->propertyPutter()(exec, thisObj, value);
+
+ return true;
+ }
+
+ /**
+ * This one is for "put".
+ * It calls lookupPut<ThisImp>() to set the value. If that call
+ * returns false (meaning no entry in the hash table was found),
+ * then it calls put() on the ParentImp class.
+ */
+ template <class ThisImp, class ParentImp>
+ inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValuePtr value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
+ {
+ if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj))
+ thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent
+ }
+
+} // namespace JSC
+
+#endif // Lookup_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "MathObject.h"
+
+#include "ObjectPrototype.h"
+#include "Operations.h"
+#include <time.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RandomNumber.h>
+#include <wtf/RandomNumberSeed.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(MathObject);
+
+static JSValuePtr mathProtoFuncAbs(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncACos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncASin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncATan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncATan2(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncCeil(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncCos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncExp(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncFloor(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncLog(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncMax(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncMin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncPow(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncRandom(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncRound(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncSin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncSqrt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr mathProtoFuncTan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+}
+
+#include "MathObject.lut.h"
+
+namespace JSC {
+
+// ------------------------------ MathObject --------------------------------
+
+const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
+
+/* Source for MathObject.lut.h
+@begin mathTable
+ abs mathProtoFuncAbs DontEnum|Function 1
+ acos mathProtoFuncACos DontEnum|Function 1
+ asin mathProtoFuncASin DontEnum|Function 1
+ atan mathProtoFuncATan DontEnum|Function 1
+ atan2 mathProtoFuncATan2 DontEnum|Function 2
+ ceil mathProtoFuncCeil DontEnum|Function 1
+ cos mathProtoFuncCos DontEnum|Function 1
+ exp mathProtoFuncExp DontEnum|Function 1
+ floor mathProtoFuncFloor DontEnum|Function 1
+ log mathProtoFuncLog DontEnum|Function 1
+ max mathProtoFuncMax DontEnum|Function 2
+ min mathProtoFuncMin DontEnum|Function 2
+ pow mathProtoFuncPow DontEnum|Function 2
+ random mathProtoFuncRandom DontEnum|Function 0
+ round mathProtoFuncRound DontEnum|Function 1
+ sin mathProtoFuncSin DontEnum|Function 1
+ sqrt mathProtoFuncSqrt DontEnum|Function 1
+ tan mathProtoFuncTan DontEnum|Function 1
+@end
+*/
+
+MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
+ : JSObject(structure)
+{
+ putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(exec, log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(exec, log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(exec, 1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(exec, 1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
+ WTF::initializeWeakRandomNumberGenerator();
+}
+
+// ECMA 15.8
+
+bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
+
+ if (!entry)
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+
+ ASSERT(entry->attributes() & Function);
+ setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
+ return true;
+}
+
+// ------------------------------ Functions --------------------------------
+
+JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, fabs(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, acos(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, asin(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, atan(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, atan2(args.at(exec, 0).toNumber(exec), args.at(exec, 1).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, ceil(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, cos(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, exp(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, floor(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, log(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ unsigned argsCount = args.size();
+ double result = -Inf;
+ for (unsigned k = 0; k < argsCount; ++k) {
+ double val = args.at(exec, k).toNumber(exec);
+ if (isnan(val)) {
+ result = NaN;
+ break;
+ }
+ if (val > result || (val == 0 && result == 0 && !signbit(val)))
+ result = val;
+ }
+ return jsNumber(exec, result);
+}
+
+JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ unsigned argsCount = args.size();
+ double result = +Inf;
+ for (unsigned k = 0; k < argsCount; ++k) {
+ double val = args.at(exec, k).toNumber(exec);
+ if (isnan(val)) {
+ result = NaN;
+ break;
+ }
+ if (val < result || (val == 0 && result == 0 && signbit(val)))
+ result = val;
+ }
+ return jsNumber(exec, result);
+}
+
+JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ // ECMA 15.8.2.1.13
+
+ double arg = args.at(exec, 0).toNumber(exec);
+ double arg2 = args.at(exec, 1).toNumber(exec);
+
+ if (isnan(arg2))
+ return jsNaN(exec);
+ if (isinf(arg2) && fabs(arg) == 1)
+ return jsNaN(exec);
+ return jsNumber(exec, pow(arg, arg2));
+}
+
+JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+{
+ return jsNumber(exec, WTF::weakRandomNumber());
+}
+
+JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ double arg = args.at(exec, 0).toNumber(exec);
+ if (signbit(arg) && arg >= -0.5)
+ return jsNumber(exec, -0.0);
+ return jsNumber(exec, floor(arg + 0.5));
+}
+
+JSValuePtr mathProtoFuncSin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, sin(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, sqrt(args.at(exec, 0).toNumber(exec)));
+}
+
+JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, tan(args.at(exec, 0).toNumber(exec)));
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef MathObject_h
+#define MathObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class MathObject : public JSObject {
+ public:
+ MathObject(ExecState*, PassRefPtr<Structure>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+ };
+
+} // namespace JSC
+
+#endif // MathObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "NativeErrorConstructor.h"
+
+#include "ErrorInstance.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "NativeErrorPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
+
+const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
+
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString()))
+ , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype))
+{
+ putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
+ putDirect(exec->propertyNames().prototype, nativeErrorPrototype, DontDelete | ReadOnly | DontEnum);
+}
+
+ErrorInstance* NativeErrorConstructor::construct(ExecState* exec, const ArgList& args)
+{
+ ErrorInstance* object = new (exec) ErrorInstance(m_errorStructure);
+ if (!args.at(exec, 0).isUndefined())
+ object->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0).toString(exec)));
+ return object;
+}
+
+static JSObject* constructWithNativeErrorConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+}
+
+ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithNativeErrorConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValuePtr callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValuePtr, const ArgList& args)
+{
+ return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+}
+
+CallType NativeErrorConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callNativeErrorConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NativeErrorConstructor_h
+#define NativeErrorConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ErrorInstance;
+ class FunctionPrototype;
+ class NativeErrorPrototype;
+
+ class NativeErrorConstructor : public InternalFunction {
+ public:
+ NativeErrorConstructor(ExecState*, PassRefPtr<Structure>, NativeErrorPrototype*);
+
+ static const ClassInfo info;
+
+ ErrorInstance* construct(ExecState*, const ArgList&);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ RefPtr<Structure> m_errorStructure;
+ };
+
+} // namespace JSC
+
+#endif // NativeErrorConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "NativeErrorPrototype.h"
+
+#include "ErrorPrototype.h"
+#include "JSString.h"
+#include "UString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
+
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message)
+ : JSObject(structure)
+{
+ putDirect(exec->propertyNames().name, jsString(exec, name), 0);
+ putDirect(exec->propertyNames().message, jsString(exec, message), 0);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NativeErrorPrototype_h
+#define NativeErrorPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class NativeErrorPrototype : public JSObject {
+ public:
+ NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message);
+ };
+
+} // namespace JSC
+
+#endif // NativeErrorPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberConstructor.h"
+
+#include "NumberObject.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberConstructor);
+
+static JSValuePtr numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&);
+
+} // namespace JSC
+
+#include "NumberConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };
+
+/* Source for NumberConstructor.lut.h
+@begin numberTable
+ NaN numberConstructorNaNValue DontEnum|DontDelete|ReadOnly
+ NEGATIVE_INFINITY numberConstructorNegInfinity DontEnum|DontDelete|ReadOnly
+ POSITIVE_INFINITY numberConstructorPosInfinity DontEnum|DontDelete|ReadOnly
+ MAX_VALUE numberConstructorMaxValue DontEnum|DontDelete|ReadOnly
+ MIN_VALUE numberConstructorMinValue DontEnum|DontDelete|ReadOnly
+@end
+*/
+
+NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
+{
+ // Number.Prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
+}
+
+JSValuePtr numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNaN(exec);
+}
+
+JSValuePtr numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumber(exec, -Inf);
+}
+
+JSValuePtr numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumber(exec, Inf);
+}
+
+JSValuePtr numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumber(exec, 1.7976931348623157E+308);
+}
+
+JSValuePtr numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumber(exec, 5E-324);
+}
+
+// ECMA 15.7.1
+static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
+ double n = args.isEmpty() ? 0 : args.at(exec, 0).toNumber(exec);
+ object->setInternalValue(jsNumber(exec, n));
+ return object;
+}
+
+ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithNumberConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.7.2
+static JSValuePtr callNumberConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0).toNumber(exec));
+}
+
+CallType NumberConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callNumberConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberConstructor_h
+#define NumberConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class NumberPrototype;
+
+ class NumberConstructor : public InternalFunction {
+ public:
+ NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ JSValuePtr getValueProperty(ExecState*, int token) const;
+
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ };
+
+} // namespace JSC
+
+#endif // NumberConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberObject.h"
+
+#include "JSGlobalObject.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberObject);
+
+const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
+
+NumberObject::NumberObject(PassRefPtr<Structure> structure)
+ : JSWrapperObject(structure)
+{
+}
+
+JSValuePtr NumberObject::getJSNumber()
+{
+ return internalValue();
+}
+
+NumberObject* constructNumber(ExecState* exec, JSValuePtr number)
+{
+ NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
+ object->setInternalValue(number);
+ return object;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberObject_h
+#define NumberObject_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ class NumberObject : public JSWrapperObject {
+ public:
+ explicit NumberObject(PassRefPtr<Structure>);
+
+ static const ClassInfo info;
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ virtual JSValuePtr getJSNumber();
+ };
+
+ NumberObject* constructNumber(ExecState*, JSValuePtr);
+
+} // namespace JSC
+
+#endif // NumberObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "PrototypeFunction.h"
+#include "dtoa.h"
+#include "Operations.h"
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+
+static JSValuePtr numberProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr numberProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr numberProtoFuncToFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr numberProtoFuncToExponential(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr numberProtoFuncToPrecision(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+// ECMA 15.7.4
+
+NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ : NumberObject(structure)
+{
+ setInternalValue(jsNumber(exec, 0));
+
+ // The constructor will be added later, after NumberConstructor has been constructed
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
+}
+
+// ------------------------------ Functions ---------------------------
+
+// ECMA 15.7.4.2 - 15.7.4.7
+
+static UString integerPartNoExp(double d)
+{
+ int decimalPoint;
+ int sign;
+ char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+ bool resultIsInfOrNan = (decimalPoint == 9999);
+ size_t length = strlen(result);
+
+ UString str = sign ? "-" : "";
+ if (resultIsInfOrNan)
+ str += result;
+ else if (decimalPoint <= 0)
+ str += "0";
+ else {
+ Vector<char, 1024> buf(decimalPoint + 1);
+
+ // FIXME: Remove use of strcpy() and strncpy()
+ if (static_cast<int>(length) <= decimalPoint) {
+ strcpy(buf.data(), result);
+ memset(buf.data() + length, '0', decimalPoint - length);
+ } else
+ strncpy(buf.data(), result, decimalPoint);
+
+ buf[decimalPoint] = '\0';
+ str.append(buf.data());
+ }
+
+ WTF::freedtoa(result);
+
+ return str;
+}
+
+static UString charSequence(char c, int count)
+{
+ Vector<char, 2048> buf(count + 1, c);
+ buf[count] = '\0';
+
+ return UString(buf.data());
+}
+
+static double intPow10(int e)
+{
+ // This function uses the "exponentiation by squaring" algorithm and
+ // long double to quickly and precisely calculate integer powers of 10.0.
+
+ // This is a handy workaround for <rdar://problem/4494756>
+
+ if (e == 0)
+ return 1.0;
+
+ bool negative = e < 0;
+ unsigned exp = negative ? -e : e;
+
+ long double result = 10.0;
+ bool foundOne = false;
+ for (int bit = 31; bit >= 0; bit--) {
+ if (!foundOne) {
+ if ((exp >> bit) & 1)
+ foundOne = true;
+ } else {
+ result = result * result;
+ if ((exp >> bit) & 1)
+ result = result * 10.0;
+ }
+ }
+
+ if (negative)
+ return static_cast<double>(1.0 / result);
+ return static_cast<double>(result);
+}
+
+JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double radixAsDouble = args.at(exec, 0).toInteger(exec); // nan -> 0
+ if (radixAsDouble == 10 || args.at(exec, 0).isUndefined())
+ return jsString(exec, v.toString(exec));
+
+ if (radixAsDouble < 2 || radixAsDouble > 36)
+ return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");
+
+ int radix = static_cast<int>(radixAsDouble);
+ const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ // INT_MAX results in 1024 characters left of the dot with radix 2
+ // give the same space on the right side. safety checks are in place
+ // unless someone finds a precise rule.
+ char s[2048 + 3];
+ const char* lastCharInString = s + sizeof(s) - 1;
+ double x = v.uncheckedGetNumber();
+ if (isnan(x) || isinf(x))
+ return jsString(exec, UString::from(x));
+
+ bool isNegative = x < 0.0;
+ if (isNegative)
+ x = -x;
+
+ double integerPart = floor(x);
+ char* decimalPoint = s + sizeof(s) / 2;
+
+ // convert integer portion
+ char* p = decimalPoint;
+ double d = integerPart;
+ do {
+ int remainderDigit = static_cast<int>(fmod(d, radix));
+ *--p = digits[remainderDigit];
+ d /= radix;
+ } while ((d <= -1.0 || d >= 1.0) && s < p);
+
+ if (isNegative)
+ *--p = '-';
+ char* startOfResultString = p;
+ ASSERT(s <= startOfResultString);
+
+ d = x - integerPart;
+ p = decimalPoint;
+ const double epsilon = 0.001; // TODO: guessed. base on radix ?
+ bool hasFractionalPart = (d < -epsilon || d > epsilon);
+ if (hasFractionalPart) {
+ *p++ = '.';
+ do {
+ d *= radix;
+ const int digit = static_cast<int>(d);
+ *p++ = digits[digit];
+ d -= digit;
+ } while ((d < -epsilon || d > epsilon) && p < lastCharInString);
+ }
+ *p = '\0';
+ ASSERT(p < s + sizeof(s));
+
+ return jsString(exec, startOfResultString);
+}
+
+JSValuePtr numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ // FIXME: Not implemented yet.
+
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ return jsString(exec, v.toString(exec));
+}
+
+JSValuePtr numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ return v;
+}
+
+JSValuePtr numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ JSValuePtr fractionDigits = args.at(exec, 0);
+ double df = fractionDigits.toInteger(exec);
+ if (!(df >= 0 && df <= 20))
+ return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");
+ int f = static_cast<int>(df);
+
+ double x = v.uncheckedGetNumber();
+ if (isnan(x))
+ return jsNontrivialString(exec, "NaN");
+
+ UString s;
+ if (x < 0) {
+ s.append('-');
+ x = -x;
+ } else if (x == -0.0)
+ x = 0;
+
+ if (x >= pow(10.0, 21.0))
+ return jsString(exec, s + UString::from(x));
+
+ const double tenToTheF = pow(10.0, f);
+ double n = floor(x * tenToTheF);
+ if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))
+ n++;
+
+ UString m = integerPartNoExp(n);
+
+ int k = m.size();
+ if (k <= f) {
+ UString z;
+ for (int i = 0; i < f + 1 - k; i++)
+ z.append('0');
+ m = z + m;
+ k = f + 1;
+ ASSERT(k == m.size());
+ }
+ int kMinusf = k - f;
+ if (kMinusf < m.size())
+ return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));
+ return jsString(exec, s + m.substr(0, kMinusf));
+}
+
+static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
+{
+ if (fractionalDigits <= 0)
+ return;
+
+ int fDigitsInResult = static_cast<int>(resultLength) - 1;
+ buf[i++] = '.';
+ if (fDigitsInResult > 0) {
+ if (fractionalDigits < fDigitsInResult) {
+ strncpy(buf + i, result + 1, fractionalDigits);
+ i += fractionalDigits;
+ } else {
+ // FIXME: Remove use of strcpy()
+ strcpy(buf + i, result + 1);
+ i += static_cast<int>(resultLength) - 1;
+ }
+ }
+
+ for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)
+ buf[i++] = '0';
+}
+
+static void exponentialPartToString(char* buf, int& i, int decimalPoint)
+{
+ buf[i++] = 'e';
+ // decimalPoint can't be more than 3 digits decimal given the
+ // nature of float representation
+ int exponential = decimalPoint - 1;
+ buf[i++] = (exponential >= 0) ? '+' : '-';
+ if (exponential < 0)
+ exponential *= -1;
+ if (exponential >= 100)
+ buf[i++] = static_cast<char>('0' + exponential / 100);
+ if (exponential >= 10)
+ buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+ buf[i++] = static_cast<char>('0' + exponential % 10);
+}
+
+JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double x = v.uncheckedGetNumber();
+
+ if (isnan(x) || isinf(x))
+ return jsString(exec, UString::from(x));
+
+ JSValuePtr fractionalDigitsValue = args.at(exec, 0);
+ double df = fractionalDigitsValue.toInteger(exec);
+ if (!(df >= 0 && df <= 20))
+ return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");
+ int fractionalDigits = static_cast<int>(df);
+ bool includeAllDigits = fractionalDigitsValue.isUndefined();
+
+ int decimalAdjust = 0;
+ if (x && !includeAllDigits) {
+ double logx = floor(log10(fabs(x)));
+ x /= pow(10.0, logx);
+ const double tenToTheF = pow(10.0, fractionalDigits);
+ double fx = floor(x * tenToTheF) / tenToTheF;
+ double cx = ceil(x * tenToTheF) / tenToTheF;
+
+ if (fabs(fx - x) < fabs(cx - x))
+ x = fx;
+ else
+ x = cx;
+
+ decimalAdjust = static_cast<int>(logx);
+ }
+
+ if (isnan(x))
+ return jsNontrivialString(exec, "NaN");
+
+ if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0
+ x = 0;
+
+ int decimalPoint;
+ int sign;
+ char* result = WTF::dtoa(x, 0, &decimalPoint, &sign, NULL);
+ size_t resultLength = strlen(result);
+ decimalPoint += decimalAdjust;
+
+ int i = 0;
+ char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)
+ if (sign)
+ buf[i++] = '-';
+
+ if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999??
+ // FIXME: Remove magic number 80
+ strlcpy(buf + i, result, 80 - i);
+ else {
+ buf[i++] = result[0];
+
+ if (includeAllDigits)
+ fractionalDigits = static_cast<int>(resultLength) - 1;
+
+ fractionalPartToString(buf, i, result, resultLength, fractionalDigits);
+ exponentialPartToString(buf, i, decimalPoint);
+ buf[i++] = '\0';
+ }
+ ASSERT(i <= 80);
+
+ WTF::freedtoa(result);
+
+ return jsString(exec, buf);
+}
+
+JSValuePtr numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSValuePtr v = thisValue.getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double doublePrecision = args.at(exec, 0).toIntegerPreserveNaN(exec);
+ double x = v.uncheckedGetNumber();
+ if (args.at(exec, 0).isUndefined() || isnan(x) || isinf(x))
+ return jsString(exec, v.toString(exec));
+
+ UString s;
+ if (x < 0) {
+ s = "-";
+ x = -x;
+ }
+
+ if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
+ return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
+ int precision = static_cast<int>(doublePrecision);
+
+ int e = 0;
+ UString m;
+ if (x) {
+ e = static_cast<int>(log10(x));
+ double tens = intPow10(e - precision + 1);
+ double n = floor(x / tens);
+ if (n < intPow10(precision - 1)) {
+ e = e - 1;
+ tens = intPow10(e - precision + 1);
+ n = floor(x / tens);
+ }
+
+ if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))
+ ++n;
+ // maintain n < 10^(precision)
+ if (n >= intPow10(precision)) {
+ n /= 10.0;
+ e += 1;
+ }
+ ASSERT(intPow10(precision - 1) <= n);
+ ASSERT(n < intPow10(precision));
+
+ m = integerPartNoExp(n);
+ if (e < -6 || e >= precision) {
+ if (m.size() > 1)
+ m = m.substr(0, 1) + "." + m.substr(1);
+ if (e >= 0)
+ return jsNontrivialString(exec, s + m + "e+" + UString::from(e));
+ return jsNontrivialString(exec, s + m + "e-" + UString::from(-e));
+ }
+ } else {
+ m = charSequence('0', precision);
+ e = 0;
+ }
+
+ if (e == precision - 1)
+ return jsString(exec, s + m);
+ if (e >= 0) {
+ if (e + 1 < m.size())
+ return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1));
+ return jsString(exec, s + m);
+ }
+ return jsNontrivialString(exec, s + "0." + charSequence('0', -(e + 1)) + m);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberPrototype_h
+#define NumberPrototype_h
+
+#include "NumberObject.h"
+
+namespace JSC {
+
+ class NumberPrototype : public NumberObject {
+ public:
+ NumberPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // NumberPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ObjectConstructor.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
+
+ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
+{
+ // ECMA 15.2.3.1
+ putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.2.2
+static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)
+{
+ JSValuePtr arg = args.at(exec, 0);
+ if (arg.isUndefinedOrNull())
+ return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+ return arg.toObject(exec);
+}
+
+static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructObject(exec, args);
+}
+
+ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithObjectConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValuePtr callObjectConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return constructObject(exec, args);
+}
+
+CallType ObjectConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callObjectConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ObjectConstructor_h
+#define ObjectConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class ObjectConstructor : public InternalFunction {
+ public:
+ ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // ObjectConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ObjectPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
+
+static JSValuePtr objectProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
+ : JSObject(stucture)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
+
+ // Mozilla extensions
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
+}
+
+// ------------------------------ Functions --------------------------------
+
+// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
+
+JSValuePtr objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ return thisValue.toThisObject(exec);
+}
+
+JSValuePtr objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0).toString(exec))));
+}
+
+JSValuePtr objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ if (!args.at(exec, 0).isObject())
+ return jsBoolean(false);
+
+ JSValuePtr v = asObject(args.at(exec, 0))->prototype();
+
+ while (true) {
+ if (!v.isObject())
+ return jsBoolean(false);
+ if (v == thisObj)\v
+ return jsBoolean(true);
+ v = asObject(v)->prototype();
+ }
+}
+
+JSValuePtr objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ CallData callData;
+ if (args.at(exec, 1).getCallData(callData) == CallTypeNone)
+ return throwError(exec, SyntaxError, "invalid getter usage");
+ thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)), asObject(args.at(exec, 1)));
+ return jsUndefined();
+}
+
+JSValuePtr objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ CallData callData;
+ if (args.at(exec, 1).getCallData(callData) == CallTypeNone)
+ return throwError(exec, SyntaxError, "invalid setter usage");
+ thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)), asObject(args.at(exec, 1)));
+ return jsUndefined();
+}
+
+JSValuePtr objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)));
+}
+
+JSValuePtr objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)));
+}
+
+JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0).toString(exec))));
+}
+
+JSValuePtr objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ return thisValue.toThisJSString(exec);
+}
+
+JSValuePtr objectProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]");
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ObjectPrototype_h
+#define ObjectPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class ObjectPrototype : public JSObject {
+ public:
+ ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ };
+
+ JSValuePtr objectProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+} // namespace JSC
+
+#endif // ObjectPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Operations.h"
+
+#include "Error.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include <math.h>
+#include <stdio.h>
+#include <wtf/MathExtras.h>
+
+#if HAVE(FLOAT_H)
+#include <float.h>
+#endif
+
+namespace JSC {
+
+bool JSValuePtr::equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+{
+ return equalSlowCaseInline(exec, v1, v2);
+}
+
+bool JSValuePtr::strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2)
+{
+ return strictEqualSlowCaseInline(v1, v2);
+}
+
+NEVER_INLINE JSValuePtr throwOutOfMemoryError(ExecState* exec)
+{
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ return error;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2002, 2005, 2006, 2007, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Operations_h
+#define Operations_h
+
+#include "JSImmediate.h"
+#include "JSNumberCell.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ // ECMA 11.9.3
+ inline bool JSValuePtr::equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+ {
+ if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ return v1 == v2;
+
+ return equalSlowCase(exec, v1, v2);
+ }
+
+ ALWAYS_INLINE bool JSValuePtr::equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2));
+
+ do {
+ if (v1.isNumber() && v2.isNumber())
+ return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
+
+ bool s1 = v1.isString();
+ bool s2 = v2.isString();
+ if (s1 && s2)
+ return asString(v1)->value() == asString(v2)->value();
+
+ if (v1.isUndefinedOrNull()) {
+ if (v2.isUndefinedOrNull())
+ return true;
+ if (JSImmediate::isImmediate(v2))
+ return false;
+ return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
+ }
+
+ if (v2.isUndefinedOrNull()) {
+ if (JSImmediate::isImmediate(v1))
+ return false;
+ return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined();
+ }
+
+ if (v1.isObject()) {
+ if (v2.isObject())
+ return v1 == v2;
+ JSValuePtr p1 = v1.toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v1 = p1;
+ if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ return v1 == v2;
+ continue;
+ }
+
+ if (v2.isObject()) {
+ JSValuePtr p2 = v2.toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v2 = p2;
+ if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ return v1 == v2;
+ continue;
+ }
+
+ if (s1 || s2) {
+ double d1 = v1.toNumber(exec);
+ double d2 = v2.toNumber(exec);
+ return d1 == d2;
+ }
+
+ if (v1.isBoolean()) {
+ if (v2.isNumber())
+ return static_cast<double>(v1.getBoolean()) == v2.uncheckedGetNumber();
+ } else if (v2.isBoolean()) {
+ if (v1.isNumber())
+ return v1.uncheckedGetNumber() == static_cast<double>(v2.getBoolean());
+ }
+
+ return v1 == v2;
+ } while (true);
+ }
+
+ // ECMA 11.9.3
+ inline bool JSValuePtr::strictEqual(JSValuePtr v1, JSValuePtr v2)
+ {
+ if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ return v1 == v2;
+
+ if (v1.isNumber() && v2.isNumber())
+ return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
+
+ if (JSImmediate::isEitherImmediate(v1, v2))
+ return v1 == v2;
+
+ return strictEqualSlowCase(v1, v2);
+ }
+
+ ALWAYS_INLINE bool JSValuePtr::strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2)
+ {
+ ASSERT(!JSImmediate::isEitherImmediate(v1, v2));
+
+ if (v1.asCell()->isString() && v2.asCell()->isString())
+ return asString(v1)->value() == asString(v2)->value();
+
+ return v1 == v2;
+ }
+
+ JSValuePtr throwOutOfMemoryError(ExecState*);
+
+}
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertyMapHashTable_h
+#define PropertyMapHashTable_h
+
+#include "UString.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ struct PropertyMapEntry {
+ UString::Rep* key;
+ unsigned offset;
+ unsigned attributes;
+ unsigned index;
+
+ PropertyMapEntry(UString::Rep* key, unsigned attributes)
+ : key(key)
+ , offset(0)
+ , attributes(attributes)
+ , index(0)
+ {
+ }
+
+ PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, unsigned index)
+ : key(key)
+ , offset(offset)
+ , attributes(attributes)
+ , index(index)
+ {
+ }
+ };
+
+ // lastIndexUsed is an ever-increasing index used to identify the order items
+ // were inserted into the property map. It's required that getEnumerablePropertyNames
+ // return the properties in the order they were added for compatibility with other
+ // browsers' JavaScript implementations.
+ struct PropertyMapHashTable {
+ unsigned sizeMask;
+ unsigned size;
+ unsigned keyCount;
+ unsigned deletedSentinelCount;
+ unsigned lastIndexUsed;
+ Vector<unsigned>* deletedOffsets;
+ unsigned entryIndices[1];
+
+ PropertyMapEntry* entries()
+ {
+ // The entries vector comes after the indices vector.
+ // The 0th item in the entries vector is not really used; it has to
+ // have a 0 in its key to allow the hash table lookup to handle deleted
+ // sentinels without any special-case code, but the other fields are unused.
+ return reinterpret_cast<PropertyMapEntry*>(&entryIndices[size]);
+ }
+
+ static size_t allocationSize(unsigned size)
+ {
+ // We never let a hash table get more than half full,
+ // So the number of indices we need is the size of the hash table.
+ // But the number of entries is half that (plus one for the deleted sentinel).
+ return sizeof(PropertyMapHashTable)
+ + (size - 1) * sizeof(unsigned)
+ + (1 + size / 2) * sizeof(PropertyMapEntry);
+ }
+ };
+
+} // namespace JSC
+
+#endif // PropertyMapHashTable_h
--- /dev/null
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+static const size_t setThreshold = 20;
+
+void PropertyNameArray::add(UString::Rep* identifier)
+{
+ ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->identifierTable());
+
+ size_t size = m_data->propertyNameVector().size();
+ if (size < setThreshold) {
+ for (size_t i = 0; i < size; ++i) {
+ if (identifier == m_data->propertyNameVector()[i].ustring().rep())
+ return;
+ }
+ } else {
+ if (m_set.isEmpty()) {
+ for (size_t i = 0; i < size; ++i)
+ m_set.add(m_data->propertyNameVector()[i].ustring().rep());
+ }
+ if (!m_set.add(identifier).second)
+ return;
+ }
+
+ m_data->propertyNameVector().append(Identifier(m_globalData, identifier));
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertyNameArray_h
+#define PropertyNameArray_h
+
+#include "CallFrame.h"
+#include "Identifier.h"
+#include "Structure.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
+ public:
+ typedef Vector<Identifier, 20> PropertyNameVector;
+ typedef PropertyNameVector::const_iterator const_iterator;
+
+ static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
+
+ const_iterator begin() const { return m_propertyNameVector.begin(); }
+ const_iterator end() const { return m_propertyNameVector.end(); }
+
+ PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
+
+ void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
+ Structure* cachedStructure() const { return m_cachedStructure; }
+
+ void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+
+ private:
+ PropertyNameArrayData()
+ : m_cachedStructure(0)
+ {
+ }
+
+ PropertyNameVector m_propertyNameVector;
+ Structure* m_cachedStructure;
+ RefPtr<StructureChain> m_cachedPrototypeChain;
+ };
+
+ class PropertyNameArray {
+ public:
+ typedef PropertyNameArrayData::const_iterator const_iterator;
+
+ PropertyNameArray(JSGlobalData* globalData)
+ : m_data(PropertyNameArrayData::create())
+ , m_globalData(globalData)
+ , m_shouldCache(true)
+ {
+ }
+
+ PropertyNameArray(ExecState* exec)
+ : m_data(PropertyNameArrayData::create())
+ , m_globalData(&exec->globalData())
+ , m_shouldCache(true)
+ {
+ }
+
+ JSGlobalData* globalData() { return m_globalData; }
+
+ void add(const Identifier& identifier) { add(identifier.ustring().rep()); }
+ void add(UString::Rep*);
+ void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
+
+ size_t size() const { return m_data->propertyNameVector().size(); }
+
+ Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
+ const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
+
+ const_iterator begin() const { return m_data->begin(); }
+ const_iterator end() const { return m_data->end(); }
+
+ void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
+ PropertyNameArrayData* data() { return m_data.get(); }
+
+ PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
+
+ void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; }
+ bool shouldCache() const { return m_shouldCache; }
+
+ private:
+ typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
+
+ RefPtr<PropertyNameArrayData> m_data;
+ IdentifierSet m_set;
+ JSGlobalData* m_globalData;
+ bool m_shouldCache;
+ };
+
+} // namespace JSC
+
+#endif // PropertyNameArray_h
--- /dev/null
+/*
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PropertySlot.h"
+
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+JSValuePtr PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ // Prevent getter functions from observing execution if an exception is pending.
+ if (exec->hadException())
+ return exec->exception();
+
+ CallData callData;
+ CallType callType = slot.m_data.getterFunc->getCallData(callData);
+ if (callType == CallTypeHost)
+ return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
+ ASSERT(callType == CallTypeJS);
+ // FIXME: Can this be done more efficiently using the callData?
+ return static_cast<JSFunction*>(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertySlot_h
+#define PropertySlot_h
+
+#include "Identifier.h"
+#include "JSValue.h"
+#include "JSImmediate.h"
+#include "Register.h"
+#include <wtf/Assertions.h>
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSObject;
+
+#define JSC_VALUE_SLOT_MARKER 0
+#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
+
+ class PropertySlot {
+ public:
+ PropertySlot()
+ : m_offset(WTF::notFound)
+ {
+ clearBase();
+ clearValue();
+ }
+
+ explicit PropertySlot(const JSValuePtr base)
+ : m_slotBase(base)
+ , m_offset(WTF::notFound)
+ {
+ clearValue();
+ }
+
+ typedef JSValuePtr (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
+
+ JSValuePtr getValue(ExecState* exec, const Identifier& propertyName) const
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER)
+ return *m_data.valueSlot;
+ if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+ return (*m_data.registerSlot).jsValue(exec);
+ return m_getValue(exec, propertyName, *this);
+ }
+
+ JSValuePtr getValue(ExecState* exec, unsigned propertyName) const
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER)
+ return *m_data.valueSlot;
+ if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+ return (*m_data.registerSlot).jsValue(exec);
+ return m_getValue(exec, Identifier::from(exec, propertyName), *this);
+ }
+
+ bool isCacheable() const { return m_offset != WTF::notFound; }
+ size_t cachedOffset() const
+ {
+ ASSERT(isCacheable());
+ return m_offset;
+ }
+
+ void putValue(JSValuePtr value)
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER) {
+ *m_data.valueSlot = value;
+ return;
+ }
+ ASSERT(m_getValue == JSC_REGISTER_SLOT_MARKER);
+ *m_data.registerSlot = JSValuePtr(value);
+ }
+
+ void setValueSlot(JSValuePtr* valueSlot)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ clearBase();
+ m_data.valueSlot = valueSlot;
+ }
+
+ void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ m_slotBase = slotBase;
+ m_data.valueSlot = valueSlot;
+ }
+
+ void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot, size_t offset)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ m_slotBase = slotBase;
+ m_data.valueSlot = valueSlot;
+ m_offset = offset;
+ }
+
+ void setValue(JSValuePtr value)
+ {
+ ASSERT(value);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ clearBase();
+ m_value = value;
+ m_data.valueSlot = &m_value;
+ }
+
+ void setRegisterSlot(Register* registerSlot)
+ {
+ ASSERT(registerSlot);
+ m_getValue = JSC_REGISTER_SLOT_MARKER;
+ clearBase();
+ m_data.registerSlot = registerSlot;
+ }
+
+ void setCustom(JSValuePtr slotBase, GetValueFunc getValue)
+ {
+ ASSERT(slotBase);
+ ASSERT(getValue);
+ m_getValue = getValue;
+ m_slotBase = slotBase;
+ }
+
+ void setCustomIndex(JSValuePtr slotBase, unsigned index, GetValueFunc getValue)
+ {
+ ASSERT(slotBase);
+ ASSERT(getValue);
+ m_getValue = getValue;
+ m_slotBase = slotBase;
+ m_data.index = index;
+ }
+
+ void setGetterSlot(JSObject* getterFunc)
+ {
+ ASSERT(getterFunc);
+ m_getValue = functionGetter;
+ m_data.getterFunc = getterFunc;
+ }
+
+ void setUndefined()
+ {
+ clearBase();
+ setValue(jsUndefined());
+ }
+
+ JSValuePtr slotBase() const
+ {
+ ASSERT(m_slotBase);
+ return m_slotBase;
+ }
+
+ void setBase(JSValuePtr base)
+ {
+ ASSERT(m_slotBase);
+ ASSERT(base);
+ m_slotBase = base;
+ }
+
+ void clearBase()
+ {
+#ifndef NDEBUG
+ m_slotBase = noValue();
+#endif
+ }
+
+ void clearValue()
+ {
+#ifndef NDEBUG
+ m_value = noValue();
+#endif
+ }
+
+ unsigned index() const { return m_data.index; }
+
+ private:
+ static JSValuePtr functionGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ GetValueFunc m_getValue;
+
+ JSValuePtr m_slotBase;
+ union {
+ JSObject* getterFunc;
+ JSValuePtr* valueSlot;
+ Register* registerSlot;
+ unsigned index;
+ } m_data;
+
+ JSValuePtr m_value;
+
+ size_t m_offset;
+ };
+
+} // namespace JSC
+
+#endif // PropertySlot_h
--- /dev/null
+/*
+ * Copyright (C) 2004, 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 Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#ifndef Protect_h
+#define Protect_h
+
+#include "JSCell.h"
+#include "Collector.h"
+
+namespace JSC {
+
+ inline void gcProtect(JSCell* val)
+ {
+ Heap::heap(val)->protect(val);
+ }
+
+ inline void gcUnprotect(JSCell* val)
+ {
+ Heap::heap(val)->unprotect(val);
+ }
+
+ inline void gcProtectNullTolerant(JSCell* val)
+ {
+ if (val)
+ gcProtect(val);
+ }
+
+ inline void gcUnprotectNullTolerant(JSCell* val)
+ {
+ if (val)
+ gcUnprotect(val);
+ }
+
+ inline void gcProtect(JSValuePtr value)
+ {
+ if (value && value.isCell())
+ gcProtect(asCell(value));
+ }
+
+ inline void gcUnprotect(JSValuePtr value)
+ {
+ if (value && value.isCell())
+ gcUnprotect(asCell(value));
+ }
+
+ // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
+ // and the implicit conversion to raw pointer
+ template <class T> class ProtectedPtr {
+ public:
+ ProtectedPtr() : m_ptr(0) {}
+ ProtectedPtr(T* ptr);
+ ProtectedPtr(const ProtectedPtr&);
+ ~ProtectedPtr();
+
+ template <class U> ProtectedPtr(const ProtectedPtr<U>&);
+
+ T* get() const { return m_ptr; }
+ operator T*() const { return m_ptr; }
+ operator JSValuePtr() const { return JSValuePtr(m_ptr); }
+ T* operator->() const { return m_ptr; }
+
+ operator bool() const { return m_ptr; }
+ bool operator!() const { return !m_ptr; }
+
+ ProtectedPtr& operator=(const ProtectedPtr&);
+ ProtectedPtr& operator=(T*);
+
+ private:
+ T* m_ptr;
+ };
+
+ class ProtectedJSValuePtr {
+ public:
+ ProtectedJSValuePtr() {}
+ ProtectedJSValuePtr(JSValuePtr value);
+ ProtectedJSValuePtr(const ProtectedJSValuePtr&);
+ ~ProtectedJSValuePtr();
+
+ template <class U> ProtectedJSValuePtr(const ProtectedPtr<U>&);
+
+ JSValuePtr get() const { return m_value; }
+ operator JSValuePtr() const { return m_value; }
+ JSValuePtr operator->() const { return m_value; }
+
+ operator bool() const { return m_value; }
+ bool operator!() const { return !m_value; }
+
+ ProtectedJSValuePtr& operator=(const ProtectedJSValuePtr&);
+ ProtectedJSValuePtr& operator=(JSValuePtr);
+
+ private:
+ JSValuePtr m_value;
+ };
+
+ template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr)
+ : m_ptr(ptr)
+ {
+ gcProtectNullTolerant(m_ptr);
+ }
+
+ template <class T> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
+ : m_ptr(o.get())
+ {
+ gcProtectNullTolerant(m_ptr);
+ }
+
+ template <class T> inline ProtectedPtr<T>::~ProtectedPtr()
+ {
+ gcUnprotectNullTolerant(m_ptr);
+ }
+
+ template <class T> template <class U> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
+ : m_ptr(o.get())
+ {
+ gcProtectNullTolerant(m_ptr);
+ }
+
+ template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o)
+ {
+ T* optr = o.m_ptr;
+ gcProtectNullTolerant(optr);
+ gcUnprotectNullTolerant(m_ptr);
+ m_ptr = optr;
+ return *this;
+ }
+
+ template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
+ {
+ gcProtectNullTolerant(optr);
+ gcUnprotectNullTolerant(m_ptr);
+ m_ptr = optr;
+ return *this;
+ }
+
+ inline ProtectedJSValuePtr::ProtectedJSValuePtr(JSValuePtr value)
+ : m_value(value)
+ {
+ gcProtect(m_value);
+ }
+
+ inline ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedJSValuePtr& o)
+ : m_value(o.get())
+ {
+ gcProtect(m_value);
+ }
+
+ inline ProtectedJSValuePtr::~ProtectedJSValuePtr()
+ {
+ gcUnprotect(m_value);
+ }
+
+ template <class U> ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedPtr<U>& o)
+ : m_value(o.get())
+ {
+ gcProtect(m_value);
+ }
+
+ inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(const ProtectedJSValuePtr& o)
+ {
+ JSValuePtr ovalue = o.m_value;
+ gcProtect(ovalue);
+ gcUnprotect(m_value);
+ m_value = ovalue;
+ return *this;
+ }
+
+ inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(JSValuePtr ovalue)
+ {
+ gcProtect(ovalue);
+ gcUnprotect(m_value);
+ m_value = ovalue;
+ return *this;
+ }
+
+ template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
+ template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
+ template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
+
+ template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
+ template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
+ template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
+
+ inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() == b.get(); }
+ inline bool operator==(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() == b; }
+ template <class T> inline bool operator==(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() == JSValuePtr(b.get()); }
+ inline bool operator==(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a == b.get(); }
+ template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) == b.get(); }
+
+ inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedJSValuePtr& b) { return a.get() != b.get(); }
+ inline bool operator!=(const ProtectedJSValuePtr& a, const JSValuePtr b) { return a.get() != b; }
+ template <class T> inline bool operator!=(const ProtectedJSValuePtr& a, const ProtectedPtr<T>& b) { return a.get() != JSValuePtr(b.get()); }
+ inline bool operator!=(const JSValuePtr a, const ProtectedJSValuePtr& b) { return a != b.get(); }
+ template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValuePtr& b) { return JSValuePtr(a.get()) != b.get(); }
+
+} // namespace JSC
+
+#endif // Protect_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PrototypeFunction.h"
+
+#include "JSGlobalObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(PrototypeFunction);
+
+PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifier& name, NativeFunction function)
+ : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), name)
+ , m_function(function)
+{
+ ASSERT_ARG(function, function);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+}
+
+PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
+ : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
+ , m_function(function)
+{
+ ASSERT_ARG(function, function);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+}
+
+CallType PrototypeFunction::getCallData(CallData& callData)
+{
+ callData.native.function = m_function;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PrototypeFunction_h
+#define PrototypeFunction_h
+
+#include "InternalFunction.h"
+#include "CallData.h"
+
+namespace JSC {
+
+ class PrototypeFunction : public InternalFunction {
+ public:
+ PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
+ PrototypeFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
+
+ private:
+ virtual CallType getCallData(CallData&);
+
+ const NativeFunction m_function;
+ };
+
+} // namespace JSC
+
+#endif // PrototypeFunction_h
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PutPropertySlot_h
+#define PutPropertySlot_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ class JSObject;
+
+ class PutPropertySlot {
+ public:
+ enum Type { Invalid, ExistingProperty, NewProperty };
+
+ PutPropertySlot()
+ : m_type(Invalid)
+ , m_base(0)
+ , m_wasTransition(false)
+ {
+ }
+
+ void setExistingProperty(JSObject* base, size_t offset)
+ {
+ m_type = ExistingProperty;
+ m_base = base;
+ m_offset = offset;
+ }
+
+ void setNewProperty(JSObject* base, size_t offset)
+ {
+ m_type = NewProperty;
+ m_base = base;
+ m_offset = offset;
+ }
+
+ Type type() const { return m_type; }
+ JSObject* base() const { return m_base; }
+
+ bool isCacheable() const { return m_type != Invalid; }
+ size_t cachedOffset() const {
+ ASSERT(isCacheable());
+ return m_offset;
+ }
+
+ bool wasTransition() const { return m_wasTransition; }
+ void setWasTransition(bool wasTransition) { m_wasTransition = wasTransition; }
+ private:
+ Type m_type;
+ JSObject* m_base;
+ bool m_wasTransition;
+ size_t m_offset;
+ };
+
+} // namespace JSC
+
+#endif // PutPropertySlot_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
+ * Copyright (c) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExp.h"
+
+#include "JIT.h"
+#include "Lexer.h"
+#include "WRECGenerator.h"
+#include <pcre/pcre.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/Assertions.h>
+#include <wtf/OwnArrayPtr.h>
+
+namespace JSC {
+
+#if ENABLE(WREC)
+using namespace WREC;
+#endif
+
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
+ : m_pattern(pattern)
+ , m_flagBits(0)
+ , m_regExp(0)
+ , m_constructionError(0)
+ , m_numSubpatterns(0)
+{
+#if ENABLE(WREC)
+ m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool);
+ if (m_wrecFunction || m_constructionError)
+ return;
+ // Fall through to non-WREC case.
+#else
+ UNUSED_PARAM(globalData);
+#endif
+ m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+ JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
+}
+
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
+{
+ return adoptRef(new RegExp(globalData, pattern));
+}
+
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+ : m_pattern(pattern)
+ , m_flags(flags)
+ , m_flagBits(0)
+ , m_regExp(0)
+ , m_constructionError(0)
+ , m_numSubpatterns(0)
+{
+ // NOTE: The global flag is handled on a case-by-case basis by functions like
+ // String::match and RegExpObject::match.
+ if (flags.find('g') != -1)
+ m_flagBits |= Global;
+
+ // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
+ JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
+ if (flags.find('i') != -1) {
+ m_flagBits |= IgnoreCase;
+ ignoreCaseOption = JSRegExpIgnoreCase;
+ }
+
+ JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
+ if (flags.find('m') != -1) {
+ m_flagBits |= Multiline;
+ multilineOption = JSRegExpMultiline;
+ }
+
+#if ENABLE(WREC)
+ m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
+ if (m_wrecFunction || m_constructionError)
+ return;
+ // Fall through to non-WREC case.
+#else
+ UNUSED_PARAM(globalData);
+#endif
+ m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+ ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+}
+
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+{
+ return adoptRef(new RegExp(globalData, pattern, flags));
+}
+
+RegExp::~RegExp()
+{
+ jsRegExpFree(m_regExp);
+}
+
+int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
+{
+ if (startOffset < 0)
+ startOffset = 0;
+ if (ovector)
+ ovector->clear();
+
+ if (startOffset > s.size() || s.isNull())
+ return -1;
+
+#if ENABLE(WREC)
+ if (m_wrecFunction) {
+ int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+ int* offsetVector = new int [offsetVectorSize];
+ for (int j = 0; j < offsetVectorSize; ++j)
+ offsetVector[j] = -1;
+
+ OwnArrayPtr<int> nonReturnedOvector;
+ if (!ovector)
+ nonReturnedOvector.set(offsetVector);
+ else
+ ovector->set(offsetVector);
+
+ int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector);
+
+ if (result < 0) {
+#ifndef NDEBUG
+ // TODO: define up a symbol, rather than magic -1
+ if (result != -1)
+ fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
+#endif
+ if (ovector)
+ ovector->clear();
+ }
+ return result;
+ } else
+#endif
+ if (m_regExp) {
+ // Set up the offset vector for the result.
+ // First 2/3 used for result, the last third used by PCRE.
+ int* offsetVector;
+ int offsetVectorSize;
+ int fixedSizeOffsetVector[3];
+ if (!ovector) {
+ offsetVectorSize = 3;
+ offsetVector = fixedSizeOffsetVector;
+ } else {
+ offsetVectorSize = (m_numSubpatterns + 1) * 3;
+ offsetVector = new int [offsetVectorSize];
+ ovector->set(offsetVector);
+ }
+
+ int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
+
+ if (numMatches < 0) {
+#ifndef NDEBUG
+ if (numMatches != JSRegExpErrorNoMatch)
+ fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
+#endif
+ if (ovector)
+ ovector->clear();
+ return -1;
+ }
+
+ return offsetVector[0];
+ }
+
+ return -1;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExp_h
+#define RegExp_h
+
+#include "UString.h"
+#include "WREC.h"
+#include "ExecutableAllocator.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+struct JSRegExp;
+
+namespace JSC {
+
+ class JSGlobalData;
+
+ class RegExp : public RefCounted<RegExp> {
+ public:
+ static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern);
+ static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+ ~RegExp();
+
+ bool global() const { return m_flagBits & Global; }
+ bool ignoreCase() const { return m_flagBits & IgnoreCase; }
+ bool multiline() const { return m_flagBits & Multiline; }
+
+ const UString& pattern() const { return m_pattern; }
+ const UString& flags() const { return m_flags; }
+
+ bool isValid() const { return !m_constructionError; }
+ const char* errorMessage() const { return m_constructionError; }
+
+ int match(const UString&, int startOffset, OwnArrayPtr<int>* ovector = 0);
+ unsigned numSubpatterns() const { return m_numSubpatterns; }
+
+ private:
+ RegExp(JSGlobalData* globalData, const UString& pattern);
+ RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+
+ void compile();
+
+ enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
+
+ UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
+ UString m_flags; // FIXME: Just decompile m_regExp instead of storing this.
+ int m_flagBits;
+ JSRegExp* m_regExp;
+ const char* m_constructionError;
+ unsigned m_numSubpatterns;
+
+#if ENABLE(WREC)
+ WREC::CompiledRegExp m_wrecFunction;
+ RefPtr<ExecutablePool> m_executablePool;
+#endif
+ };
+
+} // namespace JSC
+
+#endif // RegExp_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpConstructor.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "RegExp.h"
+
+namespace JSC {
+
+static JSValuePtr regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&);
+
+static void setRegExpConstructorInput(ExecState*, JSObject*, JSValuePtr);
+static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValuePtr);
+
+} // namespace JSC
+
+#include "RegExpConstructor.lut.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
+
+const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
+
+/* Source for RegExpConstructor.lut.h
+@begin regExpConstructorTable
+ input regExpConstructorInput None
+ $_ regExpConstructorInput DontEnum
+ multiline regExpConstructorMultiline None
+ $* regExpConstructorMultiline DontEnum
+ lastMatch regExpConstructorLastMatch DontDelete|ReadOnly
+ $& regExpConstructorLastMatch DontDelete|ReadOnly|DontEnum
+ lastParen regExpConstructorLastParen DontDelete|ReadOnly
+ $+ regExpConstructorLastParen DontDelete|ReadOnly|DontEnum
+ leftContext regExpConstructorLeftContext DontDelete|ReadOnly
+ $` regExpConstructorLeftContext DontDelete|ReadOnly|DontEnum
+ rightContext regExpConstructorRightContext DontDelete|ReadOnly
+ $' regExpConstructorRightContext DontDelete|ReadOnly|DontEnum
+ $1 regExpConstructorDollar1 DontDelete|ReadOnly
+ $2 regExpConstructorDollar2 DontDelete|ReadOnly
+ $3 regExpConstructorDollar3 DontDelete|ReadOnly
+ $4 regExpConstructorDollar4 DontDelete|ReadOnly
+ $5 regExpConstructorDollar5 DontDelete|ReadOnly
+ $6 regExpConstructorDollar6 DontDelete|ReadOnly
+ $7 regExpConstructorDollar7 DontDelete|ReadOnly
+ $8 regExpConstructorDollar8 DontDelete|ReadOnly
+ $9 regExpConstructorDollar9 DontDelete|ReadOnly
+@end
+*/
+
+struct RegExpConstructorPrivate {
+ // Global search cache / settings
+ RegExpConstructorPrivate()
+ : lastNumSubPatterns(0)
+ , multiline(false)
+ {
+ }
+
+ UString input;
+ UString lastInput;
+ OwnArrayPtr<int> lastOvector;
+ unsigned lastNumSubPatterns : 31;
+ bool multiline : 1;
+};
+
+RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
+ , d(new RegExpConstructorPrivate)
+{
+ // ECMA 15.10.5.1 RegExp.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
+}
+
+/*
+ To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
+ expression matching through the performMatch function. We use cached results to calculate,
+ e.g., RegExp.lastMatch and RegExp.leftParen.
+*/
+void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+{
+ OwnArrayPtr<int> tmpOvector;
+ position = r->match(s, startOffset, &tmpOvector);
+
+ if (ovector)
+ *ovector = tmpOvector.get();
+
+ if (position != -1) {
+ ASSERT(tmpOvector);
+
+ length = tmpOvector[1] - tmpOvector[0];
+
+ d->input = s;
+ d->lastInput = s;
+ d->lastOvector.set(tmpOvector.release());
+ d->lastNumSubPatterns = r->numSubpatterns();
+ }
+}
+
+RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
+ : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
+{
+ RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
+ d->input = data->lastInput;
+ d->lastInput = data->lastInput;
+ d->lastNumSubPatterns = data->lastNumSubPatterns;
+ unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
+ d->lastOvector.set(new int[offsetVectorSize]);
+ memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int));
+ // d->multiline is not needed, and remains uninitialized
+
+ setLazyCreationData(d);
+}
+
+RegExpMatchesArray::~RegExpMatchesArray()
+{
+ delete static_cast<RegExpConstructorPrivate*>(lazyCreationData());
+}
+
+void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
+{
+ RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData());
+ ASSERT(d);
+
+ unsigned lastNumSubpatterns = d->lastNumSubPatterns;
+
+ for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start));
+ }
+
+ PutPropertySlot slot;
+ JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0]), slot);
+ JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot);
+
+ delete d;
+ setLazyCreationData(0);
+}
+
+JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
+{
+ return new (exec) RegExpMatchesArray(exec, d.get());
+}
+
+JSValuePtr RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
+{
+ if (d->lastOvector && i <= d->lastNumSubPatterns) {
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+ }
+ return jsEmptyString(exec);
+}
+
+JSValuePtr RegExpConstructor::getLastParen(ExecState* exec) const
+{
+ unsigned i = d->lastNumSubPatterns;
+ if (i > 0) {
+ ASSERT(d->lastOvector);
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+ }
+ return jsEmptyString(exec);
+}
+
+JSValuePtr RegExpConstructor::getLeftContext(ExecState* exec) const
+{
+ if (d->lastOvector)
+ return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]);
+ return jsEmptyString(exec);
+}
+
+JSValuePtr RegExpConstructor::getRightContext(ExecState* exec) const
+{
+ if (d->lastOvector)
+ return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]);
+ return jsEmptyString(exec);
+}
+
+bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
+}
+
+JSValuePtr regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
+}
+
+JSValuePtr regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2);
+}
+
+JSValuePtr regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3);
+}
+
+JSValuePtr regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4);
+}
+
+JSValuePtr regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5);
+}
+
+JSValuePtr regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6);
+}
+
+JSValuePtr regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7);
+}
+
+JSValuePtr regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8);
+}
+
+JSValuePtr regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9);
+}
+
+JSValuePtr regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsString(exec, asRegExpConstructor(slot.slotBase())->input());
+}
+
+JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline());
+}
+
+JSValuePtr regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0);
+}
+
+JSValuePtr regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getLastParen(exec);
+}
+
+JSValuePtr regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getLeftContext(exec);
+}
+
+JSValuePtr regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getRightContext(exec);
+}
+
+void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot);
+}
+
+void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+{
+ asRegExpConstructor(baseObject)->setInput(value.toString(exec));
+}
+
+void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+{
+ asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
+}
+
+// ECMA 15.10.4
+JSObject* constructRegExp(ExecState* exec, const ArgList& args)
+{
+ JSValuePtr arg0 = args.at(exec, 0);
+ JSValuePtr arg1 = args.at(exec, 1);
+
+ if (arg0.isObject(&RegExpObject::info)) {
+ if (!arg1.isUndefined())
+ return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+ return asObject(arg0);
+ }
+
+ UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
+ UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
+
+ RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ if (!regExp->isValid())
+ return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+ return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+}
+
+static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructRegExp(exec, args);
+}
+
+ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithRegExpConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.10.3
+static JSValuePtr callRegExpConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ return constructRegExp(exec, args);
+}
+
+CallType RegExpConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callRegExpConstructor;
+ return CallTypeHost;
+}
+
+void RegExpConstructor::setInput(const UString& input)
+{
+ d->input = input;
+}
+
+const UString& RegExpConstructor::input() const
+{
+ // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
+ // state (since jsString turns null strings to empty strings).
+ return d->input;
+}
+
+void RegExpConstructor::setMultiline(bool multiline)
+{
+ d->multiline = multiline;
+}
+
+bool RegExpConstructor::multiline() const
+{
+ return d->multiline;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpConstructor_h
+#define RegExpConstructor_h
+
+#include "InternalFunction.h"
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class RegExp;
+ class RegExpPrototype;
+ struct RegExpConstructorPrivate;
+
+ class RegExpConstructor : public InternalFunction {
+ public:
+ RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*);
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ static const ClassInfo info;
+
+ void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
+ JSObject* arrayOfMatches(ExecState*) const;
+
+ void setInput(const UString&);
+ const UString& input() const;
+
+ void setMultiline(bool);
+ bool multiline() const;
+
+ JSValuePtr getBackref(ExecState*, unsigned) const;
+ JSValuePtr getLastParen(ExecState*) const;
+ JSValuePtr getLeftContext(ExecState*) const;
+ JSValuePtr getRightContext(ExecState*) const;
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ OwnPtr<RegExpConstructorPrivate> d;
+ };
+
+ RegExpConstructor* asRegExpConstructor(JSValuePtr);
+
+ JSObject* constructRegExp(ExecState*, const ArgList&);
+
+ inline RegExpConstructor* asRegExpConstructor(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+ return static_cast<RegExpConstructor*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // RegExpConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpMatchesArray_h
+#define RegExpMatchesArray_h
+
+#include "JSArray.h"
+
+namespace JSC {
+
+ class RegExpMatchesArray : public JSArray {
+ public:
+ RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*);
+ virtual ~RegExpMatchesArray();
+
+ private:
+ virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+ }
+
+ virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+ }
+
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr v, PutPropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::put(exec, propertyName, v, slot);
+ }
+
+ virtual void put(ExecState* exec, unsigned propertyName, JSValuePtr v)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::put(exec, propertyName, v);
+ }
+
+ virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::deleteProperty(exec, propertyName);
+ }
+
+ virtual bool deleteProperty(ExecState* exec, unsigned propertyName)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::deleteProperty(exec, propertyName);
+ }
+
+ virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::getPropertyNames(exec, arr);
+ }
+
+ void fillArrayInstance(ExecState*);
+};
+
+}
+
+#endif // RegExpMatchesArray_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpObject.h"
+
+#include "JSArray.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "RegExpConstructor.h"
+#include "RegExpPrototype.h"
+
+namespace JSC {
+
+static JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
+static JSValuePtr regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
+static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValuePtr);
+
+} // namespace JSC
+
+#include "RegExpObject.lut.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
+
+const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
+
+/* Source for RegExpObject.lut.h
+@begin regExpTable
+ global regExpObjectGlobal DontDelete|ReadOnly|DontEnum
+ ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum
+ multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum
+ source regExpObjectSource DontDelete|ReadOnly|DontEnum
+ lastIndex regExpObjectLastIndex DontDelete|DontEnum
+@end
+*/
+
+RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp)
+ : JSObject(structure)
+ , d(new RegExpObjectData(regExp, 0))
+{
+}
+
+RegExpObject::~RegExpObject()
+{
+}
+
+bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
+}
+
+JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
+}
+
+JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase());
+}
+
+JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline());
+}
+
+JSValuePtr regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern());
+}
+
+JSValuePtr regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex());
+}
+
+void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
+}
+
+void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+{
+ asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec));
+}
+
+JSValuePtr RegExpObject::test(ExecState* exec, const ArgList& args)
+{
+ return jsBoolean(match(exec, args));
+}
+
+JSValuePtr RegExpObject::exec(ExecState* exec, const ArgList& args)
+{
+ if (match(exec, args))
+ return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
+ return jsNull();
+}
+
+static JSValuePtr callRegExpObject(ExecState* exec, JSObject* function, JSValuePtr, const ArgList& args)
+{
+ return asRegExpObject(function)->exec(exec, args);
+}
+
+CallType RegExpObject::getCallData(CallData& callData)
+{
+ callData.native.function = callRegExpObject;
+ return CallTypeHost;
+}
+
+// Shared implementation used by test and exec.
+bool RegExpObject::match(ExecState* exec, const ArgList& args)
+{
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+
+ UString input = args.isEmpty() ? regExpConstructor->input() : args.at(exec, 0).toString(exec);
+ if (input.isNull()) {
+ throwError(exec, GeneralError, "No input to " + toString(exec) + ".");
+ return false;
+ }
+
+ if (!regExp()->global()) {
+ int position;
+ int length;
+ regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length);
+ return position >= 0;
+ }
+
+ if (d->lastIndex < 0 || d->lastIndex > input.size()) {
+ d->lastIndex = 0;
+ return false;
+ }
+
+ int position;
+ int length;
+ regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
+ if (position < 0) {
+ d->lastIndex = 0;
+ return false;
+ }
+
+ d->lastIndex = position + length;
+ return true;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpObject_h
+#define RegExpObject_h
+
+#include "JSObject.h"
+#include "RegExp.h"
+
+namespace JSC {
+
+ class RegExpObject : public JSObject {
+ public:
+ RegExpObject(PassRefPtr<Structure>, PassRefPtr<RegExp>);
+ virtual ~RegExpObject();
+
+ void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
+ RegExp* regExp() const { return d->regExp.get(); }
+
+ void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; }
+ double lastIndex() const { return d->lastIndex; }
+
+ JSValuePtr test(ExecState*, const ArgList&);
+ JSValuePtr exec(ExecState*, const ArgList&);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ bool match(ExecState*, const ArgList&);
+
+ virtual CallType getCallData(CallData&);
+
+ struct RegExpObjectData {
+ RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex)
+ : regExp(regExp)
+ , lastIndex(lastIndex)
+ {
+ }
+
+ RefPtr<RegExp> regExp;
+ double lastIndex;
+ };
+
+ OwnPtr<RegExpObjectData> d;
+ };
+
+ RegExpObject* asRegExpObject(JSValuePtr);
+
+ inline RegExpObject* asRegExpObject(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&RegExpObject::info));
+ return static_cast<RegExpObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // RegExpObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpPrototype.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include "RegExpObject.h"
+#include "RegExp.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
+
+static JSValuePtr regExpProtoFuncTest(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr regExpProtoFuncExec(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr regExpProtoFuncCompile(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr regExpProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+// ECMA 15.10.5
+
+const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
+
+RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ : JSObject(structure)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
+}
+
+// ------------------------------ Functions ---------------------------
+
+JSValuePtr regExpProtoFuncTest(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+ return asRegExpObject(thisValue)->test(exec, args);
+}
+
+JSValuePtr regExpProtoFuncExec(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+ return asRegExpObject(thisValue)->exec(exec, args);
+}
+
+JSValuePtr regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (!thisValue.isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+
+ RefPtr<RegExp> regExp;
+ JSValuePtr arg0 = args.at(exec, 0);
+ JSValuePtr arg1 = args.at(exec, 1);
+
+ if (arg0.isObject(&RegExpObject::info)) {
+ if (!arg1.isUndefined())
+ return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+ regExp = asRegExpObject(arg0)->regExp();
+ } else {
+ UString pattern = args.isEmpty() ? UString("") : arg0.toString(exec);
+ UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
+ regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ }
+
+ if (!regExp->isValid())
+ return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+
+ asRegExpObject(thisValue)->setRegExp(regExp.release());
+ asRegExpObject(thisValue)->setLastIndex(0);
+ return jsUndefined();
+}
+
+JSValuePtr regExpProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ if (!thisValue.isObject(&RegExpObject::info)) {
+ if (thisValue.isObject(&RegExpPrototype::info))
+ return jsNontrivialString(exec, "//");
+ return throwError(exec, TypeError);
+ }
+
+ UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec);
+ result.append('/');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec))
+ result.append('g');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
+ result.append('i');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec))
+ result.append('m');
+ return jsNontrivialString(exec, result);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpPrototype_h
+#define RegExpPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class RegExpPrototype : public JSObject {
+ public:
+ RegExpPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // RegExpPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ScopeChain.h"
+
+#include "JSActivation.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "PropertyNameArray.h"
+#include <stdio.h>
+
+namespace JSC {
+
+#ifndef NDEBUG
+
+void ScopeChainNode::print() const
+{
+ ScopeChainIterator scopeEnd = end();
+ for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
+ JSObject* o = *scopeIter;
+ PropertyNameArray propertyNames(globalObject()->globalExec());
+ o->getPropertyNames(globalObject()->globalExec(), propertyNames);
+ PropertyNameArray::const_iterator propEnd = propertyNames.end();
+
+ fprintf(stderr, "----- [scope %p] -----\n", o);
+ for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
+ Identifier name = *propIter;
+ fprintf(stderr, "%s, ", name.ascii());
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+#endif
+
+int ScopeChain::localDepth() const
+{
+ int scopeDepth = 0;
+ ScopeChainIterator iter = this->begin();
+ ScopeChainIterator end = this->end();
+ while (!(*iter)->isObject(&JSActivation::info)) {
+ ++iter;
+ if (iter == end)
+ break;
+ ++scopeDepth;
+ }
+ return scopeDepth;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScopeChain_h
+#define ScopeChain_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ class JSGlobalData;
+ class JSGlobalObject;
+ class JSObject;
+ class ScopeChainIterator;
+
+ class ScopeChainNode {
+ public:
+ ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
+ : next(next)
+ , object(object)
+ , globalData(globalData)
+ , globalThis(globalThis)
+ , refCount(1)
+ {
+ ASSERT(globalData);
+ }
+
+ ScopeChainNode* next;
+ JSObject* object;
+ JSGlobalData* globalData;
+ JSObject* globalThis;
+ int refCount;
+
+ void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
+ void ref() { ASSERT(refCount); ++refCount; }
+ void release();
+
+ // Before calling "push" on a bare ScopeChainNode, a client should
+ // logically "copy" the node. Later, the client can "deref" the head
+ // of its chain of ScopeChainNodes to reclaim all the nodes it added
+ // after the logical copy, leaving nodes added before the logical copy
+ // (nodes shared with other clients) untouched.
+ ScopeChainNode* copy()
+ {
+ ref();
+ return this;
+ }
+
+ ScopeChainNode* push(JSObject*);
+ ScopeChainNode* pop();
+
+ ScopeChainIterator begin() const;
+ ScopeChainIterator end() const;
+
+ JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
+ JSObject* globalThisObject() const { return globalThis; }
+
+#ifndef NDEBUG
+ void print() const;
+#endif
+ };
+
+ inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
+ {
+ ASSERT(o);
+ return new ScopeChainNode(this, o, globalData, globalThis);
+ }
+
+ inline ScopeChainNode* ScopeChainNode::pop()
+ {
+ ASSERT(next);
+ ScopeChainNode* result = next;
+
+ if (--refCount != 0)
+ ++result->refCount;
+ else
+ delete this;
+
+ return result;
+ }
+
+ inline void ScopeChainNode::release()
+ {
+ // This function is only called by deref(),
+ // Deref ensures these conditions are true.
+ ASSERT(refCount == 0);
+ ScopeChainNode* n = this;
+ do {
+ ScopeChainNode* next = n->next;
+ delete n;
+ n = next;
+ } while (n && --n->refCount == 0);
+ }
+
+ class ScopeChainIterator {
+ public:
+ ScopeChainIterator(const ScopeChainNode* node)
+ : m_node(node)
+ {
+ }
+
+ JSObject* const & operator*() const { return m_node->object; }
+ JSObject* const * operator->() const { return &(operator*()); }
+
+ ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
+
+ // postfix ++ intentionally omitted
+
+ bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
+ bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
+
+ private:
+ const ScopeChainNode* m_node;
+ };
+
+ inline ScopeChainIterator ScopeChainNode::begin() const
+ {
+ return ScopeChainIterator(this);
+ }
+
+ inline ScopeChainIterator ScopeChainNode::end() const
+ {
+ return ScopeChainIterator(0);
+ }
+
+ class NoScopeChain {};
+
+ class ScopeChain {
+ friend class JIT;
+ public:
+ ScopeChain(NoScopeChain)
+ : m_node(0)
+ {
+ }
+
+ ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis)
+ : m_node(new ScopeChainNode(0, o, globalData, globalThis))
+ {
+ }
+
+ ScopeChain(const ScopeChain& c)
+ : m_node(c.m_node->copy())
+ {
+ }
+
+ ScopeChain& operator=(const ScopeChain& c);
+
+ explicit ScopeChain(ScopeChainNode* node)
+ : m_node(node->copy())
+ {
+ }
+
+ ~ScopeChain()
+ {
+ if (m_node)
+ m_node->deref();
+ }
+
+ void swap(ScopeChain&);
+
+ ScopeChainNode* node() const { return m_node; }
+
+ JSObject* top() const { return m_node->object; }
+
+ ScopeChainIterator begin() const { return m_node->begin(); }
+ ScopeChainIterator end() const { return m_node->end(); }
+
+ void push(JSObject* o) { m_node = m_node->push(o); }
+
+ void pop() { m_node = m_node->pop(); }
+ void clear() { m_node->deref(); m_node = 0; }
+
+ JSGlobalObject* globalObject() const { return m_node->globalObject(); }
+
+ void mark() const;
+
+ // Caution: this should only be used if the codeblock this is being used
+ // with needs a full scope chain, otherwise this returns the depth of
+ // the preceeding call frame
+ //
+ // Returns the depth of the current call frame's scope chain
+ int localDepth() const;
+
+#ifndef NDEBUG
+ void print() const { m_node->print(); }
+#endif
+
+ private:
+ ScopeChainNode* m_node;
+ };
+
+ inline void ScopeChain::swap(ScopeChain& o)
+ {
+ ScopeChainNode* tmp = m_node;
+ m_node = o.m_node;
+ o.m_node = tmp;
+ }
+
+ inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+ {
+ ScopeChain tmp(c);
+ swap(tmp);
+ return *this;
+ }
+
+} // namespace JSC
+
+#endif // ScopeChain_h
--- /dev/null
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScopeChainMark_h
+#define ScopeChainMark_h
+
+#include "ScopeChain.h"
+
+namespace JSC {
+
+ inline void ScopeChain::mark() const
+ {
+ for (ScopeChainNode* n = m_node; n; n = n->next) {
+ JSObject* o = n->object;
+ if (!o->marked())
+ o->mark();
+ }
+ }
+
+} // namespace JSC
+
+#endif // ScopeChainMark_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SmallStrings.h"
+
+#include "JSGlobalObject.h"
+#include "JSString.h"
+
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+static const unsigned numCharactersToStore = 0x100;
+
+class SmallStringsStorage : Noncopyable {
+public:
+ SmallStringsStorage();
+
+ UString::Rep* rep(unsigned char character) { return &m_reps[character]; }
+
+private:
+ UChar m_characters[numCharactersToStore];
+ UString::BaseString m_base;
+ UString::Rep m_reps[numCharactersToStore];
+};
+
+SmallStringsStorage::SmallStringsStorage()
+{
+ for (unsigned i = 0; i < numCharactersToStore; ++i)
+ m_characters[i] = i;
+
+ m_base.rc = numCharactersToStore + 1;
+ m_base.buf = m_characters;
+ m_base.len = numCharactersToStore;
+ m_base.offset = 0;
+ m_base._hash = 0;
+ m_base.m_baseString = 0;
+ m_base.preCapacity = 0;
+ m_base.usedPreCapacity = 0;
+ m_base.reportedCost = 0;
+
+ // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it
+ m_base.usedCapacity = numCharactersToStore + 1;
+ m_base.capacity = numCharactersToStore + 1;
+ m_base.checkConsistency();
+
+ memset(&m_reps, 0, sizeof(m_reps));
+ for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ m_reps[i].offset = i;
+ m_reps[i].len = 1;
+ m_reps[i].rc = 1;
+ m_reps[i].setBaseString(&m_base);
+ m_reps[i].checkConsistency();
+ }
+}
+
+SmallStrings::SmallStrings()
+ : m_emptyString(0)
+ , m_storage(0)
+{
+ COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
+
+ for (unsigned i = 0; i < numCharactersToStore; ++i)
+ m_singleCharacterStrings[i] = 0;
+}
+
+SmallStrings::~SmallStrings()
+{
+}
+
+void SmallStrings::mark()
+{
+ if (m_emptyString && !m_emptyString->marked())
+ m_emptyString->mark();
+ for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked())
+ m_singleCharacterStrings[i]->mark();
+ }
+}
+
+unsigned SmallStrings::count() const
+{
+ unsigned count = 0;
+ if (m_emptyString)
+ ++count;
+ for (unsigned i = 0; i < numCharactersToStore; ++i) {
+ if (m_singleCharacterStrings[i])
+ ++count;
+ }
+ return count;
+}
+
+void SmallStrings::createEmptyString(JSGlobalData* globalData)
+{
+ ASSERT(!m_emptyString);
+ m_emptyString = new (globalData) JSString(globalData, "", JSString::HasOtherOwner);
+}
+
+void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
+{
+ if (!m_storage)
+ m_storage.set(new SmallStringsStorage);
+ ASSERT(!m_singleCharacterStrings[character]);
+ m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner);
+}
+
+UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character)
+{
+ if (!m_storage)
+ m_storage.set(new SmallStringsStorage);
+ return m_storage->rep(character);
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SmallStrings_h
+#define SmallStrings_h
+
+#include "UString.h"
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class JSGlobalData;
+ class JSString;
+
+ class SmallStringsStorage;
+
+ class SmallStrings : Noncopyable {
+ public:
+ SmallStrings();
+ ~SmallStrings();
+
+ JSString* emptyString(JSGlobalData* globalData)
+ {
+ if (!m_emptyString)
+ createEmptyString(globalData);
+ return m_emptyString;
+ }
+ JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
+ {
+ if (!m_singleCharacterStrings[character])
+ createSingleCharacterString(globalData, character);
+ return m_singleCharacterStrings[character];
+ }
+
+ UString::Rep* singleCharacterStringRep(unsigned char character);
+
+ void mark();
+
+ unsigned count() const;
+
+ private:
+ void createEmptyString(JSGlobalData*);
+ void createSingleCharacterString(JSGlobalData*, unsigned char);
+
+ JSString* m_emptyString;
+ JSString* m_singleCharacterStrings[0x100];
+ OwnPtr<SmallStringsStorage> m_storage;
+ };
+
+} // namespace JSC
+
+#endif // SmallStrings_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringConstructor.h"
+
+#include "JSGlobalObject.h"
+#include "PrototypeFunction.h"
+#include "StringPrototype.h"
+
+namespace JSC {
+
+static NEVER_INLINE JSValuePtr stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
+{
+ UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar)));
+ UChar* p = buf;
+ ArgList::const_iterator end = args.end();
+ for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+ *p++ = static_cast<UChar>((*it).jsValue(exec).toUInt32(exec));
+ return jsString(exec, UString(buf, p - buf, false));
+}
+
+static JSValuePtr stringFromCharCode(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ if (LIKELY(args.size() == 1))
+ return jsSingleCharacterString(exec, args.at(exec, 0).toUInt32(exec));
+ return stringFromCharCodeSlowCase(exec, args);
+}
+
+ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+
+StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
+{
+ // ECMA 15.5.3.1 String.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+
+ // ECMA 15.5.3.2 fromCharCode()
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.5.2
+static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ if (args.isEmpty())
+ return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure());
+ return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(exec, 0).toString(exec));
+}
+
+ConstructType StringConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithStringConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.5.1
+static JSValuePtr callStringConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+{
+ if (args.isEmpty())
+ return jsEmptyString(exec);
+ return jsString(exec, args.at(exec, 0).toString(exec));
+}
+
+CallType StringConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callStringConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringConstructor_h
+#define StringConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class StringPrototype;
+
+ class StringConstructor : public InternalFunction {
+ public:
+ StringConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // StringConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringObject.h"
+
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(StringObject);
+
+const ClassInfo StringObject::info = { "String", 0, 0, 0 };
+
+StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(jsEmptyString(exec));
+}
+
+StringObject::StringObject(PassRefPtr<Structure> structure, JSString* string)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(string);
+}
+
+StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(jsString(exec, string));
+}
+
+bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length)
+ return;
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().length)
+ return false;
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ int size = internalValue()->value().size();
+ for (int i = 0; i < size; ++i)
+ propertyNames.add(Identifier(exec, UString::from(i)));
+ return JSObject::getPropertyNames(exec, propertyNames);
+}
+
+UString StringObject::toString(ExecState*) const
+{
+ return internalValue()->value();
+}
+
+UString StringObject::toThisString(ExecState*) const
+{
+ return internalValue()->value();
+}
+
+JSString* StringObject::toThisJSString(ExecState*)
+{
+ return internalValue();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringObject_h
+#define StringObject_h
+
+#include "JSWrapperObject.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ class StringObject : public JSWrapperObject {
+ public:
+ StringObject(ExecState*, PassRefPtr<Structure>);
+ StringObject(ExecState*, PassRefPtr<Structure>, const UString&);
+
+ static StringObject* create(ExecState*, JSString*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ StringObject(PassRefPtr<Structure>, JSString*);
+
+ private:
+ virtual UString toString(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+ };
+
+ StringObject* asStringObject(JSValuePtr);
+
+ inline StringObject* asStringObject(JSValuePtr value)
+ {
+ ASSERT(asObject(value)->inherits(&StringObject::info));
+ return static_cast<StringObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // StringObject_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringObjectThatMasqueradesAsUndefined_h
+#define StringObjectThatMasqueradesAsUndefined_h
+
+#include "JSGlobalObject.h"
+#include "StringObject.h"
+#include "UString.h"
+
+namespace JSC {
+
+ // WebCore uses this to make style.filter undetectable
+ class StringObjectThatMasqueradesAsUndefined : public StringObject {
+ public:
+ static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string)
+ {
+ return new (exec) StringObjectThatMasqueradesAsUndefined(exec,
+ createStructure(exec->lexicalGlobalObject()->stringPrototype()), string);
+ }
+
+ private:
+ StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+ : StringObject(exec, structure, string)
+ {
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ {
+ return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined));
+ }
+
+ virtual bool toBoolean(ExecState*) const { return false; }
+ };
+
+} // namespace JSC
+
+#endif // StringObjectThatMasqueradesAsUndefined_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringPrototype.h"
+
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "RegExpConstructor.h"
+#include "RegExpObject.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/MathExtras.h>
+#include <wtf/unicode/Collator.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
+
+static JSValuePtr stringProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncCharAt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncMatch(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncReplace(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSearch(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSplit(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSubstr(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSubstring(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+static JSValuePtr stringProtoFuncBig(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSmall(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncBlink(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncBold(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncItalics(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncStrike(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSub(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncSup(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncFontcolor(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncFontsize(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncAnchor(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValuePtr stringProtoFuncLink(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+
+}
+
+#include "StringPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };
+
+/* Source for StringPrototype.lut.h
+@begin stringTable 26
+ toString stringProtoFuncToString DontEnum|Function 0
+ valueOf stringProtoFuncToString DontEnum|Function 0
+ charAt stringProtoFuncCharAt DontEnum|Function 1
+ charCodeAt stringProtoFuncCharCodeAt DontEnum|Function 1
+ concat stringProtoFuncConcat DontEnum|Function 1
+ indexOf stringProtoFuncIndexOf DontEnum|Function 1
+ lastIndexOf stringProtoFuncLastIndexOf DontEnum|Function 1
+ match stringProtoFuncMatch DontEnum|Function 1
+ replace stringProtoFuncReplace DontEnum|Function 2
+ search stringProtoFuncSearch DontEnum|Function 1
+ slice stringProtoFuncSlice DontEnum|Function 2
+ split stringProtoFuncSplit DontEnum|Function 2
+ substr stringProtoFuncSubstr DontEnum|Function 2
+ substring stringProtoFuncSubstring DontEnum|Function 2
+ toLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
+ toUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
+ localeCompare stringProtoFuncLocaleCompare DontEnum|Function 1
+
+ # toLocaleLowerCase and toLocaleUpperCase are currently identical to toLowerCase and toUpperCase
+ toLocaleLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
+ toLocaleUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
+
+ big stringProtoFuncBig DontEnum|Function 0
+ small stringProtoFuncSmall DontEnum|Function 0
+ blink stringProtoFuncBlink DontEnum|Function 0
+ bold stringProtoFuncBold DontEnum|Function 0
+ fixed stringProtoFuncFixed DontEnum|Function 0
+ italics stringProtoFuncItalics DontEnum|Function 0
+ strike stringProtoFuncStrike DontEnum|Function 0
+ sub stringProtoFuncSub DontEnum|Function 0
+ sup stringProtoFuncSup DontEnum|Function 0
+ fontcolor stringProtoFuncFontcolor DontEnum|Function 1
+ fontsize stringProtoFuncFontsize DontEnum|Function 1
+ anchor stringProtoFuncAnchor DontEnum|Function 1
+ link stringProtoFuncLink DontEnum|Function 1
+@end
+*/
+
+// ECMA 15.5.4
+StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+ : StringObject(exec, structure)
+{
+ // The constructor will be added later, after StringConstructor has been built
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+}
+
+bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
+}
+
+// ------------------------------ Functions --------------------------
+
+static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
+{
+ UString substitutedReplacement;
+ int offset = 0;
+ int i = -1;
+ while ((i = replacement.find('$', i + 1)) != -1) {
+ if (i + 1 == replacement.size())
+ break;
+
+ UChar ref = replacement[i + 1];
+ if (ref == '$') {
+ // "$$" -> "$"
+ ++i;
+ substitutedReplacement.append(replacement.data() + offset, i - offset);
+ offset = i + 1;
+ continue;
+ }
+
+ int backrefStart;
+ int backrefLength;
+ int advance = 0;
+ if (ref == '&') {
+ backrefStart = ovector[0];
+ backrefLength = ovector[1] - backrefStart;
+ } else if (ref == '`') {
+ backrefStart = 0;
+ backrefLength = ovector[0];
+ } else if (ref == '\'') {
+ backrefStart = ovector[1];
+ backrefLength = source.size() - backrefStart;
+ } else if (reg && ref >= '0' && ref <= '9') {
+ // 1- and 2-digit back references are allowed
+ unsigned backrefIndex = ref - '0';
+ if (backrefIndex > reg->numSubpatterns())
+ continue;
+ if (replacement.size() > i + 2) {
+ ref = replacement[i + 2];
+ if (ref >= '0' && ref <= '9') {
+ backrefIndex = 10 * backrefIndex + ref - '0';
+ if (backrefIndex > reg->numSubpatterns())
+ backrefIndex = backrefIndex / 10; // Fall back to the 1-digit reference
+ else
+ advance = 1;
+ }
+ }
+ if (!backrefIndex)
+ continue;
+ backrefStart = ovector[2 * backrefIndex];
+ backrefLength = ovector[2 * backrefIndex + 1] - backrefStart;
+ } else
+ continue;
+
+ if (i - offset)
+ substitutedReplacement.append(replacement.data() + offset, i - offset);
+ i += 1 + advance;
+ offset = i + 1;
+ substitutedReplacement.append(source.data() + backrefStart, backrefLength);
+ }
+
+ if (!offset)
+ return replacement;
+
+ if (replacement.size() - offset)
+ substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
+
+ return substitutedReplacement;
+}
+
+static inline int localeCompare(const UString& a, const UString& b)
+{
+ return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size());
+}
+
+JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ JSString* sourceVal = thisValue.toThisJSString(exec);
+ const UString& source = sourceVal->value();
+
+ JSValuePtr pattern = args.at(exec, 0);
+
+ JSValuePtr replacement = args.at(exec, 1);
+ UString replacementString;
+ CallData callData;
+ CallType callType = replacement.getCallData(callData);
+ if (callType == CallTypeNone)
+ replacementString = replacement.toString(exec);
+
+ if (pattern.isObject(&RegExpObject::info)) {
+ RegExp* reg = asRegExpObject(pattern)->regExp();
+ bool global = reg->global();
+
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+
+ int lastIndex = 0;
+ int startPosition = 0;
+
+ Vector<UString::Range, 16> sourceRanges;
+ Vector<UString, 16> replacements;
+
+ // This is either a loop (if global is set) or a one-way (if not).
+ do {
+ int matchIndex;
+ int matchLen;
+ int* ovector;
+ regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+ if (matchIndex < 0)
+ break;
+
+ sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
+
+ if (callType != CallTypeNone) {
+ int completeMatchStart = ovector[0];
+ ArgList args;
+
+ for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
+ int matchStart = ovector[i * 2];
+ int matchLen = ovector[i * 2 + 1] - matchStart;
+
+ if (matchStart < 0)
+ args.append(jsUndefined());
+ else
+ args.append(jsSubstring(exec, source, matchStart, matchLen));
+ }
+
+ args.append(jsNumber(exec, completeMatchStart));
+ args.append(sourceVal);
+
+ replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
+ if (exec->hadException())
+ break;
+ } else
+ replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
+
+ lastIndex = matchIndex + matchLen;
+ startPosition = lastIndex;
+
+ // special case of empty match
+ if (matchLen == 0) {
+ startPosition++;
+ if (startPosition > source.size())
+ break;
+ }
+ } while (global);
+
+ if (lastIndex < source.size())
+ sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
+
+ UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
+
+ if (result == source)
+ return sourceVal;
+
+ return jsString(exec, result);
+ }
+
+ // First arg is a string
+ UString patternString = pattern.toString(exec);
+ int matchPos = source.find(patternString);
+ int matchLen = patternString.size();
+ // Do the replacement
+ if (matchPos == -1)
+ return sourceVal;
+
+ if (callType != CallTypeNone) {
+ ArgList args;
+ args.append(jsSubstring(exec, source, matchPos, matchLen));
+ args.append(jsNumber(exec, matchPos));
+ args.append(sourceVal);
+
+ replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec);
+ }
+
+ int ovector[2] = { matchPos, matchPos + matchLen };
+ return jsString(exec, source.substr(0, matchPos)
+ + substituteBackreferences(replacementString, source, ovector, 0)
+ + source.substr(matchPos + matchLen));
+}
+
+JSValuePtr stringProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ // Also used for valueOf.
+
+ if (thisValue.isString())
+ return thisValue;
+
+ if (thisValue.isObject(&StringObject::info))
+ return asStringObject(thisValue)->internalValue();
+
+ return throwError(exec, TypeError);
+}
+
+JSValuePtr stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ unsigned len = s.size();
+ JSValuePtr a0 = args.at(exec, 0);
+ if (a0.isUInt32Fast()) {
+ uint32_t i = a0.getUInt32Fast();
+ if (i < len)
+ return jsSingleCharacterSubstring(exec, s, i);
+ return jsEmptyString(exec);
+ }
+ double dpos = a0.toInteger(exec);
+ if (dpos >= 0 && dpos < len)
+ return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos));
+ return jsEmptyString(exec);
+}
+
+JSValuePtr stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ unsigned len = s.size();
+ JSValuePtr a0 = args.at(exec, 0);
+ if (a0.isUInt32Fast()) {
+ uint32_t i = a0.getUInt32Fast();
+ if (i < len)
+ return jsNumber(exec, s.data()[i]);
+ return jsNaN(exec);
+ }
+ double dpos = a0.toInteger(exec);
+ if (dpos >= 0 && dpos < len)
+ return jsNumber(exec, s[static_cast<int>(dpos)]);
+ return jsNaN(exec);
+}
+
+JSValuePtr stringProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+
+ ArgList::const_iterator end = args.end();
+ for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+ s += (*it).jsValue(exec).toString(exec);
+ return jsString(exec, s);
+}
+
+JSValuePtr stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ int len = s.size();
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+ UString u2 = a0.toString(exec);
+ int pos;
+ if (a1.isUndefined())
+ pos = 0;
+ else if (a1.isUInt32Fast())
+ pos = min<uint32_t>(a1.getUInt32Fast(), len);
+ else {
+ double dpos = a1.toInteger(exec);
+ if (dpos < 0)
+ dpos = 0;
+ else if (dpos > len)
+ dpos = len;
+ pos = static_cast<int>(dpos);
+ }
+
+ return jsNumber(exec, s.find(u2, pos));
+}
+
+JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ int len = s.size();
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+
+ UString u2 = a0.toString(exec);
+ double dpos = a1.toIntegerPreserveNaN(exec);
+ if (dpos < 0)
+ dpos = 0;
+ else if (!(dpos <= len)) // true for NaN
+ dpos = len;
+ return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
+}
+
+JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+
+ JSValuePtr a0 = args.at(exec, 0);
+
+ UString u = s;
+ RefPtr<RegExp> reg;
+ RegExpObject* imp = 0;
+ if (a0.isObject(&RegExpObject::info))
+ reg = asRegExpObject(a0)->regExp();
+ else {
+ /*
+ * ECMA 15.5.4.12 String.prototype.search (regexp)
+ * If regexp is not an object whose [[Class]] property is "RegExp", it is
+ * replaced with the result of the expression new RegExp(regexp).
+ */
+ reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ }
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+ int pos;
+ int matchLength;
+ regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
+ if (!(reg->global())) {
+ // case without 'g' flag is handled like RegExp.prototype.exec
+ if (pos < 0)
+ return jsNull();
+ return regExpConstructor->arrayOfMatches(exec);
+ }
+
+ // return array of matches
+ ArgList list;
+ int lastIndex = 0;
+ while (pos >= 0) {
+ list.append(jsSubstring(exec, u, pos, matchLength));
+ lastIndex = pos;
+ pos += matchLength == 0 ? 1 : matchLength;
+ regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength);
+ }
+ if (imp)
+ imp->setLastIndex(lastIndex);
+ if (list.isEmpty()) {
+ // if there are no matches at all, it's important to return
+ // Null instead of an empty array, because this matches
+ // other browsers and because Null is a false value.
+ return jsNull();
+ }
+
+ return constructArray(exec, list);
+}
+
+JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+
+ JSValuePtr a0 = args.at(exec, 0);
+
+ UString u = s;
+ RefPtr<RegExp> reg;
+ if (a0.isObject(&RegExpObject::info))
+ reg = asRegExpObject(a0)->regExp();
+ else {
+ /*
+ * ECMA 15.5.4.12 String.prototype.search (regexp)
+ * If regexp is not an object whose [[Class]] property is "RegExp", it is
+ * replaced with the result of the expression new RegExp(regexp).
+ */
+ reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ }
+ RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+ int pos;
+ int matchLength;
+ regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
+ return jsNumber(exec, pos);
+}
+
+JSValuePtr stringProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ int len = s.size();
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+
+ // The arg processing is very much like ArrayProtoFunc::Slice
+ double start = a0.toInteger(exec);
+ double end = a1.isUndefined() ? len : a1.toInteger(exec);
+ double from = start < 0 ? len + start : start;
+ double to = end < 0 ? len + end : end;
+ if (to > from && to > 0 && from < len) {
+ if (from < 0)
+ from = 0;
+ if (to > len)
+ to = len;
+ return jsSubstring(exec, s, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from));
+ }
+
+ return jsEmptyString(exec);
+}
+
+JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+
+ JSArray* result = constructEmptyArray(exec);
+ unsigned i = 0;
+ int p0 = 0;
+ unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
+ if (a0.isObject(&RegExpObject::info)) {
+ RegExp* reg = asRegExpObject(a0)->regExp();
+ if (s.isEmpty() && reg->match(s, 0) >= 0) {
+ // empty string matched by regexp -> empty array
+ return result;
+ }
+ int pos = 0;
+ while (i != limit && pos < s.size()) {
+ OwnArrayPtr<int> ovector;
+ int mpos = reg->match(s, pos, &ovector);
+ if (mpos < 0)
+ break;
+ int mlen = ovector[1] - ovector[0];
+ pos = mpos + (mlen == 0 ? 1 : mlen);
+ if (mpos != p0 || mlen) {
+ result->put(exec, i++, jsSubstring(exec, s, p0, mpos - p0));
+ p0 = mpos + mlen;
+ }
+ for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) {
+ int spos = ovector[si * 2];
+ if (spos < 0)
+ result->put(exec, i++, jsUndefined());
+ else
+ result->put(exec, i++, jsSubstring(exec, s, spos, ovector[si * 2 + 1] - spos));
+ }
+ }
+ } else {
+ UString u2 = a0.toString(exec);
+ if (u2.isEmpty()) {
+ if (s.isEmpty()) {
+ // empty separator matches empty string -> empty array
+ return result;
+ }
+ while (i != limit && p0 < s.size() - 1)
+ result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++));
+ } else {
+ int pos;
+ while (i != limit && (pos = s.find(u2, p0)) >= 0) {
+ result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0));
+ p0 = pos + u2.size();
+ }
+ }
+ }
+
+ // add remaining string
+ if (i != limit)
+ result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0));
+
+ return result;
+}
+
+JSValuePtr stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ int len = s.size();
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+
+ double start = a0.toInteger(exec);
+ double length = a1.isUndefined() ? len : a1.toInteger(exec);
+ if (start >= len || length <= 0)
+ return jsEmptyString(exec);
+ if (start < 0) {
+ start += len;
+ if (start < 0)
+ start = 0;
+ }
+ if (start + length > len)
+ length = len - start;
+ return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length));
+}
+
+JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ int len = s.size();
+
+ JSValuePtr a0 = args.at(exec, 0);
+ JSValuePtr a1 = args.at(exec, 1);
+
+ double start = a0.toNumber(exec);
+ double end = a1.toNumber(exec);
+ if (isnan(start))
+ start = 0;
+ if (isnan(end))
+ end = 0;
+ if (start < 0)
+ start = 0;
+ if (end < 0)
+ end = 0;
+ if (start > len)
+ start = len;
+ if (end > len)
+ end = len;
+ if (a1.isUndefined())
+ end = len;
+ if (start > end) {
+ double temp = end;
+ end = start;
+ start = temp;
+ }
+ return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(end) - static_cast<unsigned>(start));
+}
+
+JSValuePtr stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSString* sVal = thisValue.toThisJSString(exec);
+ const UString& s = sVal->value();
+
+ int sSize = s.size();
+ if (!sSize)
+ return sVal;
+
+ const UChar* sData = s.data();
+ Vector<UChar> buffer(sSize);
+
+ UChar ored = 0;
+ for (int i = 0; i < sSize; i++) {
+ UChar c = sData[i];
+ ored |= c;
+ buffer[i] = toASCIILower(c);
+ }
+ if (!(ored & ~0x7f))
+ return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+
+ bool error;
+ int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
+ if (error) {
+ buffer.resize(length);
+ length = Unicode::toLower(buffer.data(), length, sData, sSize, &error);
+ if (error)
+ return sVal;
+ }
+ if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+ return sVal;
+ return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+}
+
+JSValuePtr stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ JSString* sVal = thisValue.toThisJSString(exec);
+ const UString& s = sVal->value();
+
+ int sSize = s.size();
+ if (!sSize)
+ return sVal;
+
+ const UChar* sData = s.data();
+ Vector<UChar> buffer(sSize);
+
+ UChar ored = 0;
+ for (int i = 0; i < sSize; i++) {
+ UChar c = sData[i];
+ ored |= c;
+ buffer[i] = toASCIIUpper(c);
+ }
+ if (!(ored & ~0x7f))
+ return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+
+ bool error;
+ int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
+ if (error) {
+ buffer.resize(length);
+ length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error);
+ if (error)
+ return sVal;
+ }
+ if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+ return sVal;
+ return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+}
+
+JSValuePtr stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsNumber(exec, 0);
+
+ UString s = thisValue.toThisString(exec);
+ JSValuePtr a0 = args.at(exec, 0);
+ return jsNumber(exec, localeCompare(s, a0.toString(exec)));
+}
+
+JSValuePtr stringProtoFuncBig(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<big>" + s + "</big>");
+}
+
+JSValuePtr stringProtoFuncSmall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<small>" + s + "</small>");
+}
+
+JSValuePtr stringProtoFuncBlink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<blink>" + s + "</blink>");
+}
+
+JSValuePtr stringProtoFuncBold(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<b>" + s + "</b>");
+}
+
+JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsString(exec, "<tt>" + s + "</tt>");
+}
+
+JSValuePtr stringProtoFuncItalics(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<i>" + s + "</i>");
+}
+
+JSValuePtr stringProtoFuncStrike(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<strike>" + s + "</strike>");
+}
+
+JSValuePtr stringProtoFuncSub(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<sub>" + s + "</sub>");
+}
+
+JSValuePtr stringProtoFuncSup(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+{
+ UString s = thisValue.toThisString(exec);
+ return jsNontrivialString(exec, "<sup>" + s + "</sup>");
+}
+
+JSValuePtr stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ JSValuePtr a0 = args.at(exec, 0);
+ return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
+}
+
+JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ JSValuePtr a0 = args.at(exec, 0);
+
+ uint32_t smallInteger;
+ if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
+ unsigned stringSize = s.size();
+ unsigned bufferSize = 22 + stringSize;
+ UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
+ if (!buffer)
+ return jsUndefined();
+ buffer[0] = '<';
+ buffer[1] = 'f';
+ buffer[2] = 'o';
+ buffer[3] = 'n';
+ buffer[4] = 't';
+ buffer[5] = ' ';
+ buffer[6] = 's';
+ buffer[7] = 'i';
+ buffer[8] = 'z';
+ buffer[9] = 'e';
+ buffer[10] = '=';
+ buffer[11] = '"';
+ buffer[12] = '0' + smallInteger;
+ buffer[13] = '"';
+ buffer[14] = '>';
+ memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar));
+ buffer[15 + stringSize] = '<';
+ buffer[16 + stringSize] = '/';
+ buffer[17 + stringSize] = 'f';
+ buffer[18 + stringSize] = 'o';
+ buffer[19 + stringSize] = 'n';
+ buffer[20 + stringSize] = 't';
+ buffer[21 + stringSize] = '>';
+ return jsNontrivialString(exec, UString(buffer, bufferSize, false));
+ }
+
+ return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
+}
+
+JSValuePtr stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ JSValuePtr a0 = args.at(exec, 0);
+ return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
+}
+
+JSValuePtr stringProtoFuncLink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+{
+ UString s = thisValue.toThisString(exec);
+ JSValuePtr a0 = args.at(exec, 0);
+ UString linkText = a0.toString(exec);
+
+ unsigned linkTextSize = linkText.size();
+ unsigned stringSize = s.size();
+ unsigned bufferSize = 15 + linkTextSize + stringSize;
+ UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
+ if (!buffer)
+ return jsUndefined();
+ buffer[0] = '<';
+ buffer[1] = 'a';
+ buffer[2] = ' ';
+ buffer[3] = 'h';
+ buffer[4] = 'r';
+ buffer[5] = 'e';
+ buffer[6] = 'f';
+ buffer[7] = '=';
+ buffer[8] = '"';
+ memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar));
+ buffer[9 + linkTextSize] = '"';
+ buffer[10 + linkTextSize] = '>';
+ memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar));
+ buffer[11 + linkTextSize + stringSize] = '<';
+ buffer[12 + linkTextSize + stringSize] = '/';
+ buffer[13 + linkTextSize + stringSize] = 'a';
+ buffer[14 + linkTextSize + stringSize] = '>';
+ return jsNontrivialString(exec, UString(buffer, bufferSize, false));
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringPrototype_h
+#define StringPrototype_h
+
+#include "StringObject.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class StringPrototype : public StringObject {
+ public:
+ StringPrototype(ExecState*, PassRefPtr<Structure>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // StringPrototype_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Structure.h"
+
+#include "Identifier.h"
+#include "JSObject.h"
+#include "PropertyNameArray.h"
+#include "StructureChain.h"
+#include "Lookup.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/RefPtr.h>
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <wtf/Threading.h>
+#endif
+
+#define DUMP_STRUCTURE_ID_STATISTICS 0
+
+#ifndef NDEBUG
+#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
+#else
+#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
+#endif
+
+using namespace std;
+using namespace WTF;
+
+namespace JSC {
+
+// Choose a number for the following so that most property maps are smaller,
+// but it's not going to blow out the stack to allocate this number of pointers.
+static const int smallMapThreshold = 1024;
+
+// The point at which the function call overhead of the qsort implementation
+// becomes small compared to the inefficiency of insertion sort.
+static const unsigned tinyMapThreshold = 20;
+
+static const unsigned newTableSize = 16;
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter structureCounter("Structure");
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+static Mutex ignoreSetMutex;
+#endif
+
+static bool shouldIgnoreLeaks;
+static HashSet<Structure*> ignoreSet;
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+static HashSet<Structure*> liveStructureSet;
+#endif
+
+void Structure::dumpStatistics()
+{
+#if DUMP_STRUCTURE_ID_STATISTICS
+ unsigned numberLeaf = 0;
+ unsigned numberUsingSingleSlot = 0;
+ unsigned numberSingletons = 0;
+ unsigned numberWithPropertyMaps = 0;
+ unsigned totalPropertyMapsSize = 0;
+
+ HashSet<Structure*>::const_iterator end = liveStructureSet.end();
+ for (HashSet<Structure*>::const_iterator it = liveStructureSet.begin(); it != end; ++it) {
+ Structure* structure = *it;
+ if (structure->m_usingSingleTransitionSlot) {
+ if (!structure->m_transitions.singleTransition)
+ ++numberLeaf;
+ else
+ ++numberUsingSingleSlot;
+
+ if (!structure->m_previous && !structure->m_transitions.singleTransition)
+ ++numberSingletons;
+ }
+
+ if (structure->m_propertyTable) {
+ ++numberWithPropertyMaps;
+ totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structure->m_propertyTable->size);
+ if (structure->m_propertyTable->deletedOffsets)
+ totalPropertyMapsSize += (structure->m_propertyTable->deletedOffsets->capacity() * sizeof(unsigned));
+ }
+ }
+
+ printf("Number of live Structures: %d\n", liveStructureSet.size());
+ printf("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
+ printf("Number of Structures that are leaf nodes: %d\n", numberLeaf);
+ printf("Number of Structures that singletons: %d\n", numberSingletons);
+ printf("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps);
+
+ printf("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure)));
+ printf("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
+ printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size()));
+#else
+ printf("Dumping Structure statistics is not enabled.\n");
+#endif
+}
+
+Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo)
+ : m_typeInfo(typeInfo)
+ , m_prototype(prototype)
+ , m_propertyTable(0)
+ , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+ , m_offset(noOffset)
+ , m_isDictionary(false)
+ , m_isPinnedPropertyTable(false)
+ , m_hasGetterSetterProperties(false)
+ , m_usingSingleTransitionSlot(true)
+ , m_attributesInPrevious(0)
+{
+ ASSERT(m_prototype);
+ ASSERT(m_prototype.isObject() || m_prototype.isNull());
+
+ m_transitions.singleTransition = 0;
+
+#ifndef NDEBUG
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ MutexLocker protect(ignoreSetMutex);
+#endif
+ if (shouldIgnoreLeaks)
+ ignoreSet.add(this);
+ else
+ structureCounter.increment();
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+ liveStructureSet.add(this);
+#endif
+}
+
+Structure::~Structure()
+{
+ if (m_previous) {
+ if (m_previous->m_usingSingleTransitionSlot) {
+ m_previous->m_transitions.singleTransition = 0;
+ } else {
+ ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious)));
+ m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious));
+ }
+ }
+
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructure(0);
+
+ if (!m_usingSingleTransitionSlot)
+ delete m_transitions.table;
+
+ if (m_propertyTable) {
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; i++) {
+ if (UString::Rep* key = m_propertyTable->entries()[i].key)
+ key->deref();
+ }
+
+ delete m_propertyTable->deletedOffsets;
+ fastFree(m_propertyTable);
+ }
+
+#ifndef NDEBUG
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ MutexLocker protect(ignoreSetMutex);
+#endif
+ HashSet<Structure*>::iterator it = ignoreSet.find(this);
+ if (it != ignoreSet.end())
+ ignoreSet.remove(it);
+ else
+ structureCounter.decrement();
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+ liveStructureSet.remove(this);
+#endif
+}
+
+void Structure::startIgnoringLeaks()
+{
+#ifndef NDEBUG
+ shouldIgnoreLeaks = true;
+#endif
+}
+
+void Structure::stopIgnoringLeaks()
+{
+#ifndef NDEBUG
+ shouldIgnoreLeaks = false;
+#endif
+}
+
+static bool isPowerOf2(unsigned v)
+{
+ // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+
+ return !(v & (v - 1)) && v;
+}
+
+static unsigned nextPowerOf2(unsigned v)
+{
+ // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+ // Devised by Sean Anderson, Sepember 14, 2001
+
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+
+ return v;
+}
+
+static unsigned sizeForKeyCount(size_t keyCount)
+{
+ if (keyCount == notFound)
+ return newTableSize;
+
+ if (keyCount < 8)
+ return newTableSize;
+
+ if (isPowerOf2(keyCount))
+ return keyCount * 4;
+
+ return nextPowerOf2(keyCount) * 2;
+}
+
+void Structure::materializePropertyMap()
+{
+ ASSERT(!m_propertyTable);
+
+ Vector<Structure*, 8> structures;
+ structures.append(this);
+
+ Structure* structure = this;
+
+ // Search for the last Structure with a property table.
+ while ((structure = structure->previousID())) {
+ if (structure->m_isPinnedPropertyTable) {
+ ASSERT(structure->m_propertyTable);
+ ASSERT(!structure->m_previous);
+
+ m_propertyTable = structure->copyPropertyTable();
+ break;
+ }
+
+ structures.append(structure);
+ }
+
+ if (!m_propertyTable)
+ createPropertyMapHashTable(sizeForKeyCount(m_offset + 1));
+ else {
+ if (sizeForKeyCount(m_offset + 1) > m_propertyTable->size)
+ rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above.
+ }
+
+ for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
+ structure = structures[i];
+ structure->m_nameInPrevious->ref();
+ PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed);
+ insertIntoPropertyMapHashTable(entry);
+ }
+}
+
+void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
+{
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
+
+ if (shouldCache && m_cachedPropertyNameArrayData) {
+ if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
+ propertyNames.setData(m_cachedPropertyNameArrayData);
+ return;
+ }
+ clearEnumerationCache();
+ }
+
+ getEnumerableNamesFromPropertyTable(propertyNames);
+ getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
+
+ if (m_prototype.isObject()) {
+ propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
+ asObject(m_prototype)->getPropertyNames(exec, propertyNames);
+ }
+
+ if (shouldCache) {
+ m_cachedPropertyNameArrayData = propertyNames.data();
+ m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec));
+ m_cachedPropertyNameArrayData->setCachedStructure(this);
+ }
+}
+
+void Structure::clearEnumerationCache()
+{
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructure(0);
+ m_cachedPropertyNameArrayData.clear();
+}
+
+void Structure::growPropertyStorageCapacity()
+{
+ if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
+ m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+ else
+ m_propertyStorageCapacity *= 2;
+}
+
+PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
+{
+ ASSERT(!structure->m_isDictionary);
+ ASSERT(structure->typeInfo().type() == ObjectType);
+
+ if (structure->m_usingSingleTransitionSlot) {
+ Structure* existingTransition = structure->m_transitions.singleTransition;
+ if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) {
+ ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
+ offset = structure->m_transitions.singleTransition->m_offset;
+ return existingTransition;
+ }
+ } else {
+ if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) {
+ ASSERT(existingTransition->m_offset != noOffset);
+ offset = existingTransition->m_offset;
+ return existingTransition;
+ }
+ }
+
+ return 0;
+}
+
+PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
+{
+ ASSERT(!structure->m_isDictionary);
+ ASSERT(structure->typeInfo().type() == ObjectType);
+ ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
+
+ if (structure->transitionCount() > s_maxTransitionLength) {
+ RefPtr<Structure> transition = toDictionaryTransition(structure);
+ offset = transition->put(propertyName, attributes);
+ if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
+ transition->growPropertyStorageCapacity();
+ return transition.release();
+ }
+
+ RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+ transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
+ transition->m_previous = structure;
+ transition->m_nameInPrevious = propertyName.ustring().rep();
+ transition->m_attributesInPrevious = attributes;
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+
+ if (structure->m_propertyTable) {
+ if (structure->m_isPinnedPropertyTable)
+ transition->m_propertyTable = structure->copyPropertyTable();
+ else {
+ transition->m_propertyTable = structure->m_propertyTable;
+ structure->m_propertyTable = 0;
+ }
+ } else {
+ if (structure->m_previous)
+ transition->materializePropertyMap();
+ else
+ transition->createPropertyMapHashTable();
+ }
+
+ offset = transition->put(propertyName, attributes);
+ if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
+ transition->growPropertyStorageCapacity();
+
+ transition->m_offset = offset;
+
+ if (structure->m_usingSingleTransitionSlot) {
+ if (!structure->m_transitions.singleTransition) {
+ structure->m_transitions.singleTransition = transition.get();
+ return transition.release();
+ }
+
+ Structure* existingTransition = structure->m_transitions.singleTransition;
+ structure->m_usingSingleTransitionSlot = false;
+ StructureTransitionTable* transitionTable = new StructureTransitionTable;
+ structure->m_transitions.table = transitionTable;
+ transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition);
+ }
+ structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
+ return transition.release();
+}
+
+PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
+{
+ ASSERT(!structure->m_isDictionary);
+
+ RefPtr<Structure> transition = toDictionaryTransition(structure);
+
+ offset = transition->remove(propertyName);
+
+ return transition.release();
+}
+
+PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValuePtr prototype)
+{
+ RefPtr<Structure> transition = create(prototype, structure->typeInfo());
+
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+
+ // Don't set m_offset, as one can not transition to this.
+
+ structure->materializePropertyMapIfNecessary();
+ transition->m_propertyTable = structure->copyPropertyTable();
+ transition->m_isPinnedPropertyTable = true;
+
+ return transition.release();
+}
+
+PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
+{
+ RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
+
+ // Don't set m_offset, as one can not transition to this.
+
+ structure->materializePropertyMapIfNecessary();
+ transition->m_propertyTable = structure->copyPropertyTable();
+ transition->m_isPinnedPropertyTable = true;
+
+ return transition.release();
+}
+
+PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure)
+{
+ ASSERT(!structure->m_isDictionary);
+
+ RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+ transition->m_isDictionary = true;
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+
+ structure->materializePropertyMapIfNecessary();
+ transition->m_propertyTable = structure->copyPropertyTable();
+ transition->m_isPinnedPropertyTable = true;
+
+ return transition.release();
+}
+
+PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
+{
+ ASSERT(structure->m_isDictionary);
+
+ // Since dictionary Structures are not shared, and no opcodes specialize
+ // for them, we don't need to allocate a new Structure when transitioning
+ // to non-dictionary status.
+
+ // FIMXE: We can make this more efficient by canonicalizing the Structure (draining the
+ // deleted offsets vector) before transitioning from dictionary.
+ if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty())
+ structure->m_isDictionary = false;
+
+ return structure;
+}
+
+size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes)
+{
+ ASSERT(!m_transitions.singleTransition);
+
+ materializePropertyMapIfNecessary();
+
+ m_isPinnedPropertyTable = true;
+ size_t offset = put(propertyName, attributes);
+ if (propertyStorageSize() > propertyStorageCapacity())
+ growPropertyStorageCapacity();
+ clearEnumerationCache();
+ return offset;
+}
+
+size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
+{
+ ASSERT(!m_transitions.singleTransition);
+ ASSERT(m_isDictionary);
+
+ materializePropertyMapIfNecessary();
+
+ m_isPinnedPropertyTable = true;
+ size_t offset = remove(propertyName);
+ clearEnumerationCache();
+ return offset;
+}
+
+#if DUMP_PROPERTYMAP_STATS
+
+static int numProbes;
+static int numCollisions;
+static int numRehashes;
+static int numRemoves;
+
+struct PropertyMapStatisticsExitLogger {
+ ~PropertyMapStatisticsExitLogger();
+};
+
+static PropertyMapStatisticsExitLogger logger;
+
+PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
+{
+ printf("\nJSC::PropertyMap statistics\n\n");
+ printf("%d probes\n", numProbes);
+ printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
+ printf("%d rehashes\n", numRehashes);
+ printf("%d removes\n", numRemoves);
+}
+
+#endif
+
+static const unsigned deletedSentinelIndex = 1;
+
+#if !DO_PROPERTYMAP_CONSTENCY_CHECK
+
+inline void Structure::checkConsistency()
+{
+}
+
+#endif
+
+PropertyMapHashTable* Structure::copyPropertyTable()
+{
+ if (!m_propertyTable)
+ return 0;
+
+ size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size);
+ PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize));
+ memcpy(newTable, m_propertyTable, tableSize);
+
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; ++i) {
+ if (UString::Rep* key = newTable->entries()[i].key)
+ key->ref();
+ }
+
+ // Copy the deletedOffsets vector.
+ if (m_propertyTable->deletedOffsets)
+ newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets);
+
+ return newTable;
+}
+
+size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
+{
+ ASSERT(!propertyName.isNull());
+
+ materializePropertyMapIfNecessary();
+ if (!m_propertyTable)
+ return notFound;
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+ }
+}
+
+size_t Structure::put(const Identifier& propertyName, unsigned attributes)
+{
+ ASSERT(!propertyName.isNull());
+ ASSERT(get(propertyName) == notFound);
+
+ checkConsistency();
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ if (!m_propertyTable)
+ createPropertyMapHashTable();
+
+ // FIXME: Consider a fast case for tables with no deleted sentinels.
+
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ bool foundDeletedElement = false;
+ unsigned deletedElementIndex = 0; // initialize to make the compiler happy
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ while (1) {
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ break;
+
+ if (entryIndex == deletedSentinelIndex) {
+ // If we find a deleted-element sentinel, remember it for use later.
+ if (!foundDeletedElement) {
+ foundDeletedElement = true;
+ deletedElementIndex = i;
+ }
+ }
+
+ if (k == 0) {
+ k = 1 | doubleHash(rep->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ // Figure out which entry to use.
+ unsigned entryIndex = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount + 2;
+ if (foundDeletedElement) {
+ i = deletedElementIndex;
+ --m_propertyTable->deletedSentinelCount;
+
+ // Since we're not making the table bigger, we can't use the entry one past
+ // the end that we were planning on using, so search backwards for the empty
+ // slot that we can use. We know it will be there because we did at least one
+ // deletion in the past that left an entry empty.
+ while (m_propertyTable->entries()[--entryIndex - 1].key) { }
+ }
+
+ // Create a new hash table entry.
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
+
+ // Create a new hash table entry.
+ rep->ref();
+ m_propertyTable->entries()[entryIndex - 1].key = rep;
+ m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
+ m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
+
+ unsigned newOffset;
+ if (m_propertyTable->deletedOffsets && !m_propertyTable->deletedOffsets->isEmpty()) {
+ newOffset = m_propertyTable->deletedOffsets->last();
+ m_propertyTable->deletedOffsets->removeLast();
+ } else
+ newOffset = m_propertyTable->keyCount;
+ m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
+
+ ++m_propertyTable->keyCount;
+
+ if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
+ expandPropertyMapHashTable();
+
+ checkConsistency();
+ return newOffset;
+}
+
+size_t Structure::remove(const Identifier& propertyName)
+{
+ ASSERT(!propertyName.isNull());
+
+ checkConsistency();
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ if (!m_propertyTable)
+ return notFound;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+ ++numRemoves;
+#endif
+
+ // Find the thing to remove.
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ unsigned entryIndex;
+ UString::Rep* key = 0;
+ while (1) {
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return notFound;
+
+ key = m_propertyTable->entries()[entryIndex - 1].key;
+ if (rep == key)
+ break;
+
+ if (k == 0) {
+ k = 1 | doubleHash(rep->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ // Replace this one element with the deleted sentinel. Also clear out
+ // the entry so we can iterate all the entries as needed.
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
+
+ size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+
+ key->deref();
+ m_propertyTable->entries()[entryIndex - 1].key = 0;
+ m_propertyTable->entries()[entryIndex - 1].attributes = 0;
+ m_propertyTable->entries()[entryIndex - 1].offset = 0;
+
+ if (!m_propertyTable->deletedOffsets)
+ m_propertyTable->deletedOffsets = new Vector<unsigned>;
+ m_propertyTable->deletedOffsets->append(offset);
+
+ ASSERT(m_propertyTable->keyCount >= 1);
+ --m_propertyTable->keyCount;
+ ++m_propertyTable->deletedSentinelCount;
+
+ if (m_propertyTable->deletedSentinelCount * 4 >= m_propertyTable->size)
+ rehashPropertyMapHashTable();
+
+ checkConsistency();
+ return offset;
+}
+
+void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
+{
+ ASSERT(m_propertyTable);
+
+ unsigned i = entry.key->computedHash();
+ unsigned k = 0;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ while (1) {
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ break;
+
+ if (k == 0) {
+ k = 1 | doubleHash(entry.key->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ unsigned entryIndex = m_propertyTable->keyCount + 2;
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
+ m_propertyTable->entries()[entryIndex - 1] = entry;
+
+ ++m_propertyTable->keyCount;
+}
+
+void Structure::createPropertyMapHashTable()
+{
+ ASSERT(sizeForKeyCount(7) == newTableSize);
+ createPropertyMapHashTable(newTableSize);
+}
+
+void Structure::createPropertyMapHashTable(unsigned newTableSize)
+{
+ ASSERT(!m_propertyTable);
+ ASSERT(isPowerOf2(newTableSize));
+
+ checkConsistency();
+
+ m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
+ m_propertyTable->size = newTableSize;
+ m_propertyTable->sizeMask = newTableSize - 1;
+
+ checkConsistency();
+}
+
+void Structure::expandPropertyMapHashTable()
+{
+ ASSERT(m_propertyTable);
+ rehashPropertyMapHashTable(m_propertyTable->size * 2);
+}
+
+void Structure::rehashPropertyMapHashTable()
+{
+ ASSERT(m_propertyTable);
+ ASSERT(m_propertyTable->size);
+ rehashPropertyMapHashTable(m_propertyTable->size);
+}
+
+void Structure::rehashPropertyMapHashTable(unsigned newTableSize)
+{
+ ASSERT(m_propertyTable);
+ ASSERT(isPowerOf2(newTableSize));
+
+ checkConsistency();
+
+ PropertyMapHashTable* oldTable = m_propertyTable;
+
+ m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
+ m_propertyTable->size = newTableSize;
+ m_propertyTable->sizeMask = newTableSize - 1;
+
+ unsigned lastIndexUsed = 0;
+ unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; ++i) {
+ if (oldTable->entries()[i].key) {
+ lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
+ insertIntoPropertyMapHashTable(oldTable->entries()[i]);
+ }
+ }
+ m_propertyTable->lastIndexUsed = lastIndexUsed;
+ m_propertyTable->deletedOffsets = oldTable->deletedOffsets;
+
+ fastFree(oldTable);
+
+ checkConsistency();
+}
+
+static int comparePropertyMapEntryIndices(const void* a, const void* b)
+{
+ unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
+ unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index;
+ if (ia < ib)
+ return -1;
+ if (ia > ib)
+ return +1;
+ return 0;
+}
+
+void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames)
+{
+ materializePropertyMapIfNecessary();
+ if (!m_propertyTable)
+ return;
+
+ if (m_propertyTable->keyCount < tinyMapThreshold) {
+ PropertyMapEntry* a[tinyMapThreshold];
+ int i = 0;
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned k = 1; k <= entryCount; k++) {
+ if (m_propertyTable->entries()[k].key && !(m_propertyTable->entries()[k].attributes & DontEnum)) {
+ PropertyMapEntry* value = &m_propertyTable->entries()[k];
+ int j;
+ for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
+ a[j + 1] = a[j];
+ a[j + 1] = value;
+ ++i;
+ }
+ }
+ if (!propertyNames.size()) {
+ for (int k = 0; k < i; ++k)
+ propertyNames.addKnownUnique(a[k]->key);
+ } else {
+ for (int k = 0; k < i; ++k)
+ propertyNames.add(a[k]->key);
+ }
+
+ return;
+ }
+
+ // Allocate a buffer to use to sort the keys.
+ Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);
+
+ // Get pointers to the enumerable entries in the buffer.
+ PropertyMapEntry** p = sortedEnumerables.data();
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; i++) {
+ if (m_propertyTable->entries()[i].key && !(m_propertyTable->entries()[i].attributes & DontEnum))
+ *p++ = &m_propertyTable->entries()[i];
+ }
+
+ size_t enumerableCount = p - sortedEnumerables.data();
+ // Sort the entries by index.
+ qsort(sortedEnumerables.data(), enumerableCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
+ sortedEnumerables.resize(enumerableCount);
+
+ // Put the keys of the sorted entries into the list.
+ if (!propertyNames.size()) {
+ for (size_t i = 0; i < sortedEnumerables.size(); ++i)
+ propertyNames.addKnownUnique(sortedEnumerables[i]->key);
+ } else {
+ for (size_t i = 0; i < sortedEnumerables.size(); ++i)
+ propertyNames.add(sortedEnumerables[i]->key);
+ }
+}
+
+void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
+{
+ // Add properties from the static hashtables of properties
+ for (; classInfo; classInfo = classInfo->parentClass) {
+ const HashTable* table = classInfo->propHashTable(exec);
+ if (!table)
+ continue;
+ table->initializeIfNeeded(exec);
+ ASSERT(table->table);
+#if ENABLE(PERFECT_HASH_SIZE)
+ int hashSizeMask = table->hashSizeMask;
+#else
+ int hashSizeMask = table->compactSize - 1;
+#endif
+ const HashEntry* entry = table->table;
+ for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
+ if (entry->key() && !(entry->attributes() & DontEnum))
+ propertyNames.add(entry->key());
+ }
+ }
+}
+
+#if DO_PROPERTYMAP_CONSTENCY_CHECK
+
+void Structure::checkConsistency()
+{
+ if (!m_propertyTable)
+ return;
+
+ ASSERT(m_propertyTable->size >= newTableSize);
+ ASSERT(m_propertyTable->sizeMask);
+ ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1);
+ ASSERT(!(m_propertyTable->size & m_propertyTable->sizeMask));
+
+ ASSERT(m_propertyTable->keyCount <= m_propertyTable->size / 2);
+ ASSERT(m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 4);
+
+ ASSERT(m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 2);
+
+ unsigned indexCount = 0;
+ unsigned deletedIndexCount = 0;
+ for (unsigned a = 0; a != m_propertyTable->size; ++a) {
+ unsigned entryIndex = m_propertyTable->entryIndices[a];
+ if (entryIndex == emptyEntryIndex)
+ continue;
+ if (entryIndex == deletedSentinelIndex) {
+ ++deletedIndexCount;
+ continue;
+ }
+ ASSERT(entryIndex > deletedSentinelIndex);
+ ASSERT(entryIndex - 1 <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount);
+ ++indexCount;
+
+ for (unsigned b = a + 1; b != m_propertyTable->size; ++b)
+ ASSERT(m_propertyTable->entryIndices[b] != entryIndex);
+ }
+ ASSERT(indexCount == m_propertyTable->keyCount);
+ ASSERT(deletedIndexCount == m_propertyTable->deletedSentinelCount);
+
+ ASSERT(m_propertyTable->entries()[0].key == 0);
+
+ unsigned nonEmptyEntryCount = 0;
+ for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
+ UString::Rep* rep = m_propertyTable->entries()[c].key;
+ if (!rep)
+ continue;
+ ++nonEmptyEntryCount;
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ unsigned entryIndex;
+ while (1) {
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ ASSERT(entryIndex != emptyEntryIndex);
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ break;
+ if (k == 0)
+ k = 1 | doubleHash(rep->computedHash());
+ i += k;
+ }
+ ASSERT(entryIndex == c + 1);
+ }
+
+ ASSERT(nonEmptyEntryCount == m_propertyTable->keyCount);
+}
+
+#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Structure_h
+#define Structure_h
+
+#include "Identifier.h"
+#include "JSType.h"
+#include "JSValue.h"
+#include "PropertyMapHashTable.h"
+#include "StructureChain.h"
+#include "StructureTransitionTable.h"
+#include "TypeInfo.h"
+#include "UString.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#ifndef NDEBUG
+#define DUMP_PROPERTYMAP_STATS 0
+#else
+#define DUMP_PROPERTYMAP_STATS 0
+#endif
+
+namespace JSC {
+
+ class PropertyNameArray;
+ class PropertyNameArrayData;
+
+ class Structure : public RefCounted<Structure> {
+ public:
+ friend class JIT;
+ static PassRefPtr<Structure> create(JSValuePtr prototype, const TypeInfo& typeInfo)
+ {
+ return adoptRef(new Structure(prototype, typeInfo));
+ }
+
+ static void startIgnoringLeaks();
+ static void stopIgnoringLeaks();
+
+ static void dumpStatistics();
+
+ static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset);
+ static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, size_t& offset);
+ static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
+ static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValuePtr prototype);
+ static PassRefPtr<Structure> getterSetterTransition(Structure*);
+ static PassRefPtr<Structure> toDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> fromDictionaryTransition(Structure*);
+
+ ~Structure();
+
+ void mark()
+ {
+ if (!m_prototype.marked())
+ m_prototype.mark();
+ }
+
+ // These should be used with caution.
+ size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes);
+ size_t removePropertyWithoutTransition(const Identifier& propertyName);
+ void setPrototypeWithoutTransition(JSValuePtr prototype) { m_prototype = prototype; }
+
+ bool isDictionary() const { return m_isDictionary; }
+
+ const TypeInfo& typeInfo() const { return m_typeInfo; }
+
+ JSValuePtr storedPrototype() const { return m_prototype; }
+ JSValuePtr prototypeForLookup(ExecState*) const;
+ StructureChain* prototypeChain(ExecState*) const;
+
+ Structure* previousID() const { return m_previous.get(); }
+
+ void growPropertyStorageCapacity();
+ size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
+ size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
+
+ size_t get(const Identifier& propertyName);
+ size_t get(const Identifier& propertyName, unsigned& attributes);
+ void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
+
+ bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
+ void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
+
+ bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
+
+ private:
+ Structure(JSValuePtr prototype, const TypeInfo&);
+
+ size_t put(const Identifier& propertyName, unsigned attributes);
+ size_t remove(const Identifier& propertyName);
+ void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
+ void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
+
+ void expandPropertyMapHashTable();
+ void rehashPropertyMapHashTable();
+ void rehashPropertyMapHashTable(unsigned newTableSize);
+ void createPropertyMapHashTable();
+ void createPropertyMapHashTable(unsigned newTableSize);
+ void insertIntoPropertyMapHashTable(const PropertyMapEntry&);
+ void checkConsistency();
+
+ PropertyMapHashTable* copyPropertyTable();
+ void materializePropertyMap();
+ void materializePropertyMapIfNecessary()
+ {
+ if (m_propertyTable || !m_previous)
+ return;
+ materializePropertyMap();
+ }
+
+ void clearEnumerationCache();
+
+ void* addressOfCount()
+ {
+ return &m_refCount;
+ }
+
+ signed char transitionCount() const
+ {
+ // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
+ return m_offset == noOffset ? 0 : m_offset + 1;
+ }
+
+ bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
+
+ static const unsigned emptyEntryIndex = 0;
+
+ static const signed char s_maxTransitionLength = 64;
+
+ static const signed char noOffset = -1;
+
+ TypeInfo m_typeInfo;
+
+ JSValuePtr m_prototype;
+ mutable RefPtr<StructureChain> m_cachedPrototypeChain;
+
+ RefPtr<Structure> m_previous;
+ RefPtr<UString::Rep> m_nameInPrevious;
+
+ union {
+ Structure* singleTransition;
+ StructureTransitionTable* table;
+ } m_transitions;
+
+ RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
+
+ PropertyMapHashTable* m_propertyTable;
+
+ size_t m_propertyStorageCapacity;
+ signed char m_offset;
+
+ bool m_isDictionary : 1;
+ bool m_isPinnedPropertyTable : 1;
+ bool m_hasGetterSetterProperties : 1;
+ bool m_usingSingleTransitionSlot : 1;
+ unsigned m_attributesInPrevious : 5;
+ };
+
+ inline size_t Structure::get(const Identifier& propertyName)
+ {
+ ASSERT(!propertyName.isNull());
+
+ materializePropertyMapIfNecessary();
+ if (!m_propertyTable)
+ return WTF::notFound;
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | WTF::doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+ }
+
+} // namespace JSC
+
+#endif // Structure_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureChain.h"
+
+#include "JSObject.h"
+#include "Structure.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+StructureChain::StructureChain(Structure* head)
+{
+ size_t size = 0;
+ for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
+ ++size;
+
+ m_vector.set(new RefPtr<Structure>[size + 1]);
+
+ size_t i = 0;
+ for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
+ m_vector[i++] = current;
+ m_vector[i] = 0;
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureChain_h
+#define StructureChain_h
+
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class Structure;
+
+ class StructureChain : public RefCounted<StructureChain> {
+ public:
+ static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
+ RefPtr<Structure>* head() { return m_vector.get(); }
+
+ private:
+ StructureChain(Structure* head);
+
+ OwnArrayPtr<RefPtr<Structure> > m_vector;
+ };
+
+} // namespace JSC
+
+#endif // StructureChain_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureTransitionTable_h
+#define StructureTransitionTable_h
+
+#include "UString.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashTraits.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class Structure;
+
+ struct StructureTransitionTableHash {
+ typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
+ static unsigned hash(const Key& p)
+ {
+ return p.first->computedHash();
+ }
+
+ static bool equal(const Key& a, const Key& b)
+ {
+ return a == b;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+
+ struct StructureTransitionTableHashTraits {
+ typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
+ typedef WTF::GenericHashTraits<unsigned> SecondTraits;
+ typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
+
+ static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
+ static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
+
+ static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
+
+ static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
+ static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
+ };
+
+ typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable;
+
+} // namespace JSC
+
+#endif // StructureTransitionTable_h
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SymbolTable_h
+#define SymbolTable_h
+
+#include "JSObject.h"
+#include "UString.h"
+#include <wtf/AlwaysInline.h>
+
+namespace JSC {
+
+ static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
+
+ // The bit twiddling in this class assumes that every register index is a
+ // reasonably small positive or negative number, and therefore has its high
+ // four bits all set or all unset.
+
+ struct SymbolTableEntry {
+ SymbolTableEntry()
+ : m_bits(0)
+ {
+ }
+
+ SymbolTableEntry(int index)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, false, false);
+ }
+
+ SymbolTableEntry(int index, unsigned attributes)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ bool isNull() const
+ {
+ return !m_bits;
+ }
+
+ int getIndex() const
+ {
+ return m_bits >> FlagBits;
+ }
+
+ unsigned getAttributes() const
+ {
+ unsigned attributes = 0;
+ if (m_bits & ReadOnlyFlag)
+ attributes |= ReadOnly;
+ if (m_bits & DontEnumFlag)
+ attributes |= DontEnum;
+ return attributes;
+ }
+
+ void setAttributes(unsigned attributes)
+ {
+ pack(getIndex(), attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ bool isReadOnly() const
+ {
+ return m_bits & ReadOnlyFlag;
+ }
+
+ private:
+ static const unsigned ReadOnlyFlag = 0x1;
+ static const unsigned DontEnumFlag = 0x2;
+ static const unsigned NotNullFlag = 0x4;
+ static const unsigned FlagBits = 3;
+
+ void pack(int index, bool readOnly, bool dontEnum)
+ {
+ m_bits = (index << FlagBits) | NotNullFlag;
+ if (readOnly)
+ m_bits |= ReadOnlyFlag;
+ if (dontEnum)
+ m_bits |= DontEnumFlag;
+ }
+
+ bool isValidIndex(int index)
+ {
+ return ((index << FlagBits) >> FlagBits) == index;
+ }
+
+ int m_bits;
+ };
+
+ struct SymbolTableIndexHashTraits {
+ typedef SymbolTableEntry TraitType;
+ static SymbolTableEntry emptyValue() { return SymbolTableEntry(); }
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ };
+
+ typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
+
+} // namespace JSC
+
+#endif // SymbolTable_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+provider JavaScriptCore
+{
+ probe gc__begin();
+ probe gc__marked();
+ probe gc__end(int, int);
+
+ probe profile__will_execute(int, char*, char*, int);
+ probe profile__did_execute(int, char*, char*, int);
+};
+
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore provider
+#pragma D attributes Private/Private/Unknown provider JavaScriptCore module
+#pragma D attributes Private/Private/Unknown provider JavaScriptCore function
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore name
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore args
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Tracing_h
+#define Tracing_h
+
+#if HAVE(DTRACE)
+#include "TracingDtrace.h"
+#else
+
+#define JAVASCRIPTCORE_GC_BEGIN()
+#define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0
+
+#define JAVASCRIPTCORE_GC_END(arg0, arg1)
+#define JAVASCRIPTCORE_GC_END_ENABLED() 0
+
+#define JAVASCRIPTCORE_GC_MARKED()
+#define JAVASCRIPTCORE_GC_MARKED_ENABLED() 0
+
+#define JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(arg0, arg1, arg2, arg3)
+#define JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED() 0
+
+#define JAVASCRIPTCORE_PROFILE_DID_EXECUTE(arg0, arg1, arg2, arg3)
+#define JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED() 0
+
+#endif
+
+#endif // Tracing_h
--- /dev/null
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TypeInfo_h
+#define TypeInfo_h
+
+#include "JSType.h"
+
+namespace JSC {
+
+ // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
+ static const unsigned MasqueradesAsUndefined = 1;
+ static const unsigned ImplementsHasInstance = 1 << 1;
+ static const unsigned OverridesHasInstance = 1 << 2;
+ static const unsigned NeedsThisConversion = 1 << 3;
+ static const unsigned HasStandardGetOwnPropertySlot = 1 << 4;
+
+ class TypeInfo {
+ friend class JIT;
+ public:
+ TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { }
+
+ JSType type() const { return m_type; }
+
+ bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; }
+ bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
+ bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
+ bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
+ bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; }
+
+ unsigned flags() const { return m_flags; }
+
+ private:
+ JSType m_type;
+ unsigned m_flags;
+ };
+
+}
+
+#endif // TypeInfo_h
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "UString.h"
+
+#include "JSGlobalObjectFunctions.h"
+#include "Collector.h"
+#include "dtoa.h"
+#include "Identifier.h"
+#include "Operations.h"
+#include <ctype.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/UTF8.h>
+
+#if HAVE(STRING_H)
+#include <string.h>
+#endif
+#if HAVE(STRINGS_H)
+#include <strings.h>
+#endif
+
+using namespace WTF;
+using namespace WTF::Unicode;
+using namespace std;
+
+// This can be tuned differently per platform by putting platform #ifs right here.
+// If you don't define this macro at all, then copyChars will just call directly
+// to memcpy.
+#define USTRING_COPY_CHARS_INLINE_CUTOFF 20
+
+namespace JSC {
+
+extern const double NaN;
+extern const double Inf;
+
+static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }
+static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }
+
+static inline UChar* allocChars(size_t length)
+{
+ ASSERT(length);
+ if (length > maxUChars())
+ return 0;
+ return static_cast<UChar*>(tryFastMalloc(sizeof(UChar) * length));
+}
+
+static inline UChar* reallocChars(UChar* buffer, size_t length)
+{
+ ASSERT(length);
+ if (length > maxUChars())
+ return 0;
+ return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length));
+}
+
+static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
+{
+#ifdef USTRING_COPY_CHARS_INLINE_CUTOFF
+ if (numCharacters <= USTRING_COPY_CHARS_INLINE_CUTOFF) {
+ for (unsigned i = 0; i < numCharacters; ++i)
+ destination[i] = source[i];
+ return;
+ }
+#endif
+ memcpy(destination, source, numCharacters * sizeof(UChar));
+}
+
+COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
+
+CString::CString(const char* c)
+ : m_length(strlen(c))
+ , m_data(new char[m_length + 1])
+{
+ memcpy(m_data, c, m_length + 1);
+}
+
+CString::CString(const char* c, size_t length)
+ : m_length(length)
+ , m_data(new char[length + 1])
+{
+ memcpy(m_data, c, m_length);
+ m_data[m_length] = 0;
+}
+
+CString::CString(const CString& b)
+{
+ m_length = b.m_length;
+ if (b.m_data) {
+ m_data = new char[m_length + 1];
+ memcpy(m_data, b.m_data, m_length + 1);
+ } else
+ m_data = 0;
+}
+
+CString::~CString()
+{
+ delete [] m_data;
+}
+
+CString CString::adopt(char* c, size_t length)
+{
+ CString s;
+ s.m_data = c;
+ s.m_length = length;
+ return s;
+}
+
+CString& CString::append(const CString& t)
+{
+ char* n;
+ n = new char[m_length + t.m_length + 1];
+ if (m_length)
+ memcpy(n, m_data, m_length);
+ if (t.m_length)
+ memcpy(n + m_length, t.m_data, t.m_length);
+ m_length += t.m_length;
+ n[m_length] = 0;
+
+ delete [] m_data;
+ m_data = n;
+
+ return *this;
+}
+
+CString& CString::operator=(const char* c)
+{
+ if (m_data)
+ delete [] m_data;
+ m_length = strlen(c);
+ m_data = new char[m_length + 1];
+ memcpy(m_data, c, m_length + 1);
+
+ return *this;
+}
+
+CString& CString::operator=(const CString& str)
+{
+ if (this == &str)
+ return *this;
+
+ if (m_data)
+ delete [] m_data;
+ m_length = str.m_length;
+ if (str.m_data) {
+ m_data = new char[m_length + 1];
+ memcpy(m_data, str.m_data, m_length + 1);
+ } else
+ m_data = 0;
+
+ return *this;
+}
+
+bool operator==(const CString& c1, const CString& c2)
+{
+ size_t len = c1.size();
+ return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
+}
+
+// These static strings are immutable, except for rc, whose initial value is chosen to
+// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
+static UChar sharedEmptyChar;
+UString::BaseString* UString::Rep::nullBaseString;
+UString::BaseString* UString::Rep::emptyBaseString;
+UString* UString::nullUString;
+
+static void initializeStaticBaseString(int len, UChar* buf, UString::BaseString& base)
+{
+ base.offset = 0;
+ base.len = len;
+ base.rc = INT_MAX / 2;
+ base._hash = 0;
+ base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag);
+ base.m_baseString = 0;
+ base.buf = buf;
+ base.preCapacity = 0;
+ base.usedPreCapacity = 0;
+ base.capacity = 0;
+ base.usedCapacity = 0;
+ base.reportedCost = 0;
+ base.checkConsistency();
+}
+
+void initializeUString()
+{
+ UString::Rep::nullBaseString = new UString::BaseString;
+ initializeStaticBaseString(0, 0, *UString::Rep::nullBaseString);
+
+ UString::Rep::emptyBaseString = new UString::BaseString;
+ initializeStaticBaseString(0, &sharedEmptyChar, *UString::Rep::emptyBaseString);
+
+ UString::nullUString = new UString;
+}
+
+static char* statBuffer = 0; // Only used for debugging via UString::ascii().
+
+PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l)
+{
+ UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar)));
+ copyChars(copyD, d, l);
+ return create(copyD, l);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l)
+{
+ BaseString* r = new BaseString;
+ r->offset = 0;
+ r->len = l;
+ r->rc = 1;
+ r->_hash = 0;
+ r->m_baseString = 0;
+ r->reportedCost = 0;
+ r->buf = d;
+ r->usedCapacity = l;
+ r->capacity = l;
+ r->usedPreCapacity = 0;
+ r->preCapacity = 0;
+
+ r->checkConsistency();
+
+ // steal the single reference this Rep was created with
+ return adoptRef(r);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> rep, int offset, int length)
+{
+ ASSERT(rep);
+ rep->checkConsistency();
+
+ int repOffset = rep->offset;
+
+ PassRefPtr<BaseString> base = rep->baseString();
+
+ ASSERT(-(offset + repOffset) <= base->usedPreCapacity);
+ ASSERT(offset + repOffset + length <= base->usedCapacity);
+
+ Rep* r = new Rep;
+ r->offset = repOffset + offset;
+ r->len = length;
+ r->rc = 1;
+ r->_hash = 0;
+ r->setBaseString(base);
+
+ r->checkConsistency();
+
+ // steal the single reference this Rep was created with
+ return adoptRef(r);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string)
+{
+ if (!string)
+ return &UString::Rep::null();
+
+ size_t length = strlen(string);
+ Vector<UChar, 1024> buffer(length);
+ UChar* p = buffer.data();
+ if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
+ return &UString::Rep::null();
+
+ return UString::Rep::createCopying(buffer.data(), p - buffer.data());
+}
+
+void UString::Rep::destroy()
+{
+ checkConsistency();
+
+ // Static null and empty strings can never be destroyed, but we cannot rely on
+ // reference counting, because ref/deref are not thread-safe.
+ if (!isStatic()) {
+ if (identifierTable())
+ Identifier::remove(this);
+ UString::BaseString* base = baseString();
+ if (base == this)
+ fastFree(base->buf);
+ else
+ base->deref();
+
+ delete this;
+ }
+}
+
+// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+// or anything like that.
+const unsigned PHI = 0x9e3779b9U;
+
+// Paul Hsieh's SuperFastHash
+// http://www.azillionmonkeys.com/qed/hash.html
+unsigned UString::Rep::computeHash(const UChar* s, int len)
+{
+ unsigned l = len;
+ uint32_t hash = PHI;
+ uint32_t tmp;
+
+ int rem = l & 1;
+ l >>= 1;
+
+ // Main loop
+ for (; l > 0; l--) {
+ hash += s[0];
+ tmp = (s[1] << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ s += 2;
+ hash += hash >> 11;
+ }
+
+ // Handle end case
+ if (rem) {
+ hash += s[0];
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ }
+
+ // Force "avalanching" of final 127 bits
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 2;
+ hash += hash >> 15;
+ hash ^= hash << 10;
+
+ // this avoids ever returning a hash code of 0, since that is used to
+ // signal "hash not computed yet", using a value that is likely to be
+ // effectively the same as 0 when the low bits are masked
+ if (hash == 0)
+ hash = 0x80000000;
+
+ return hash;
+}
+
+// Paul Hsieh's SuperFastHash
+// http://www.azillionmonkeys.com/qed/hash.html
+unsigned UString::Rep::computeHash(const char* s, int l)
+{
+ // This hash is designed to work on 16-bit chunks at a time. But since the normal case
+ // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
+ // were 16-bit chunks, which should give matching results
+
+ uint32_t hash = PHI;
+ uint32_t tmp;
+
+ size_t rem = l & 1;
+ l >>= 1;
+
+ // Main loop
+ for (; l > 0; l--) {
+ hash += static_cast<unsigned char>(s[0]);
+ tmp = (static_cast<unsigned char>(s[1]) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ s += 2;
+ hash += hash >> 11;
+ }
+
+ // Handle end case
+ if (rem) {
+ hash += static_cast<unsigned char>(s[0]);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ }
+
+ // Force "avalanching" of final 127 bits
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 2;
+ hash += hash >> 15;
+ hash ^= hash << 10;
+
+ // this avoids ever returning a hash code of 0, since that is used to
+ // signal "hash not computed yet", using a value that is likely to be
+ // effectively the same as 0 when the low bits are masked
+ if (hash == 0)
+ hash = 0x80000000;
+
+ return hash;
+}
+
+#ifndef NDEBUG
+void UString::Rep::checkConsistency() const
+{
+ const UString::BaseString* base = baseString();
+
+ // There is no recursion for base strings.
+ ASSERT(base == base->baseString());
+
+ if (isStatic()) {
+ // There are only two static strings: null and empty.
+ ASSERT(!len);
+
+ // Static strings cannot get in identifier tables, because they are globally shared.
+ ASSERT(!identifierTable());
+ }
+
+ // The string fits in buffer.
+ ASSERT(base->usedPreCapacity <= base->preCapacity);
+ ASSERT(base->usedCapacity <= base->capacity);
+ ASSERT(-offset <= base->usedPreCapacity);
+ ASSERT(offset + len <= base->usedCapacity);
+}
+#endif
+
+// put these early so they can be inlined
+static inline size_t expandedSize(size_t size, size_t otherSize)
+{
+ // Do the size calculation in two parts, returning overflowIndicator if
+ // we overflow the maximum value that we can handle.
+
+ if (size > maxUChars())
+ return overflowIndicator();
+
+ size_t expandedSize = ((size + 10) / 10 * 11) + 1;
+ if (maxUChars() - expandedSize < otherSize)
+ return overflowIndicator();
+
+ return expandedSize + otherSize;
+}
+
+static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
+{
+ rep->checkConsistency();
+
+ UString::BaseString* base = rep->baseString();
+
+ if (requiredLength > base->capacity) {
+ size_t newCapacity = expandedSize(requiredLength, base->preCapacity);
+ UChar* oldBuf = base->buf;
+ base->buf = reallocChars(base->buf, newCapacity);
+ if (!base->buf) {
+ base->buf = oldBuf;
+ return false;
+ }
+ base->capacity = newCapacity - base->preCapacity;
+ }
+ if (requiredLength > base->usedCapacity)
+ base->usedCapacity = requiredLength;
+
+ rep->checkConsistency();
+ return true;
+}
+
+void UString::expandCapacity(int requiredLength)
+{
+ if (!JSC::expandCapacity(m_rep.get(), requiredLength))
+ makeNull();
+}
+
+void UString::expandPreCapacity(int requiredPreCap)
+{
+ m_rep->checkConsistency();
+
+ BaseString* base = m_rep->baseString();
+
+ if (requiredPreCap > base->preCapacity) {
+ size_t newCapacity = expandedSize(requiredPreCap, base->capacity);
+ int delta = newCapacity - base->capacity - base->preCapacity;
+
+ UChar* newBuf = allocChars(newCapacity);
+ if (!newBuf) {
+ makeNull();
+ return;
+ }
+ copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity);
+ fastFree(base->buf);
+ base->buf = newBuf;
+
+ base->preCapacity = newCapacity - base->capacity;
+ }
+ if (requiredPreCap > base->usedPreCapacity)
+ base->usedPreCapacity = requiredPreCap;
+
+ m_rep->checkConsistency();
+}
+
+static PassRefPtr<UString::Rep> createRep(const char* c)
+{
+ if (!c)
+ return &UString::Rep::null();
+
+ if (!c[0])
+ return &UString::Rep::empty();
+
+ size_t length = strlen(c);
+ UChar* d = allocChars(length);
+ if (!d)
+ return &UString::Rep::null();
+ else {
+ for (size_t i = 0; i < length; i++)
+ d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+ return UString::Rep::create(d, static_cast<int>(length));
+ }
+
+}
+
+UString::UString(const char* c)
+ : m_rep(createRep(c))
+{
+}
+
+UString::UString(const UChar* c, int length)
+{
+ if (length == 0)
+ m_rep = &Rep::empty();
+ else
+ m_rep = Rep::createCopying(c, length);
+}
+
+UString::UString(UChar* c, int length, bool copy)
+{
+ if (length == 0)
+ m_rep = &Rep::empty();
+ else if (copy)
+ m_rep = Rep::createCopying(c, length);
+ else
+ m_rep = Rep::create(c, length);
+}
+
+UString::UString(const Vector<UChar>& buffer)
+{
+ if (!buffer.size())
+ m_rep = &Rep::empty();
+ else
+ m_rep = Rep::createCopying(buffer.data(), buffer.size());
+}
+
+static ALWAYS_INLINE int newCapacityWithOverflowCheck(const int currentCapacity, const int extendLength, const bool plusOne = false)
+{
+ ASSERT_WITH_MESSAGE(extendLength >= 0, "extendedLength = %d", extendLength);
+
+ const int plusLength = plusOne ? 1 : 0;
+ if (currentCapacity > std::numeric_limits<int>::max() - extendLength - plusLength)
+ CRASH();
+
+ return currentCapacity + extendLength + plusLength;
+}
+
+static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const UChar* tData, int tSize)
+{
+ RefPtr<UString::Rep> rep = r;
+
+ rep->checkConsistency();
+
+ int thisSize = rep->size();
+ int thisOffset = rep->offset;
+ int length = thisSize + tSize;
+ UString::BaseString* base = rep->baseString();
+
+ // possible cases:
+ if (tSize == 0) {
+ // t is empty
+ } else if (thisSize == 0) {
+ // this is empty
+ rep = UString::Rep::createCopying(tData, tSize);
+ } else if (rep == base && rep->rc == 1) {
+ // this is direct and has refcount of 1 (so we can just alter it directly)
+ if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)))
+ rep = &UString::Rep::null();
+ if (rep->data()) {
+ copyChars(rep->data() + thisSize, tData, tSize);
+ rep->len = length;
+ rep->_hash = 0;
+ }
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ // this reaches the end of the buffer - extend it if it's long enough to append to
+ if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)))
+ rep = &UString::Rep::null();
+ if (rep->data()) {
+ copyChars(rep->data() + thisSize, tData, tSize);
+ rep = UString::Rep::create(rep, 0, length);
+ }
+ } else {
+ // this is shared with someone using more capacity, gotta make a whole new string
+ size_t newCapacity = expandedSize(length, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ rep = &UString::Rep::null();
+ else {
+ copyChars(d, rep->data(), thisSize);
+ copyChars(d + thisSize, tData, tSize);
+ rep = UString::Rep::create(d, length);
+ rep->baseString()->capacity = newCapacity;
+ }
+ }
+
+ rep->checkConsistency();
+
+ return rep.release();
+}
+
+static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const char* t)
+{
+ RefPtr<UString::Rep> rep = r;
+
+ rep->checkConsistency();
+
+ int thisSize = rep->size();
+ int thisOffset = rep->offset;
+ int tSize = static_cast<int>(strlen(t));
+ int length = thisSize + tSize;
+ UString::BaseString* base = rep->baseString();
+
+ // possible cases:
+ if (thisSize == 0) {
+ // this is empty
+ rep = createRep(t);
+ } else if (tSize == 0) {
+ // t is empty, we'll just return *this below.
+ } else if (rep == base && rep->rc == 1) {
+ // this is direct and has refcount of 1 (so we can just alter it directly)
+ expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length));
+ UChar* d = rep->data();
+ if (d) {
+ for (int i = 0; i < tSize; ++i)
+ d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+ rep->len = length;
+ rep->_hash = 0;
+ }
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ // this string reaches the end of the buffer - extend it
+ expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length));
+ UChar* d = rep->data();
+ if (d) {
+ for (int i = 0; i < tSize; ++i)
+ d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+ rep = UString::Rep::create(rep, 0, length);
+ }
+ } else {
+ // this is shared with someone using more capacity, gotta make a whole new string
+ size_t newCapacity = expandedSize(length, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ rep = &UString::Rep::null();
+ else {
+ copyChars(d, rep->data(), thisSize);
+ for (int i = 0; i < tSize; ++i)
+ d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+ rep = UString::Rep::create(d, length);
+ rep->baseString()->capacity = newCapacity;
+ }
+ }
+
+ rep->checkConsistency();
+
+ return rep.release();
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b)
+{
+ a->checkConsistency();
+ b->checkConsistency();
+
+ int aSize = a->size();
+ int aOffset = a->offset;
+ int bSize = b->size();
+ int bOffset = b->offset;
+ int length = aSize + bSize;
+
+ // possible cases:
+
+ // a is empty
+ if (aSize == 0)
+ return b;
+ // b is empty
+ if (bSize == 0)
+ return a;
+
+ UString::BaseString* aBase = a->baseString();
+ if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + length <= aBase->capacity) {
+ // b is a single character (common fast case)
+ aBase->usedCapacity = aOffset + length;
+ a->data()[aSize] = b->data()[0];
+ return UString::Rep::create(a, 0, length);
+ }
+
+ UString::BaseString* bBase = b->baseString();
+ if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize
+ && (-bOffset != bBase->usedPreCapacity || aSize >= bSize)) {
+ // - a reaches the end of its buffer so it qualifies for shared append
+ // - also, it's at least a quarter the length of b - appending to a much shorter
+ // string does more harm than good
+ // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
+
+ UString x(a);
+ x.expandCapacity(newCapacityWithOverflowCheck(aOffset, length));
+ if (!a->data() || !x.data())
+ return 0;
+ copyChars(a->data() + aSize, b->data(), bSize);
+ PassRefPtr<UString::Rep> result = UString::Rep::create(a, 0, length);
+
+ a->checkConsistency();
+ b->checkConsistency();
+ result->checkConsistency();
+
+ return result;
+ }
+
+ if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
+ // - b reaches the beginning of its buffer so it qualifies for shared prepend
+ // - also, it's at least a quarter the length of a - prepending to a much shorter
+ // string does more harm than good
+ UString y(b);
+ y.expandPreCapacity(-bOffset + aSize);
+ if (!b->data() || !y.data())
+ return 0;
+ copyChars(b->data() - aSize, a->data(), aSize);
+ PassRefPtr<UString::Rep> result = UString::Rep::create(b, -aSize, length);
+
+ a->checkConsistency();
+ b->checkConsistency();
+ result->checkConsistency();
+
+ return result;
+ }
+
+ // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
+ size_t newCapacity = expandedSize(length, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ return 0;
+ copyChars(d, a->data(), aSize);
+ copyChars(d + aSize, b->data(), bSize);
+ PassRefPtr<UString::Rep> result = UString::Rep::create(d, length);
+ result->baseString()->capacity = newCapacity;
+
+ a->checkConsistency();
+ b->checkConsistency();
+ result->checkConsistency();
+
+ return result;
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
+{
+ UChar buf[1 + sizeof(i) * 3];
+ UChar* end = buf + sizeof(buf) / sizeof(UChar);
+ UChar* p = end;
+
+ if (i == 0)
+ *--p = '0';
+ else if (i == INT_MIN) {
+ char minBuf[1 + sizeof(i) * 3];
+ sprintf(minBuf, "%d", INT_MIN);
+ return concatenate(rep, minBuf);
+ } else {
+ bool negative = false;
+ if (i < 0) {
+ negative = true;
+ i = -i;
+ }
+ while (i) {
+ *--p = static_cast<unsigned short>((i % 10) + '0');
+ i /= 10;
+ }
+ if (negative)
+ *--p = '-';
+ }
+
+ return concatenate(rep, p, static_cast<int>(end - p));
+
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d)
+{
+ // avoid ever printing -NaN, in JS conceptually there is only one NaN value
+ if (isnan(d))
+ return concatenate(rep, "NaN");
+
+ if (d == 0.0) // stringify -0 as 0
+ d = 0.0;
+
+ char buf[80];
+ int decimalPoint;
+ int sign;
+
+ char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+ int length = static_cast<int>(strlen(result));
+
+ int i = 0;
+ if (sign)
+ buf[i++] = '-';
+
+ if (decimalPoint <= 0 && decimalPoint > -6) {
+ buf[i++] = '0';
+ buf[i++] = '.';
+ for (int j = decimalPoint; j < 0; j++)
+ buf[i++] = '0';
+ strcpy(buf + i, result);
+ } else if (decimalPoint <= 21 && decimalPoint > 0) {
+ if (length <= decimalPoint) {
+ strcpy(buf + i, result);
+ i += length;
+ for (int j = 0; j < decimalPoint - length; j++)
+ buf[i++] = '0';
+ buf[i] = '\0';
+ } else {
+ strncpy(buf + i, result, decimalPoint);
+ i += decimalPoint;
+ buf[i++] = '.';
+ strcpy(buf + i, result + decimalPoint);
+ }
+ } else if (result[0] < '0' || result[0] > '9')
+ strcpy(buf + i, result);
+ else {
+ buf[i++] = result[0];
+ if (length > 1) {
+ buf[i++] = '.';
+ strcpy(buf + i, result + 1);
+ i += length - 1;
+ }
+
+ buf[i++] = 'e';
+ buf[i++] = (decimalPoint >= 0) ? '+' : '-';
+ // decimalPoint can't be more than 3 digits decimal given the
+ // nature of float representation
+ int exponential = decimalPoint - 1;
+ if (exponential < 0)
+ exponential = -exponential;
+ if (exponential >= 100)
+ buf[i++] = static_cast<char>('0' + exponential / 100);
+ if (exponential >= 10)
+ buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+ buf[i++] = static_cast<char>('0' + exponential % 10);
+ buf[i++] = '\0';
+ }
+
+ WTF::freedtoa(result);
+
+ return concatenate(rep, buf);
+}
+
+UString UString::from(int i)
+{
+ UChar buf[1 + sizeof(i) * 3];
+ UChar* end = buf + sizeof(buf) / sizeof(UChar);
+ UChar* p = end;
+
+ if (i == 0)
+ *--p = '0';
+ else if (i == INT_MIN) {
+ char minBuf[1 + sizeof(i) * 3];
+ snprintf(minBuf, 1 + sizeof(i) * 3, "%d", INT_MIN);
+ return UString(minBuf);
+ } else {
+ bool negative = false;
+ if (i < 0) {
+ negative = true;
+ i = -i;
+ }
+ while (i) {
+ *--p = static_cast<unsigned short>((i % 10) + '0');
+ i /= 10;
+ }
+ if (negative)
+ *--p = '-';
+ }
+
+ return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(unsigned int u)
+{
+ UChar buf[sizeof(u) * 3];
+ UChar* end = buf + sizeof(buf) / sizeof(UChar);
+ UChar* p = end;
+
+ if (u == 0)
+ *--p = '0';
+ else {
+ while (u) {
+ *--p = static_cast<unsigned short>((u % 10) + '0');
+ u /= 10;
+ }
+ }
+
+ return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(long l)
+{
+ UChar buf[1 + sizeof(l) * 3];
+ UChar* end = buf + sizeof(buf) / sizeof(UChar);
+ UChar* p = end;
+
+ if (l == 0)
+ *--p = '0';
+ else if (l == LONG_MIN) {
+ char minBuf[1 + sizeof(l) * 3];
+ snprintf(minBuf, 1 + sizeof(l) * 3, "%ld", LONG_MIN);
+ return UString(minBuf);
+ } else {
+ bool negative = false;
+ if (l < 0) {
+ negative = true;
+ l = -l;
+ }
+ while (l) {
+ *--p = static_cast<unsigned short>((l % 10) + '0');
+ l /= 10;
+ }
+ if (negative)
+ *--p = '-';
+ }
+
+ return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(double d)
+{
+ // avoid ever printing -NaN, in JS conceptually there is only one NaN value
+ if (isnan(d))
+ return "NaN";
+
+ char buf[80];
+ int decimalPoint;
+ int sign;
+
+ char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+ int length = static_cast<int>(strlen(result));
+
+ int i = 0;
+ if (sign)
+ buf[i++] = '-';
+
+ if (decimalPoint <= 0 && decimalPoint > -6) {
+ buf[i++] = '0';
+ buf[i++] = '.';
+ for (int j = decimalPoint; j < 0; j++)
+ buf[i++] = '0';
+ strlcpy(buf + i, result, sizeof(buf) - i);
+ } else if (decimalPoint <= 21 && decimalPoint > 0) {
+ if (length <= decimalPoint) {
+ strlcpy(buf + i, result, sizeof(buf) - i);
+ i += length;
+ for (int j = 0; j < decimalPoint - length; j++)
+ buf[i++] = '0';
+ buf[i] = '\0';
+ } else {
+ int len = (decimalPoint <= static_cast<int>(sizeof(buf)) - i ? decimalPoint : sizeof(buf) - i);
+ strncpy(buf + i, result, len);
+ i += len;
+ buf[i++] = '.';
+ strlcpy(buf + i, result + decimalPoint, sizeof(buf) - i);
+ }
+ } else if (result[0] < '0' || result[0] > '9')
+ strlcpy(buf + i, result, sizeof(buf) - i);
+ else {
+ buf[i++] = result[0];
+ if (length > 1) {
+ buf[i++] = '.';
+ strlcpy(buf + i, result + 1, sizeof(buf) - i);
+ i += length - 1;
+ }
+
+ buf[i++] = 'e';
+ buf[i++] = (decimalPoint >= 0) ? '+' : '-';
+ // decimalPoint can't be more than 3 digits decimal given the
+ // nature of float representation
+ int exponential = decimalPoint - 1;
+ if (exponential < 0)
+ exponential = -exponential;
+ if (exponential >= 100)
+ buf[i++] = static_cast<char>('0' + exponential / 100);
+ if (exponential >= 10)
+ buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+ buf[i++] = static_cast<char>('0' + exponential % 10);
+ buf[i++] = '\0';
+ ASSERT(i <= static_cast<int>(sizeof(buf)));
+ }
+
+ WTF::freedtoa(result);
+
+ return UString(buf);
+}
+
+UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
+{
+ m_rep->checkConsistency();
+
+ if (rangeCount == 1 && separatorCount == 0) {
+ int thisSize = size();
+ int position = substringRanges[0].position;
+ int length = substringRanges[0].length;
+ if (position <= 0 && length >= thisSize)
+ return *this;
+ return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
+ }
+
+ int totalLength = 0;
+ for (int i = 0; i < rangeCount; i++)
+ totalLength += substringRanges[i].length;
+ for (int i = 0; i < separatorCount; i++)
+ totalLength += separators[i].size();
+
+ if (totalLength == 0)
+ return "";
+
+ UChar* buffer = allocChars(totalLength);
+ if (!buffer)
+ return null();
+
+ int maxCount = max(rangeCount, separatorCount);
+ int bufferPos = 0;
+ for (int i = 0; i < maxCount; i++) {
+ if (i < rangeCount) {
+ copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
+ bufferPos += substringRanges[i].length;
+ }
+ if (i < separatorCount) {
+ copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
+ bufferPos += separators[i].size();
+ }
+ }
+
+ return UString::Rep::create(buffer, totalLength);
+}
+
+UString& UString::append(const UString &t)
+{
+ m_rep->checkConsistency();
+ t.rep()->checkConsistency();
+
+ int thisSize = size();
+ int thisOffset = m_rep->offset;
+ int tSize = t.size();
+ int length = thisSize + tSize;
+ BaseString* base = m_rep->baseString();
+
+ // possible cases:
+ if (thisSize == 0) {
+ // this is empty
+ *this = t;
+ } else if (tSize == 0) {
+ // t is empty
+ } else if (m_rep == base && m_rep->rc == 1) {
+ // this is direct and has refcount of 1 (so we can just alter it directly)
+ expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
+ if (data()) {
+ copyChars(m_rep->data() + thisSize, t.data(), tSize);
+ m_rep->len = length;
+ m_rep->_hash = 0;
+ }
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ // this reaches the end of the buffer - extend it if it's long enough to append to
+ expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
+ if (data()) {
+ copyChars(m_rep->data() + thisSize, t.data(), tSize);
+ m_rep = Rep::create(m_rep, 0, length);
+ }
+ } else {
+ // this is shared with someone using more capacity, gotta make a whole new string
+ size_t newCapacity = expandedSize(length, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ makeNull();
+ else {
+ copyChars(d, data(), thisSize);
+ copyChars(d + thisSize, t.data(), tSize);
+ m_rep = Rep::create(d, length);
+ m_rep->baseString()->capacity = newCapacity;
+ }
+ }
+
+ m_rep->checkConsistency();
+ t.rep()->checkConsistency();
+
+ return *this;
+}
+
+UString& UString::append(const UChar* tData, int tSize)
+{
+ m_rep = concatenate(m_rep.release(), tData, tSize);
+ return *this;
+}
+
+UString& UString::append(const char* t)
+{
+ m_rep = concatenate(m_rep.release(), t);
+ return *this;
+}
+
+UString& UString::append(UChar c)
+{
+ m_rep->checkConsistency();
+
+ int thisOffset = m_rep->offset;
+ int length = size();
+ BaseString* base = m_rep->baseString();
+
+ // possible cases:
+ if (length == 0) {
+ // this is empty - must make a new m_rep because we don't want to pollute the shared empty one
+ size_t newCapacity = expandedSize(1, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ makeNull();
+ else {
+ d[0] = c;
+ m_rep = Rep::create(d, 1);
+ m_rep->baseString()->capacity = newCapacity;
+ }
+ } else if (m_rep == base && m_rep->rc == 1) {
+ // this is direct and has refcount of 1 (so we can just alter it directly)
+ expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true));
+ UChar* d = m_rep->data();
+ if (d) {
+ d[length] = c;
+ m_rep->len = length + 1;
+ m_rep->_hash = 0;
+ }
+ } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) {
+ // this reaches the end of the string - extend it and share
+ expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true));
+ UChar* d = m_rep->data();
+ if (d) {
+ d[length] = c;
+ m_rep = Rep::create(m_rep, 0, length + 1);
+ }
+ } else {
+ // this is shared with someone using more capacity, gotta make a whole new string
+ size_t newCapacity = expandedSize(length + 1, 0);
+ UChar* d = allocChars(newCapacity);
+ if (!d)
+ makeNull();
+ else {
+ copyChars(d, data(), length);
+ d[length] = c;
+ m_rep = Rep::create(d, length + 1);
+ m_rep->baseString()->capacity = newCapacity;
+ }
+ }
+
+ m_rep->checkConsistency();
+
+ return *this;
+}
+
+bool UString::getCString(CStringBuffer& buffer) const
+{
+ int length = size();
+ int neededSize = length + 1;
+ buffer.resize(neededSize);
+ char* buf = buffer.data();
+
+ UChar ored = 0;
+ const UChar* p = data();
+ char* q = buf;
+ const UChar* limit = p + length;
+ while (p != limit) {
+ UChar c = p[0];
+ ored |= c;
+ *q = static_cast<char>(c);
+ ++p;
+ ++q;
+ }
+ *q = '\0';
+
+ return !(ored & 0xFF00);
+}
+
+char* UString::ascii() const
+{
+ int length = size();
+ int neededSize = length + 1;
+ delete[] statBuffer;
+ statBuffer = new char[neededSize];
+
+ const UChar* p = data();
+ char* q = statBuffer;
+ const UChar* limit = p + length;
+ while (p != limit) {
+ *q = static_cast<char>(p[0]);
+ ++p;
+ ++q;
+ }
+ *q = '\0';
+
+ return statBuffer;
+}
+
+UString& UString::operator=(const char* c)
+{
+ if (!c) {
+ m_rep = &Rep::null();
+ return *this;
+ }
+
+ if (!c[0]) {
+ m_rep = &Rep::empty();
+ return *this;
+ }
+
+ int l = static_cast<int>(strlen(c));
+ UChar* d;
+ BaseString* base = m_rep->baseString();
+ if (m_rep->rc == 1 && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) {
+ d = base->buf;
+ m_rep->_hash = 0;
+ m_rep->len = l;
+ } else {
+ d = allocChars(l);
+ if (!d) {
+ makeNull();
+ return *this;
+ }
+ m_rep = Rep::create(d, l);
+ }
+ for (int i = 0; i < l; i++)
+ d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+
+ return *this;
+}
+
+bool UString::is8Bit() const
+{
+ const UChar* u = data();
+ const UChar* limit = u + size();
+ while (u < limit) {
+ if (u[0] > 0xFF)
+ return false;
+ ++u;
+ }
+
+ return true;
+}
+
+UChar UString::operator[](int pos) const
+{
+ if (pos >= size())
+ return '\0';
+ return data()[pos];
+}
+
+double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
+{
+ if (size() == 1) {
+ UChar c = data()[0];
+ if (isASCIIDigit(c))
+ return c - '0';
+ if (isASCIISpace(c) && tolerateEmptyString)
+ return 0;
+ return NaN;
+ }
+
+ // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
+ // after the number, so this is too strict a check.
+ CStringBuffer s;
+ if (!getCString(s))
+ return NaN;
+ const char* c = s.data();
+
+ // skip leading white space
+ while (isASCIISpace(*c))
+ c++;
+
+ // empty string ?
+ if (*c == '\0')
+ return tolerateEmptyString ? 0.0 : NaN;
+
+ double d;
+
+ // hex number ?
+ if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
+ const char* firstDigitPosition = c + 2;
+ c++;
+ d = 0.0;
+ while (*(++c)) {
+ if (*c >= '0' && *c <= '9')
+ d = d * 16.0 + *c - '0';
+ else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
+ d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
+ else
+ break;
+ }
+
+ if (d >= mantissaOverflowLowerBound)
+ d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
+ } else {
+ // regular number ?
+ char* end;
+ d = WTF::strtod(c, &end);
+ if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
+ c = end;
+ } else {
+ double sign = 1.0;
+
+ if (*c == '+')
+ c++;
+ else if (*c == '-') {
+ sign = -1.0;
+ c++;
+ }
+
+ // We used strtod() to do the conversion. However, strtod() handles
+ // infinite values slightly differently than JavaScript in that it
+ // converts the string "inf" with any capitalization to infinity,
+ // whereas the ECMA spec requires that it be converted to NaN.
+
+ if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
+ d = sign * Inf;
+ c += 8;
+ } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
+ c = end;
+ else
+ return NaN;
+ }
+ }
+
+ // allow trailing white space
+ while (isASCIISpace(*c))
+ c++;
+ // don't allow anything after - unless tolerant=true
+ if (!tolerateTrailingJunk && *c != '\0')
+ d = NaN;
+
+ return d;
+}
+
+double UString::toDouble(bool tolerateTrailingJunk) const
+{
+ return toDouble(tolerateTrailingJunk, true);
+}
+
+double UString::toDouble() const
+{
+ return toDouble(false, true);
+}
+
+uint32_t UString::toUInt32(bool* ok) const
+{
+ double d = toDouble();
+ bool b = true;
+
+ if (d != static_cast<uint32_t>(d)) {
+ b = false;
+ d = 0;
+ }
+
+ if (ok)
+ *ok = b;
+
+ return static_cast<uint32_t>(d);
+}
+
+uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
+{
+ double d = toDouble(false, tolerateEmptyString);
+ bool b = true;
+
+ if (d != static_cast<uint32_t>(d)) {
+ b = false;
+ d = 0;
+ }
+
+ if (ok)
+ *ok = b;
+
+ return static_cast<uint32_t>(d);
+}
+
+uint32_t UString::toStrictUInt32(bool* ok) const
+{
+ if (ok)
+ *ok = false;
+
+ // Empty string is not OK.
+ int len = m_rep->len;
+ if (len == 0)
+ return 0;
+ const UChar* p = m_rep->data();
+ unsigned short c = p[0];
+
+ // If the first digit is 0, only 0 itself is OK.
+ if (c == '0') {
+ if (len == 1 && ok)
+ *ok = true;
+ return 0;
+ }
+
+ // Convert to UInt32, checking for overflow.
+ uint32_t i = 0;
+ while (1) {
+ // Process character, turning it into a digit.
+ if (c < '0' || c > '9')
+ return 0;
+ const unsigned d = c - '0';
+
+ // Multiply by 10, checking for overflow out of 32 bits.
+ if (i > 0xFFFFFFFFU / 10)
+ return 0;
+ i *= 10;
+
+ // Add in the digit, checking for overflow out of 32 bits.
+ const unsigned max = 0xFFFFFFFFU - d;
+ if (i > max)
+ return 0;
+ i += d;
+
+ // Handle end of string.
+ if (--len == 0) {
+ if (ok)
+ *ok = true;
+ return i;
+ }
+
+ // Get next character.
+ c = *(++p);
+ }
+}
+
+int UString::find(const UString& f, int pos) const
+{
+ int fsz = f.size();
+
+ if (pos < 0)
+ pos = 0;
+
+ if (fsz == 1) {
+ UChar ch = f[0];
+ const UChar* end = data() + size();
+ for (const UChar* c = data() + pos; c < end; c++) {
+ if (*c == ch)
+ return static_cast<int>(c - data());
+ }
+ return -1;
+ }
+
+ int sz = size();
+ if (sz < fsz)
+ return -1;
+ if (fsz == 0)
+ return pos;
+ const UChar* end = data() + sz - fsz;
+ int fsizeminusone = (fsz - 1) * sizeof(UChar);
+ const UChar* fdata = f.data();
+ unsigned short fchar = fdata[0];
+ ++fdata;
+ for (const UChar* c = data() + pos; c <= end; c++) {
+ if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
+ return static_cast<int>(c - data());
+ }
+
+ return -1;
+}
+
+int UString::find(UChar ch, int pos) const
+{
+ if (pos < 0)
+ pos = 0;
+ const UChar* end = data() + size();
+ for (const UChar* c = data() + pos; c < end; c++) {
+ if (*c == ch)
+ return static_cast<int>(c - data());
+ }
+
+ return -1;
+}
+
+int UString::rfind(const UString& f, int pos) const
+{
+ int sz = size();
+ int fsz = f.size();
+ if (sz < fsz)
+ return -1;
+ if (pos < 0)
+ pos = 0;
+ if (pos > sz - fsz)
+ pos = sz - fsz;
+ if (fsz == 0)
+ return pos;
+ int fsizeminusone = (fsz - 1) * sizeof(UChar);
+ const UChar* fdata = f.data();
+ for (const UChar* c = data() + pos; c >= data(); c--) {
+ if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
+ return static_cast<int>(c - data());
+ }
+
+ return -1;
+}
+
+int UString::rfind(UChar ch, int pos) const
+{
+ if (isEmpty())
+ return -1;
+ if (pos + 1 >= size())
+ pos = size() - 1;
+ for (const UChar* c = data() + pos; c >= data(); c--) {
+ if (*c == ch)
+ return static_cast<int>(c - data());
+ }
+
+ return -1;
+}
+
+UString UString::substr(int pos, int len) const
+{
+ int s = size();
+
+ if (pos < 0)
+ pos = 0;
+ else if (pos >= s)
+ pos = s;
+ if (len < 0)
+ len = s;
+ if (pos + len >= s)
+ len = s - pos;
+
+ if (pos == 0 && len == s)
+ return *this;
+
+ return UString(Rep::create(m_rep, pos, len));
+}
+
+bool operator==(const UString& s1, const UString& s2)
+{
+ int size = s1.size();
+ switch (size) {
+ case 0:
+ return !s2.size();
+ case 1:
+ return s2.size() == 1 && s1.data()[0] == s2.data()[0];
+ default:
+ return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
+ }
+}
+
+bool operator==(const UString& s1, const char *s2)
+{
+ if (s2 == 0)
+ return s1.isEmpty();
+
+ const UChar* u = s1.data();
+ const UChar* uend = u + s1.size();
+ while (u != uend && *s2) {
+ if (u[0] != (unsigned char)*s2)
+ return false;
+ s2++;
+ u++;
+ }
+
+ return u == uend && *s2 == 0;
+}
+
+bool operator<(const UString& s1, const UString& s2)
+{
+ const int l1 = s1.size();
+ const int l2 = s2.size();
+ const int lmin = l1 < l2 ? l1 : l2;
+ const UChar* c1 = s1.data();
+ const UChar* c2 = s2.data();
+ int l = 0;
+ while (l < lmin && *c1 == *c2) {
+ c1++;
+ c2++;
+ l++;
+ }
+ if (l < lmin)
+ return (c1[0] < c2[0]);
+
+ return (l1 < l2);
+}
+
+bool operator>(const UString& s1, const UString& s2)
+{
+ const int l1 = s1.size();
+ const int l2 = s2.size();
+ const int lmin = l1 < l2 ? l1 : l2;
+ const UChar* c1 = s1.data();
+ const UChar* c2 = s2.data();
+ int l = 0;
+ while (l < lmin && *c1 == *c2) {
+ c1++;
+ c2++;
+ l++;
+ }
+ if (l < lmin)
+ return (c1[0] > c2[0]);
+
+ return (l1 > l2);
+}
+
+int compare(const UString& s1, const UString& s2)
+{
+ const int l1 = s1.size();
+ const int l2 = s2.size();
+ const int lmin = l1 < l2 ? l1 : l2;
+ const UChar* c1 = s1.data();
+ const UChar* c2 = s2.data();
+ int l = 0;
+ while (l < lmin && *c1 == *c2) {
+ c1++;
+ c2++;
+ l++;
+ }
+
+ if (l < lmin)
+ return (c1[0] > c2[0]) ? 1 : -1;
+
+ if (l1 == l2)
+ return 0;
+
+ return (l1 > l2) ? 1 : -1;
+}
+
+bool equal(const UString::Rep* r, const UString::Rep* b)
+{
+ int length = r->len;
+ if (length != b->len)
+ return false;
+ const UChar* d = r->data();
+ const UChar* s = b->data();
+ for (int i = 0; i != length; ++i) {
+ if (d[i] != s[i])
+ return false;
+ }
+ return true;
+}
+
+CString UString::UTF8String(bool strict) const
+{
+ // Allocate a buffer big enough to hold all the characters.
+ const int length = size();
+ Vector<char, 1024> buffer(length * 3);
+
+ // Convert to runs of 8-bit characters.
+ char* p = buffer.data();
+ const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
+ ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
+ if (result != conversionOK)
+ return CString();
+
+ return CString(buffer.data(), p - buffer.data());
+}
+
+// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
+NEVER_INLINE void UString::makeNull()
+{
+ m_rep = &Rep::null();
+}
+
+// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
+NEVER_INLINE UString::Rep* UString::nullRep()
+{
+ return &Rep::null();
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef UString_h
+#define UString_h
+
+#include "Collector.h"
+#include <stdint.h>
+#include <string.h>
+#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/PtrAndFlags.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC {
+
+ using WTF::PlacementNewAdoptType;
+ using WTF::PlacementNewAdopt;
+
+ class IdentifierTable;
+
+ class CString {
+ public:
+ CString()
+ : m_length(0)
+ , m_data(0)
+ {
+ }
+
+ CString(const char*);
+ CString(const char*, size_t);
+ CString(const CString&);
+
+ ~CString();
+
+ static CString adopt(char*, size_t); // buffer should be allocated with new[].
+
+ CString& append(const CString&);
+ CString& operator=(const char* c);
+ CString& operator=(const CString&);
+ CString& operator+=(const CString& c) { return append(c); }
+
+ size_t size() const { return m_length; }
+ const char* c_str() const { return m_data; }
+
+ private:
+ size_t m_length;
+ char* m_data;
+ };
+
+ typedef Vector<char, 32> CStringBuffer;
+
+ class UString {
+ friend class JIT;
+
+ public:
+ struct BaseString;
+ struct Rep : Noncopyable {
+ friend class JIT;
+
+ static PassRefPtr<Rep> create(UChar*, int);
+ static PassRefPtr<Rep> createCopying(const UChar*, int);
+ static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
+
+ // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h).
+ // Returns UString::Rep::null for null input or conversion failure.
+ static PassRefPtr<Rep> createFromUTF8(const char*);
+
+ void destroy();
+
+ bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); }
+ UChar* data() const;
+ int size() const { return len; }
+
+ unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; }
+ unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers
+
+ static unsigned computeHash(const UChar*, int length);
+ static unsigned computeHash(const char*, int length);
+ static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); }
+
+ IdentifierTable* identifierTable() const { return m_identifierTableAndFlags.get(); }
+ void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); }
+
+ bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); }
+ void setStatic(bool);
+ void setBaseString(PassRefPtr<BaseString>);
+ BaseString* baseString();
+ const BaseString* baseString() const;
+
+ Rep* ref() { ++rc; return this; }
+ ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
+
+ void checkConsistency() const;
+ enum UStringFlags {
+ StaticFlag,
+ BaseStringFlag
+ };
+
+ // unshared data
+ int offset;
+ int len;
+ int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted.
+ mutable unsigned _hash;
+ PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags;
+ void* m_baseString; // If "this" is a BaseString instance, it is 0. BaseString* otherwise.
+
+ static BaseString& null() { return *nullBaseString; }
+ static BaseString& empty() { return *emptyBaseString; }
+
+ private:
+ friend void initializeUString();
+ static BaseString* nullBaseString;
+ static BaseString* emptyBaseString;
+ };
+
+ struct BaseString : public Rep {
+ BaseString()
+ {
+ m_identifierTableAndFlags.setFlag(BaseStringFlag);
+ }
+
+ // potentially shared data.
+ UChar* buf;
+ int preCapacity;
+ int usedPreCapacity;
+ int capacity;
+ int usedCapacity;
+
+ size_t reportedCost;
+ };
+
+ public:
+ UString();
+ UString(const char*);
+ UString(const UChar*, int length);
+ UString(UChar*, int length, bool copy);
+
+ UString(const UString& s)
+ : m_rep(s.m_rep)
+ {
+ }
+
+ UString(const Vector<UChar>& buffer);
+
+ ~UString()
+ {
+ }
+
+ // Special constructor for cases where we overwrite an object in place.
+ UString(PlacementNewAdoptType)
+ : m_rep(PlacementNewAdopt)
+ {
+ }
+
+ static UString from(int);
+ static UString from(unsigned int);
+ static UString from(long);
+ static UString from(double);
+
+ struct Range {
+ public:
+ Range(int pos, int len)
+ : position(pos)
+ , length(len)
+ {
+ }
+
+ Range()
+ {
+ }
+
+ int position;
+ int length;
+ };
+
+ UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
+
+ UString& append(const UString&);
+ UString& append(const char*);
+ UString& append(UChar);
+ UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
+ UString& append(const UChar*, int size);
+
+ bool getCString(CStringBuffer&) const;
+
+ // NOTE: This method should only be used for *debugging* purposes as it
+ // is neither Unicode safe nor free from side effects nor thread-safe.
+ char* ascii() const;
+
+ /**
+ * Convert the string to UTF-8, assuming it is UTF-16 encoded.
+ * In non-strict mode, this function is tolerant of badly formed UTF-16, it
+ * can create UTF-8 strings that are invalid because they have characters in
+ * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
+ * guaranteed to be otherwise valid.
+ * In strict mode, error is returned as null CString.
+ */
+ CString UTF8String(bool strict = false) const;
+
+ UString& operator=(const char*c);
+
+ UString& operator+=(const UString& s) { return append(s); }
+ UString& operator+=(const char* s) { return append(s); }
+
+ const UChar* data() const { return m_rep->data(); }
+
+ bool isNull() const { return (m_rep == &Rep::null()); }
+ bool isEmpty() const { return (!m_rep->len); }
+
+ bool is8Bit() const;
+
+ int size() const { return m_rep->size(); }
+
+ UChar operator[](int pos) const;
+
+ double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
+ double toDouble(bool tolerateTrailingJunk) const;
+ double toDouble() const;
+
+ uint32_t toUInt32(bool* ok = 0) const;
+ uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
+ uint32_t toStrictUInt32(bool* ok = 0) const;
+
+ unsigned toArrayIndex(bool* ok = 0) const;
+
+ int find(const UString& f, int pos = 0) const;
+ int find(UChar, int pos = 0) const;
+ int rfind(const UString& f, int pos) const;
+ int rfind(UChar, int pos) const;
+
+ UString substr(int pos = 0, int len = -1) const;
+
+ static const UString& null() { return *nullUString; }
+
+ Rep* rep() const { return m_rep.get(); }
+ static Rep* nullRep();
+
+ UString(PassRefPtr<Rep> r)
+ : m_rep(r)
+ {
+ ASSERT(m_rep);
+ }
+
+ size_t cost() const;
+
+ private:
+ void expandCapacity(int requiredLength);
+ void expandPreCapacity(int requiredPreCap);
+ void makeNull();
+
+ RefPtr<Rep> m_rep;
+ static UString* nullUString;
+
+ friend void initializeUString();
+ friend bool operator==(const UString&, const UString&);
+ friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory
+ };
+ PassRefPtr<UString::Rep> concatenate(UString::Rep*, UString::Rep*);
+ PassRefPtr<UString::Rep> concatenate(UString::Rep*, int);
+ PassRefPtr<UString::Rep> concatenate(UString::Rep*, double);
+
+ bool operator==(const UString&, const UString&);
+
+ inline bool operator!=(const UString& s1, const UString& s2)
+ {
+ return !JSC::operator==(s1, s2);
+ }
+
+ bool operator<(const UString& s1, const UString& s2);
+ bool operator>(const UString& s1, const UString& s2);
+
+ bool operator==(const UString& s1, const char* s2);
+
+ inline bool operator!=(const UString& s1, const char* s2)
+ {
+ return !JSC::operator==(s1, s2);
+ }
+
+ inline bool operator==(const char *s1, const UString& s2)
+ {
+ return operator==(s2, s1);
+ }
+
+ inline bool operator!=(const char *s1, const UString& s2)
+ {
+ return !JSC::operator==(s1, s2);
+ }
+
+ bool operator==(const CString&, const CString&);
+
+ inline UString operator+(const UString& s1, const UString& s2)
+ {
+ RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep());
+ return UString(result ? result.release() : UString::nullRep());
+ }
+
+ int compare(const UString&, const UString&);
+
+ bool equal(const UString::Rep*, const UString::Rep*);
+
+ inline UChar* UString::Rep::data() const
+ {
+ const BaseString* base = baseString();
+ return base->buf + base->preCapacity + offset;
+ }
+
+ inline void UString::Rep::setStatic(bool v)
+ {
+ ASSERT(!identifierTable());
+ if (v)
+ m_identifierTableAndFlags.setFlag(StaticFlag);
+ else
+ m_identifierTableAndFlags.clearFlag(StaticFlag);
+ }
+
+ inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base)
+ {
+ ASSERT(base != this);
+ m_baseString = base.releaseRef();
+ }
+
+ inline UString::BaseString* UString::Rep::baseString()
+ {
+ return reinterpret_cast<BaseString*>(baseIsSelf() ? this : m_baseString);
+ }
+
+ inline const UString::BaseString* UString::Rep::baseString() const
+ {
+ return const_cast<const BaseString*>(const_cast<Rep*>(this)->baseString());
+ }
+
+#ifdef NDEBUG
+ inline void UString::Rep::checkConsistency() const
+ {
+ }
+#endif
+
+ inline UString::UString()
+ : m_rep(&Rep::null())
+ {
+ }
+
+ // Rule from ECMA 15.2 about what an array index is.
+ // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
+ inline unsigned UString::toArrayIndex(bool* ok) const
+ {
+ unsigned i = toStrictUInt32(ok);
+ if (ok && i >= 0xFFFFFFFFU)
+ *ok = false;
+ return i;
+ }
+
+ // We'd rather not do shared substring append for small strings, since
+ // this runs too much risk of a tiny initial string holding down a
+ // huge buffer.
+ // FIXME: this should be size_t but that would cause warnings until we
+ // fix UString sizes to be size_t instead of int
+ static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar);
+
+ inline size_t UString::cost() const
+ {
+ BaseString* base = m_rep->baseString();
+ size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar);
+ size_t reportedCost = base->reportedCost;
+ ASSERT(capacity >= reportedCost);
+
+ size_t capacityDelta = capacity - reportedCost;
+
+ if (capacityDelta < static_cast<size_t>(minShareSize))
+ return 0;
+
+ base->reportedCost = capacity;
+
+ return capacityDelta;
+ }
+
+ struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
+ static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); }
+ static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); }
+ };
+
+ void initializeUString();
+} // namespace JSC
+
+namespace WTF {
+
+ template<typename T> struct DefaultHash;
+ template<typename T> struct StrHash;
+
+ template<> struct StrHash<JSC::UString::Rep*> {
+ static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); }
+ static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return JSC::equal(a, b); }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+ };
+
+ template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> {
+ using StrHash<JSC::UString::Rep*>::hash;
+ static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); }
+ using StrHash<JSC::UString::Rep*>::equal;
+ static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a.get(), b.get()); }
+ static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a, b.get()); }
+ static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return JSC::equal(a.get(), b); }
+
+ static const bool safeToCompareToEmptyOrDeleted = false;
+ };
+
+ template<> struct DefaultHash<JSC::UString::Rep*> {
+ typedef StrHash<JSC::UString::Rep*> Hash;
+ };
+
+ template<> struct DefaultHash<RefPtr<JSC::UString::Rep> > {
+ typedef StrHash<RefPtr<JSC::UString::Rep> > Hash;
+
+ };
+
+} // namespace WTF
+
+#endif
return ( x.valueOf() == y.valueOf() ? 0 : ( x.valueOf() > y.valueOf() ? 1 : -1 ) );
}
function comparefn3( x, y ) {
- return ( x == y ? 0 : ( x > y ? 1: -1 ) );
+ return ( +x == +y ? 0 : ( x > y ? 1 : -1 ) );
}
function clone( source, target ) {
for (i = 0; i < source.length; i++ ) {
<html><head>
-<title>Test results, kjs</title>
+<title>Test results, squirrelfish</title>
</head>
<body bgcolor='white'>
<a name='tippy_top'></a>
-<h2>Test results, kjs</h2><br>
+<h2>Test results, squirrelfish</h2><br>
<p class='results_summary'>
Test List: All tests<br>
Skip List: (none)<br>
-1135 test(s) selected, 1127 test(s) completed, 52 failures reported (4.61% failed)<br>
-Engine command line: /symroots/Development/testkjs <br>
-OS type: Darwin dkilzer.apple.com 9.1.0 Darwin Kernel Version 9.1.0: Wed Oct 31 17:48:21 PDT 2007; root:xnu-1228.0.2~1/RELEASE_PPC Power Macintosh<br>
-Testcase execution time: 4 minutes, 34 seconds.<br>
-Tests completed on Sat Jan 5 15:45:34 2008.<br><br>
+1135 test(s) selected, 1127 test(s) completed, 50 failures reported (4.43% failed)<br>
+Engine command line: "/Users/Cameron/WebKit/WebKitBuild/Debug/jsc" <br>
+OS type: Darwin d141-97-200.home.cgocable.net 9.5.0 Darwin Kernel Version 9.5.0: Wed Sep 3 11:29:43 PDT 2008; root:xnu-1228.7.58~1/RELEASE_I386 i386<br>
+Testcase execution time: 1 minutes, 10 seconds.<br>
+Tests completed on Thu Sep 18 02:24:54 2008.<br><br>
[ <a href='#fail_detail'>Failure Details</a> | <a href='#retest_list'>Retest List</a> | <a href='menu.html'>Test Selection Page</a> ]<br>
<hr>
<a name='fail_detail'></a>
(Mon Feb 28 2000 16:00:00 GMT-0800 (PST)).toLocaleTimeString() = 4:00:00 PM PST FAILED! expected: 16:00:00<br>
(Mon Feb 28 2000 15:59:59 GMT-0800 (PST)).toLocaleTimeString() = 3:59:59 PM PST FAILED! expected: 15:59:59<br>
(Tue Feb 29 2000 00:00:00 GMT-0800 (PST)).toLocaleTimeString() = 12:00:00 AM PST FAILED! expected: 00:00:00<br>
-(Sat Jan 05 2008 15:44:42 GMT-0800 (PST)).toLocaleTimeString() = 3:44:42 PM PST FAILED! expected: 15:44:42<br>
-(Sat Jan 05 2008 23:44:42 GMT-0800 (PST)).toLocaleTimeString() = 11:44:42 PM PST FAILED! expected: 23:44:42<br>
+(Thu Sep 18 2008 02:24:30 GMT-0700 (PDT)).toLocaleTimeString() = 2:24:30 AM PDT FAILED! expected: 02:24:30<br>
+(Thu Sep 18 2008 10:24:30 GMT-0700 (PDT)).toLocaleTimeString() = 10:24:30 AM PDT FAILED! expected: 10:24:30<br>
(Fri Dec 31 2004 16:00:00 GMT-0800 (PST)).toLocaleTimeString() = 4:00:00 PM PST FAILED! expected: 16:00:00<br>
(Fri Dec 31 2004 15:59:59 GMT-0800 (PST)).toLocaleTimeString() = 3:59:59 PM PST FAILED! expected: 15:59:59<br>
(Sat Jan 01 2005 00:00:00 GMT-0800 (PST)).toLocaleTimeString() = 12:00:00 AM PST FAILED! expected: 00:00:00<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40229] ./ecma_3/Statements/regress-194364.js line 1: SyntaxError: Parse error<br>
-</tt><br>
+Testcase produced no output!</tt><br>
<a name='failure9'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-001.js'>ecma_3/Unicode/uc-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23610' target='other_window'>Bug Number 23610</a><br>
[ <a href='#failure8'>Previous Failure</a> | <a href='#failure10'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Unicode format-control character (Category Cf) test.<br>
FAILED!: [reported from test()] Expected value 'no error', Actual value 'no‎ error'<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-002.js'>ecma_3/Unicode/uc-002.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23613' target='other_window'>Bug Number 23613</a><br>
+<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br>
[ <a href='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>STATUS: Unicode non-breaking space character test.<br>
-Failure messages were:<br>
-FAILED!: [reported from test()] Unicode non-breaking space character regexp test.<br>
-FAILED!: [reported from test()] Expected value '0', Actual value '-1'<br>
-FAILED!: [reported from test()] <br>
-</tt><br>
-<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br>
- [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
var o = new Object(); o.toString() = [object Object] FAILED! expected: {}<br>
o = {}; o.toString() = [object Object] FAILED! expected: {}<br>
o = { name:"object", length:0, value:"hello" }; o.toString() = false FAILED! expected: true<br>
</tt><br>
-<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br>
- [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br>
+ [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
-f.name = undefined FAILED! expected: a_test_function<br>
f.arity = undefined FAILED! expected: 3<br>
-(new Function()).name = undefined FAILED! expected: anonymous<br>
-} FAILED! expected: <br>
+(new Function()).toString() = function anonymous() {} FAILED! expected: <br>
</tt><br>
-<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br>
- [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br>
+ [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 3, got 0<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
</tt><br>
-<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br>
- [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br>
+ [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
} FAILED! expected: <br>
} FAILED! expected: <br>
} FAILED! expected: <br>
} FAILED! expected: <br>
-} FAILED! expected: <br>
+f.toString() = function anonymous() {return "hello!"} FAILED! expected: <br>
</tt><br>
-<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br>
- [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br>
+ [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
} FAILED! expected: <br>
} FAILED! expected: <br>
} FAILED! expected: <br>
</tt><br>
-<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br>
- [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br>
+ [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
(new String('x') == 'x') = true FAILED! expected: false<br>
('x' == new String('x')) = true FAILED! expected: false<br>
</tt><br>
-<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br>
- [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br>
+ [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
re=/x./g; re.lastIndex=4; re.exec('xyabcdxa') = xa FAILED! expected: ["xa"]<br>
re.exec('xyabcdef') = xy FAILED! expected: ["xy"]<br>
</tt><br>
-<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline.js'>js1_2/regexp/RegExp_multiline.js</a> failed</b> <br>
- [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline.js'>js1_2/regexp/RegExp_multiline.js</a> failed</b> <br>
+ [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
(multiline == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br>
(multiline == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br>
(multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br>
</tt><br>
-<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline_as_array.js'>js1_2/regexp/RegExp_multiline_as_array.js</a> failed</b> <br>
- [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline_as_array.js'>js1_2/regexp/RegExp_multiline_as_array.js</a> failed</b> <br>
+ [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
(['$*'] == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br>
(['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br>
(['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br>
</tt><br>
-<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br>
- [ <a href='#failure19'>Previous Failure</a> | <a href='#failure21'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br>
+ [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
123xyz'.match(new RegExp('^\d+')) = null FAILED! expected: 123<br>
</tt><br>
-<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br>
- [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br>
+ [ <a href='#failure19'>Previous Failure</a> | <a href='#failure21'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
xyz'.match(new RegExp('\d+$')) = null FAILED! expected: 890<br>
</tt><br>
-<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br>
- [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br>
+ [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
'abc'.split(/[a-z]/) = ,,, FAILED! expected: ,,<br>
'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br>
'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br>
</tt><br>
-<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br>
- [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br>
+ [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
new Boolean(false) = true FAILED! expected: false<br>
</tt><br>
-<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br>
- [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br>
+ [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Regression test for Bugzilla bug 99663<br>
Failure messages were:<br>
Section 1 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
Section 2 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
Section 3 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
</tt><br>
-<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
- [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
+ [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 3, got 0<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
</tt><br>
-<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br>
- [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br>
+ [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
script-001 NativeScript<br>
-[40334] ./js1_3/Script/script-001.js line 133: ReferenceError: Can't find variable: Script<br>
</tt><br>
-<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
- [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
+ [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 3, got 0<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
</tt><br>
-<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br>
+<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br>
+ [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+Testcase produced no output!</tt><br>
+<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br>
[ <a href='#failure27'>Previous Failure</a> | <a href='#failure29'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br>
+<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br>
[ <a href='#failure28'>Previous Failure</a> | <a href='#failure30'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br>
+<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br>
[ <a href='#failure29'>Previous Failure</a> | <a href='#failure31'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br>
+<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br>
[ <a href='#failure30'>Previous Failure</a> | <a href='#failure32'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40379] ./js1_5/Exceptions/errstack-001.js line 247: TypeError: Undefined value<br>
+BUGNUMBER: 50447<br>
+STATUS: Test (non-ECMA) Error object properties fileName, lineNumber<br>
</tt><br>
-<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br>
+<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br>
[ <a href='#failure31'>Previous Failure</a> | <a href='#failure33'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-BUGNUMBER: 50447<br>
-STATUS: Test (non-ECMA) Error object properties fileName, lineNumber<br>
-[40380] ./js1_5/Exceptions/regress-50447.js line 65: TypeError: Undefined value<br>
-</tt><br>
-<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br>
+Testcase produced no output!</tt><br>
+<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br>
[ <a href='#failure32'>Previous Failure</a> | <a href='#failure34'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br>
+<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br>
[ <a href='#failure33'>Previous Failure</a> | <a href='#failure35'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br>
+<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br>
[ <a href='#failure34'>Previous Failure</a> | <a href='#failure36'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br>
+<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br>
[ <a href='#failure35'>Previous Failure</a> | <a href='#failure37'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40395] ./js1_5/Object/regress-90596-001.js line 48: TypeError: Value undefined (result of expression obj.toSource) is not object.<br>
-</tt><br>
-<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br>
+Testcase produced no output!</tt><br>
+<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br>
[ <a href='#failure36'>Previous Failure</a> | <a href='#failure38'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40396] ./js1_5/Object/regress-90596-002.js line 48: ReferenceError: Can't find variable: uneval<br>
-</tt><br>
-<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br>
+Testcase produced no output!</tt><br>
+<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br>
[ <a href='#failure37'>Previous Failure</a> | <a href='#failure39'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40398] ./js1_5/Object/regress-96284-001.js line 49: TypeError: Value undefined (result of expression obj1.toSource) is not object.<br>
-</tt><br>
-<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br>
+Testcase produced no output!</tt><br>
+<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br>
[ <a href='#failure38'>Previous Failure</a> | <a href='#failure40'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40399] ./js1_5/Object/regress-96284-002.js line 49: ReferenceError: Can't find variable: uneval<br>
-</tt><br>
-<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br>
- [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>Expected exit code 0, got 3<br>
-Testcase terminated with signal 0<br>
-Complete testcase output was:<br>
BUGNUMBER: 44009<br>
STATUS: Testing that we don't crash on obj.toSource()<br>
-[40404] ./js1_5/Regress/regress-44009.js line 60: TypeError: Value undefined (result of expression obj.toSource) is not object.<br>
</tt><br>
-<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-68498-003.js'>js1_5/Regress/regress-68498-003.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=68498' target='other_window'>Bug Number 68498</a><br>
- [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>STATUS: Testing calling obj.eval(str)<br>
-Failure messages were:<br>
-FAILED!: [reported from test()] Testing calling obj.eval(str); currently at expect[1] within test -<br>
-FAILED!: [reported from test()] Type mismatch, expected type number, actual type boolean<br>
-FAILED!: [reported from test()] Expected value '43', Actual value 'false'<br>
-FAILED!: [reported from test()] <br>
-</tt><br>
-<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br>
- [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br>
+ [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Reassignment to a const is NOT an error per ECMA<br>
Failure messages were:<br>
FAILED!: [reported from test()] Section 1 of test -<br>
FAILED!: [reported from test()] Expected value '1', Actual value '2'<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br>
- [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br>
+ [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br>
- [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br>
+ [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40431] ./js1_5/Regress/regress-127557.js line 75: ReferenceError: Can't find variable: clone<br>
-</tt><br>
-<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br>
- [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+Testcase produced no output!</tt><br>
+<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br>
+ [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40440] ./js1_5/Regress/regress-172699.js line 61: URIError: URI error<br>
-</tt><br>
-<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br>
- [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+Testcase produced no output!</tt><br>
+<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br>
+ [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Don't crash on extraneous arguments to str.match(), etc.<br>
Failure messages were:<br>
FAILED!: [reported from test()] Section 14 of test -<br>
FAILED!: [reported from test()] Expected value 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!', Actual value 'ABC Zbc'<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure47'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br>
- [ <a href='#failure46'>Previous Failure</a> | <a href='#failure48'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br>
+ [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
-[40465] ./js1_5/Scope/regress-220584.js line 56: ReferenceError: Can't find variable: Script<br>
-</tt><br>
-<a name='failure48'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br>
- [ <a href='#failure47'>Previous Failure</a> | <a href='#failure49'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+Testcase produced no output!</tt><br>
+<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br>
+ [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Testing scope after changing obj.__proto__<br>
Failure messages were:<br>
FAILED!: [reported from test()] Step 1: setting obj.__proto__ = global object<br>
FAILED!: [reported from test()] Expected value 'undefined', Actual value '1'<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure49'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br>
- [ <a href='#failure48'>Previous Failure</a> | <a href='#failure50'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure47'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br>
+ [ <a href='#failure46'>Previous Failure</a> | <a href='#failure48'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: E4X should be enabled even when e4x=1 not specified<br>
Failure messages were:<br>
FAILED!: E4X should be enabled even when e4x=1 not specified: XML()<br>
FAILED!: Expected value 'No error', Actual value 'error: ReferenceError: Can't find variable: XML'<br>
FAILED!: <br>
</tt><br>
-<a name='failure50'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br>
- [ <a href='#failure49'>Previous Failure</a> | <a href='#failure51'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure48'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br>
+ [ <a href='#failure47'>Previous Failure</a> | <a href='#failure49'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure51'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br>
- [ <a href='#failure50'>Previous Failure</a> | <a href='#failure52'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure49'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br>
+ [ <a href='#failure48'>Previous Failure</a> | <a href='#failure50'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
Testcase produced no output!</tt><br>
-<a name='failure52'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br>
- [ <a href='#failure51'>Previous Failure</a> | <a href='#failure53'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure50'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br>
+ [ <a href='#failure49'>Previous Failure</a> | <a href='#failure51'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>Expected exit code 0, got 3<br>
Testcase terminated with signal 0<br>
Complete testcase output was:<br>
BUGNUMBER: 306591<br>
STATUS: String static methods<br>
STATUS: See https://bugzilla.mozilla.org/show_bug.cgi?id=304828<br>
-[40487] ./js1_6/String/regress-306591.js line 48: TypeError: Value undefined (result of expression String.split) is not object.<br>
</tt><br>
</dl>
[ <a href='#tippy_top'>Top of Page</a> | <a href='#fail_detail'>Top of Failures</a> ]<br>
<pre>
<a name='retest_list'></a>
<h2>Retest List</h2><br>
-# Retest List, kjs, generated Sat Jan 5 15:45:34 2008.
+# Retest List, squirrelfish, generated Thu Sep 18 02:24:54 2008.
# Original test base was: All tests.
-# 1127 of 1135 test(s) were completed, 52 failures reported.
+# 1127 of 1135 test(s) were completed, 50 failures reported.
ecma/TypeConversion/9.3.1-3.js
ecma_2/Exceptions/function-001.js
ecma_3/Date/15.9.5.7.js
ecma_3/RegExp/regress-209919.js
ecma_3/Statements/regress-194364.js
ecma_3/Unicode/uc-001.js
-ecma_3/Unicode/uc-002.js
js1_2/Objects/toString-001.js
js1_2/function/Function_object.js
js1_2/function/function-001-n.js
js1_5/Object/regress-96284-001.js
js1_5/Object/regress-96284-002.js
js1_5/Regress/regress-44009.js
-js1_5/Regress/regress-68498-003.js
js1_5/Regress/regress-103602.js
js1_5/Regress/regress-104077.js
js1_5/Regress/regress-127557.js
js1_6/Regress/regress-301574.js
js1_6/Regress/regress-309242.js
js1_6/Regress/regress-314887.js
-js1_6/String/regress-306591.js
\ No newline at end of file
+js1_6/String/regress-306591.js
/* This test assumes that if version() exists, it can set the JavaScript
* interpreter to an arbitrary version. To prevent unhandled exceptions in
- * other tests, testkjs implements version() as a stub function, but
+ * other tests, jsc implements version() as a stub function, but
* JavaScriptCore doesn't support setting the JavaScript engine's version.
* Commenting out the following lines forces the test to expect JavaScript
/* This test assumes that if version() exists, it can set the JavaScript
* interpreter to an arbitrary version. To prevent unhandled exceptions in
- * other tests, testkjs implements version() as a stub function, but
+ * other tests, jsc implements version() as a stub function, but
* JavaScriptCore doesn't support setting the JavaScript engine's version.
* Commenting out the following lines forces the test to expect JavaScript
printBugNumber(bug);
printStatus(summary);
-// KJS doesn't run out of memory, so we don't expect an abnormal exit code
+// JSC doesn't run out of memory, so we don't expect an abnormal exit code
//expectExitCode(3);
var IN_RHINO = inRhino();
my $opt_console_failures = 0;
my $opt_lxr_url = "./"; # "http://lxr.mozilla.org/mozilla/source/js/tests/";
my $opt_exit_munge = ($os_type ne "MAC") ? 1 : 0;
+my $opt_arch= "";
# command line option definition
-my $options = "b=s bugurl>b c=s classpath>c e=s engine>e f=s file>f " .
+my $options = "a=s arch>a b=s bugurl>b c=s classpath>c e=s engine>e f=s file>f " .
"h help>h i j=s javapath>j k confail>k l=s list>l L=s neglist>L " .
"o=s opt>o p=s testpath>p s=s shellpath>s t trace>t u=s lxrurl>u " .
"x noexitmunge>x";
# (only check for their existance if the suite or test_dir has changed
# since the last time we looked.)
if ($last_suite ne $suite || $last_test_dir ne $test_dir) {
- $shell_command = &xp_path($engine_command);
+ $shell_command = $opt_arch . " ";
+
+ $shell_command .= &xp_path($engine_command) . " -s ";
$path = &xp_path($opt_suite_path . $suite . "/shell.js");
if (-f $path) {
}
$path = &xp_path($opt_suite_path . $test);
- &status ("executing: " . $shell_command . $file_param . $path);
+
+ print ($shell_command . $file_param . $path . "\n");
&dd ("executing: " . $shell_command . $file_param . $path);
open (OUTPUT, $shell_command . $file_param . $path .
while (($option, $value) = nextOption()) {
- if ($option eq "b") {
+ if ($option eq "a") {
+ &dd ("opt: running with architecture $value.");
+ $value =~ s/^ //;
+ $opt_arch = "arch -$value";
+
+ } elsif ($option eq "b") {
&dd ("opt: setting bugurl to '$value'.");
$opt_bug_url = $value;
sub usage {
print STDERR
("\nusage: $0 [<options>] \n" .
+ "(-a|--arch) <arch> run with a specific architecture on mac\n" .
"(-b|--bugurl) Bugzilla URL.\n" .
" (default is $opt_bug_url)\n" .
"(-c|--classpath) Classpath (Rhino only.)\n" .
"(-e|--engine) <type> ... Specify the type of engine(s) to test.\n" .
" <type> is one or more of\n" .
- " (kjs|smopt|smdebug|lcopt|lcdebug|xpcshell|" .
+ " (squirrelfish|smopt|smdebug|lcopt|lcdebug|xpcshell|" .
"rhino|rhinoi|rhinoms|rhinomsi|rhino9|rhinoms9).\n" .
"(-f|--file) <file> Redirect output to file named <file>.\n" .
" (default is " .
} elsif ($opt_engine_type =~ /^ep(opt|debug)$/) {
&dd ("getting epimetheus engine command.");
$retval = &get_ep_engine_command;
- } elsif ($opt_engine_type eq "kjs") {
- &dd ("getting kjs engine command.");
- $retval = &get_kjs_engine_command;
-
+ } elsif ($opt_engine_type eq "squirrelfish") {
+ &dd ("getting squirrelfish engine command.");
+ $retval = &get_squirrelfish_engine_command;
} else {
die ("Unknown engine type selected, '$opt_engine_type'.\n");
}
}
#
-# get the shell command used to run kjs
+# get the shell command used to run squirrelfish
#
-sub get_kjs_engine_command {
+sub get_squirrelfish_engine_command {
my $retval;
if ($opt_shell_path) {
- $retval = $opt_shell_path;
+ # FIXME: Quoting the path this way won't work with paths with quotes in
+ # them. A better fix would be to use the multi-parameter version of
+ # open(), but that doesn't work on ActiveState Perl.
+ $retval = "\"" . $opt_shell_path . "\"";
} else {
- die "Please specify a full path to the kjs testing engine";
+ die "Please specify a full path to the squirrelfish testing engine";
}
return $retval;
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CharacterClass.h"
+
+#if ENABLE(WREC)
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+const CharacterClass& CharacterClass::newline() {
+ static const UChar asciiNewlines[2] = { '\n', '\r' };
+ static const UChar unicodeNewlines[2] = { 0x2028, 0x2029 };
+ static const CharacterClass charClass = {
+ asciiNewlines, 2,
+ 0, 0,
+ unicodeNewlines, 2,
+ 0, 0,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::digits() {
+ static const CharacterRange asciiDigitsRange[1] = { { '0', '9' } };
+ static const CharacterClass charClass = {
+ 0, 0,
+ asciiDigitsRange, 1,
+ 0, 0,
+ 0, 0,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::spaces() {
+ static const UChar asciiSpaces[1] = { ' ' };
+ static const CharacterRange asciiSpacesRange[1] = { { '\t', '\r' } };
+ static const UChar unicodeSpaces[8] = { 0x00a0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000 };
+ static const CharacterRange unicodeSpacesRange[1] = { { 0x2000, 0x200a } };
+ static const CharacterClass charClass = {
+ asciiSpaces, 1,
+ asciiSpacesRange, 1,
+ unicodeSpaces, 8,
+ unicodeSpacesRange, 1,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::wordchar() {
+ static const UChar asciiWordchar[1] = { '_' };
+ static const CharacterRange asciiWordcharRange[3] = { { '0', '9' }, { 'A', 'Z' }, { 'a', 'z' } };
+ static const CharacterClass charClass = {
+ asciiWordchar, 1,
+ asciiWordcharRange, 3,
+ 0, 0,
+ 0, 0,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::nondigits() {
+ static const CharacterRange asciiNondigitsRange[2] = { { 0, '0' - 1 }, { '9' + 1, 0x7f } };
+ static const CharacterRange unicodeNondigitsRange[1] = { { 0x0080, 0xffff } };
+ static const CharacterClass charClass = {
+ 0, 0,
+ asciiNondigitsRange, 2,
+ 0, 0,
+ unicodeNondigitsRange, 1,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::nonspaces() {
+ static const CharacterRange asciiNonspacesRange[3] = { { 0, '\t' - 1 }, { '\r' + 1, ' ' - 1 }, { ' ' + 1, 0x7f } };
+ static const CharacterRange unicodeNonspacesRange[9] = {
+ { 0x0080, 0x009f },
+ { 0x00a1, 0x167f },
+ { 0x1681, 0x180d },
+ { 0x180f, 0x1fff },
+ { 0x200b, 0x2027 },
+ { 0x202a, 0x202e },
+ { 0x2030, 0x205e },
+ { 0x2060, 0x2fff },
+ { 0x3001, 0xffff }
+ };
+ static const CharacterClass charClass = {
+ 0, 0,
+ asciiNonspacesRange, 3,
+ 0, 0,
+ unicodeNonspacesRange, 9,
+ };
+
+ return charClass;
+}
+
+const CharacterClass& CharacterClass::nonwordchar() {
+ static const UChar asciiNonwordchar[1] = { '`' };
+ static const CharacterRange asciiNonwordcharRange[4] = { { 0, '0' - 1 }, { '9' + 1, 'A' - 1 }, { 'Z' + 1, '_' - 1 }, { 'z' + 1, 0x7f } };
+ static const CharacterRange unicodeNonwordcharRange[1] = { { 0x0080, 0xffff } };
+ static const CharacterClass charClass = {
+ asciiNonwordchar, 1,
+ asciiNonwordcharRange, 4,
+ 0, 0,
+ unicodeNonwordcharRange, 1,
+ };
+
+ return charClass;
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CharacterClass_h
+#define CharacterClass_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace WREC {
+
+ struct CharacterRange {
+ UChar begin;
+ UChar end;
+ };
+
+ struct CharacterClass {
+ static const CharacterClass& newline();
+ static const CharacterClass& digits();
+ static const CharacterClass& spaces();
+ static const CharacterClass& wordchar();
+ static const CharacterClass& nondigits();
+ static const CharacterClass& nonspaces();
+ static const CharacterClass& nonwordchar();
+
+ const UChar* matches;
+ unsigned numMatches;
+
+ const CharacterRange* ranges;
+ unsigned numRanges;
+
+ const UChar* matchesUnicode;
+ unsigned numMatchesUnicode;
+
+ const CharacterRange* rangesUnicode;
+ unsigned numRangesUnicode;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // CharacterClass_h
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CharacterClassConstructor.h"
+
+#if ENABLE(WREC)
+
+#include "pcre_internal.h"
+#include <wtf/ASCIICType.h>
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+void CharacterClassConstructor::addSorted(Vector<UChar>& matches, UChar ch)
+{
+ unsigned pos = 0;
+ unsigned range = matches.size();
+
+ // binary chop, find position to insert char.
+ while (range) {
+ unsigned index = range >> 1;
+
+ int val = matches[pos+index] - ch;
+ if (!val)
+ return;
+ else if (val > 0)
+ range = index;
+ else {
+ pos += (index+1);
+ range -= (index+1);
+ }
+ }
+
+ if (pos == matches.size())
+ matches.append(ch);
+ else
+ matches.insert(pos, ch);
+}
+
+void CharacterClassConstructor::addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi)
+{
+ unsigned end = ranges.size();
+
+ // Simple linear scan - I doubt there are that many ranges anyway...
+ // feel free to fix this with something faster (eg binary chop).
+ for (unsigned i = 0; i < end; ++i) {
+ // does the new range fall before the current position in the array
+ if (hi < ranges[i].begin) {
+ // optional optimization: concatenate appending ranges? - may not be worthwhile.
+ if (hi == (ranges[i].begin - 1)) {
+ ranges[i].begin = lo;
+ return;
+ }
+ CharacterRange r = {lo, hi};
+ ranges.insert(i, r);
+ return;
+ }
+ // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining
+ // If the new range start at or before the end of the last range, then the overlap (if it starts one after the
+ // end of the last range they concatenate, which is just as good.
+ if (lo <= (ranges[i].end + 1)) {
+ // found an intersect! we'll replace this entry in the array.
+ ranges[i].begin = std::min(ranges[i].begin, lo);
+ ranges[i].end = std::max(ranges[i].end, hi);
+
+ // now check if the new range can subsume any subsequent ranges.
+ unsigned next = i+1;
+ // each iteration of the loop we will either remove something from the list, or break the loop.
+ while (next < ranges.size()) {
+ if (ranges[next].begin <= (ranges[i].end + 1)) {
+ // the next entry now overlaps / concatenates this one.
+ ranges[i].end = std::max(ranges[i].end, ranges[next].end);
+ ranges.remove(next);
+ } else
+ break;
+ }
+
+ return;
+ }
+ }
+
+ // CharacterRange comes after all existing ranges.
+ CharacterRange r = {lo, hi};
+ ranges.append(r);
+}
+
+void CharacterClassConstructor::put(UChar ch)
+{
+ // Parsing a regular expression like [a-z], we start in an initial empty state:
+ // ((m_charBuffer == -1) && !m_isPendingDash)
+ // When buffer the 'a' sice it may be (and is in this case) part of a range:
+ // ((m_charBuffer != -1) && !m_isPendingDash)
+ // Having parsed the hyphen we then record that the dash is also pending:
+ // ((m_charBuffer != -1) && m_isPendingDash)
+ // The next change will always take us back to the initial state - either because
+ // a complete range has been parsed (such as [a-z]), or because a flush is forced,
+ // due to an early end in the regexp ([a-]), or a character class escape being added
+ // ([a-\s]). The fourth permutation of m_charBuffer and m_isPendingDash is not permitted.
+ ASSERT(!((m_charBuffer == -1) && m_isPendingDash));
+
+ if (m_charBuffer != -1) {
+ if (m_isPendingDash) {
+ // EXAMPLE: parsing [-a-c], the 'c' reaches this case - we have buffered a previous character and seen a hyphen, so this is a range.
+ UChar lo = m_charBuffer;
+ UChar hi = ch;
+ // Reset back to the inital state.
+ m_charBuffer = -1;
+ m_isPendingDash = false;
+
+ // This is an error, detected lazily. Do not proceed.
+ if (lo > hi) {
+ m_isUpsideDown = true;
+ return;
+ }
+
+ if (lo <= 0x7f) {
+ char asciiLo = lo;
+ char asciiHi = std::min(hi, (UChar)0x7f);
+ addSortedRange(m_ranges, lo, asciiHi);
+
+ if (m_isCaseInsensitive) {
+ if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
+ addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A'));
+ if ((asciiLo <= 'z') && (asciiHi >= 'a'))
+ addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a'));
+ }
+ }
+ if (hi >= 0x80) {
+ UChar unicodeCurr = std::max(lo, (UChar)0x80);
+ addSortedRange(m_rangesUnicode, unicodeCurr, hi);
+
+ if (m_isCaseInsensitive) {
+ // we're going to scan along, updating the start of the range
+ while (unicodeCurr <= hi) {
+ // Spin forwards over any characters that don't have two cases.
+ for (; jsc_pcre_ucp_othercase(unicodeCurr) == -1; ++unicodeCurr) {
+ // if this was the last character in the range, we're done.
+ if (unicodeCurr == hi)
+ return;
+ }
+ // if we fall through to here, unicodeCurr <= hi & has another case. Get the other case.
+ UChar rangeStart = unicodeCurr;
+ UChar otherCurr = jsc_pcre_ucp_othercase(unicodeCurr);
+
+ // If unicodeCurr is not yet hi, check the next char in the range. If it also has another case,
+ // and if it's other case value is one greater then the othercase value for the current last
+ // character included in the range, we can include next into the range.
+ while ((unicodeCurr < hi) && (jsc_pcre_ucp_othercase(unicodeCurr + 1) == (otherCurr + 1))) {
+ // increment unicodeCurr; it points to the end of the range.
+ // increment otherCurr, due to the check above other for next must be 1 greater than the currrent other value.
+ ++unicodeCurr;
+ ++otherCurr;
+ }
+
+ // otherChar is the last in the range of other case chars, calculate offset to get back to the start.
+ addSortedRange(m_rangesUnicode, otherCurr-(unicodeCurr-rangeStart), otherCurr);
+
+ // unicodeCurr has been added, move on to the next char.
+ ++unicodeCurr;
+ }
+ }
+ }
+ } else if (ch == '-')
+ // EXAMPLE: parsing [-a-c], the second '-' reaches this case - the hyphen is treated as potentially indicating a range.
+ m_isPendingDash = true;
+ else {
+ // EXAMPLE: Parsing [-a-c], the 'a' reaches this case - we repace the previously buffered char with the 'a'.
+ flush();
+ m_charBuffer = ch;
+ }
+ } else
+ // EXAMPLE: Parsing [-a-c], the first hyphen reaches this case - there is no buffered character
+ // (the hyphen not treated as a special character in this case, same handling for any char).
+ m_charBuffer = ch;
+}
+
+// When a character is added to the set we do not immediately add it to the arrays, in case it is actually defining a range.
+// When we have determined the character is not used in specifing a range it is added, in a sorted fashion, to the appropriate
+// array (either ascii or unicode).
+// If the pattern is case insensitive we add entries for both cases.
+void CharacterClassConstructor::flush()
+{
+ if (m_charBuffer != -1) {
+ if (m_charBuffer <= 0x7f) {
+ if (m_isCaseInsensitive && isASCIILower(m_charBuffer))
+ addSorted(m_matches, toASCIIUpper(m_charBuffer));
+ addSorted(m_matches, m_charBuffer);
+ if (m_isCaseInsensitive && isASCIIUpper(m_charBuffer))
+ addSorted(m_matches, toASCIILower(m_charBuffer));
+ } else {
+ addSorted(m_matchesUnicode, m_charBuffer);
+ if (m_isCaseInsensitive) {
+ int other = jsc_pcre_ucp_othercase(m_charBuffer);
+ if (other != -1)
+ addSorted(m_matchesUnicode, other);
+ }
+ }
+ m_charBuffer = -1;
+ }
+
+ if (m_isPendingDash) {
+ addSorted(m_matches, '-');
+ m_isPendingDash = false;
+ }
+}
+
+void CharacterClassConstructor::append(const CharacterClass& other)
+{
+ // [x-\s] will add, 'x', '-', and all unicode spaces to new class (same as [x\s-]).
+ // Need to check the spec, really, but think this matches PCRE behaviour.
+ flush();
+
+ if (other.numMatches) {
+ for (size_t i = 0; i < other.numMatches; ++i)
+ addSorted(m_matches, other.matches[i]);
+ }
+ if (other.numRanges) {
+ for (size_t i = 0; i < other.numRanges; ++i)
+ addSortedRange(m_ranges, other.ranges[i].begin, other.ranges[i].end);
+ }
+ if (other.numMatchesUnicode) {
+ for (size_t i = 0; i < other.numMatchesUnicode; ++i)
+ addSorted(m_matchesUnicode, other.matchesUnicode[i]);
+ }
+ if (other.numRangesUnicode) {
+ for (size_t i = 0; i < other.numRangesUnicode; ++i)
+ addSortedRange(m_rangesUnicode, other.rangesUnicode[i].begin, other.rangesUnicode[i].end);
+ }
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CharacterClassConstructor_h
+#define CharacterClassConstructor_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include "CharacterClass.h"
+#include <wtf/AlwaysInline.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace WREC {
+
+ class CharacterClassConstructor {
+ public:
+ CharacterClassConstructor(bool isCaseInsensitive)
+ : m_charBuffer(-1)
+ , m_isPendingDash(false)
+ , m_isCaseInsensitive(isCaseInsensitive)
+ , m_isUpsideDown(false)
+ {
+ }
+
+ void flush();
+
+ // We need to flush prior to an escaped hyphen to prevent it as being treated as indicating
+ // a range, e.g. [a\-c] we flush prior to adding the hyphen so that this is not treated as
+ // [a-c]. However, we do not want to flush if we have already seen a non escaped hyphen -
+ // e.g. [+-\-] should be treated the same as [+--], producing a range that will also match
+ // a comma.
+ void flushBeforeEscapedHyphen()
+ {
+ if (!m_isPendingDash)
+ flush();
+ }
+
+ void put(UChar ch);
+ void append(const CharacterClass& other);
+
+ bool isUpsideDown() { return m_isUpsideDown; }
+
+ ALWAYS_INLINE CharacterClass charClass()
+ {
+ CharacterClass newCharClass = {
+ m_matches.begin(), m_matches.size(),
+ m_ranges.begin(), m_ranges.size(),
+ m_matchesUnicode.begin(), m_matchesUnicode.size(),
+ m_rangesUnicode.begin(), m_rangesUnicode.size(),
+ };
+
+ return newCharClass;
+ }
+
+ private:
+ void addSorted(Vector<UChar>& matches, UChar ch);
+ void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi);
+
+ int m_charBuffer;
+ bool m_isPendingDash;
+ bool m_isCaseInsensitive;
+ bool m_isUpsideDown;
+
+ Vector<UChar> m_matches;
+ Vector<CharacterRange> m_ranges;
+ Vector<UChar> m_matchesUnicode;
+ Vector<CharacterRange> m_rangesUnicode;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // CharacterClassConstructor_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Escapes_h
+#define Escapes_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include <wtf/Assertions.h>
+
+namespace JSC { namespace WREC {
+
+ class CharacterClass;
+
+ class Escape {
+ public:
+ enum Type {
+ PatternCharacter,
+ CharacterClass,
+ Backreference,
+ WordBoundaryAssertion,
+ Error,
+ };
+
+ Escape(Type type)
+ : m_type(type)
+ {
+ }
+
+ Type type() const { return m_type; }
+
+ private:
+ Type m_type;
+
+ protected:
+ // Used by subclasses to store data.
+ union {
+ int i;
+ const WREC::CharacterClass* c;
+ } m_u;
+ bool m_invert;
+ };
+
+ class PatternCharacterEscape : public Escape {
+ public:
+ static const PatternCharacterEscape& cast(const Escape& escape)
+ {
+ ASSERT(escape.type() == PatternCharacter);
+ return static_cast<const PatternCharacterEscape&>(escape);
+ }
+
+ PatternCharacterEscape(int character)
+ : Escape(PatternCharacter)
+ {
+ m_u.i = character;
+ }
+
+ operator Escape() const { return *this; }
+
+ int character() const { return m_u.i; }
+ };
+
+ class CharacterClassEscape : public Escape {
+ public:
+ static const CharacterClassEscape& cast(const Escape& escape)
+ {
+ ASSERT(escape.type() == CharacterClass);
+ return static_cast<const CharacterClassEscape&>(escape);
+ }
+
+ CharacterClassEscape(const WREC::CharacterClass& characterClass, bool invert)
+ : Escape(CharacterClass)
+ {
+ m_u.c = &characterClass;
+ m_invert = invert;
+ }
+
+ operator Escape() { return *this; }
+
+ const WREC::CharacterClass& characterClass() const { return *m_u.c; }
+ bool invert() const { return m_invert; }
+ };
+
+ class BackreferenceEscape : public Escape {
+ public:
+ static const BackreferenceEscape& cast(const Escape& escape)
+ {
+ ASSERT(escape.type() == Backreference);
+ return static_cast<const BackreferenceEscape&>(escape);
+ }
+
+ BackreferenceEscape(int subpatternId)
+ : Escape(Backreference)
+ {
+ m_u.i = subpatternId;
+ }
+
+ operator Escape() const { return *this; }
+
+ int subpatternId() const { return m_u.i; }
+ };
+
+ class WordBoundaryAssertionEscape : public Escape {
+ public:
+ static const WordBoundaryAssertionEscape& cast(const Escape& escape)
+ {
+ ASSERT(escape.type() == WordBoundaryAssertion);
+ return static_cast<const WordBoundaryAssertionEscape&>(escape);
+ }
+
+ WordBoundaryAssertionEscape(bool invert)
+ : Escape(WordBoundaryAssertion)
+ {
+ m_invert = invert;
+ }
+
+ operator Escape() const { return *this; }
+
+ bool invert() const { return m_invert; }
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // Escapes_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Quantifier_h
+#define Quantifier_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include <wtf/Assertions.h>
+#include <limits.h>
+
+namespace JSC { namespace WREC {
+
+ struct Quantifier {
+ enum Type {
+ None,
+ Greedy,
+ NonGreedy,
+ Error,
+ };
+
+ Quantifier(Type type = None, unsigned min = 0, unsigned max = Infinity)
+ : type(type)
+ , min(min)
+ , max(max)
+ {
+ ASSERT(min <= max);
+ }
+
+ Type type;
+
+ unsigned min;
+ unsigned max;
+
+ static const unsigned Infinity = UINT_MAX;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // Quantifier_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WREC.h"
+
+#if ENABLE(WREC)
+
+#include "CharacterClassConstructor.h"
+#include "Interpreter.h"
+#include "JSGlobalObject.h"
+#include "RegisterFile.h"
+#include "WRECFunctors.h"
+#include "WRECParser.h"
+#include "pcre_internal.h"
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+CompiledRegExp Generator::compileRegExp(JSGlobalData* globalData, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase, bool multiline)
+{
+ if (pattern.size() > MAX_PATTERN_SIZE) {
+ *error_ptr = "regular expression too large";
+ return 0;
+ }
+
+ Parser parser(pattern, ignoreCase, multiline);
+ Generator& generator = parser.generator();
+ MacroAssembler::JumpList failures;
+ MacroAssembler::Jump endOfInput;
+
+ generator.generateEnter();
+ generator.generateSaveIndex();
+
+ Label beginPattern(&generator);
+ parser.parsePattern(failures);
+ generator.generateReturnSuccess();
+
+ failures.link(&generator);
+ generator.generateIncrementIndex(&endOfInput);
+ parser.parsePattern(failures);
+ generator.generateReturnSuccess();
+
+ failures.link(&generator);
+ generator.generateIncrementIndex();
+ generator.generateJumpIfNotEndOfInput(beginPattern);
+
+ endOfInput.link(&generator);
+ generator.generateReturnFailure();
+
+ if (parser.error()) {
+ *error_ptr = parser.syntaxError(); // NULL in the case of patterns that WREC doesn't support yet.
+ return 0;
+ }
+
+ *numSubpatterns_ptr = parser.numSubpatterns();
+ pool = globalData->poolForSize(generator.size());
+ return reinterpret_cast<CompiledRegExp>(generator.copyCode(pool.get()));
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WREC_h
+#define WREC_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include <wtf/unicode/Unicode.h>
+
+#if COMPILER(GCC) && PLATFORM(X86)
+#define WREC_CALL __attribute__ ((regparm (3)))
+#else
+#define WREC_CALL
+#endif
+
+namespace JSC {
+ class Interpreter;
+ class UString;
+}
+
+namespace JSC { namespace WREC {
+
+ typedef int (*CompiledRegExp)(const UChar* input, unsigned start, unsigned length, int* output) WREC_CALL;
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // WREC_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WRECFunctors.h"
+
+#if ENABLE(WREC)
+
+#include "WRECGenerator.h"
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+void GeneratePatternCharacterFunctor::generateAtom(Generator* generator, Generator::JumpList& failures)
+{
+ generator->generatePatternCharacter(failures, m_ch);
+}
+
+void GeneratePatternCharacterFunctor::backtrack(Generator* generator)
+{
+ generator->generateBacktrack1();
+}
+
+void GenerateCharacterClassFunctor::generateAtom(Generator* generator, Generator::JumpList& failures)
+{
+ generator->generateCharacterClass(failures, *m_charClass, m_invert);
+}
+
+void GenerateCharacterClassFunctor::backtrack(Generator* generator)
+{
+ generator->generateBacktrack1();
+}
+
+void GenerateBackreferenceFunctor::generateAtom(Generator* generator, Generator::JumpList& failures)
+{
+ generator->generateBackreference(failures, m_subpatternId);
+}
+
+void GenerateBackreferenceFunctor::backtrack(Generator* generator)
+{
+ generator->generateBacktrackBackreference(m_subpatternId);
+}
+
+void GenerateParenthesesNonGreedyFunctor::generateAtom(Generator* generator, Generator::JumpList& failures)
+{
+ generator->generateParenthesesNonGreedy(failures, m_start, m_success, m_fail);
+}
+
+void GenerateParenthesesNonGreedyFunctor::backtrack(Generator*)
+{
+ // FIXME: do something about this.
+ CRASH();
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include "WRECGenerator.h"
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace WREC {
+
+ struct CharacterClass;
+
+ class GenerateAtomFunctor {
+ public:
+ virtual ~GenerateAtomFunctor() {}
+
+ virtual void generateAtom(Generator*, Generator::JumpList&) = 0;
+ virtual void backtrack(Generator*) = 0;
+ };
+
+ class GeneratePatternCharacterFunctor : public GenerateAtomFunctor {
+ public:
+ GeneratePatternCharacterFunctor(const UChar ch)
+ : m_ch(ch)
+ {
+ }
+
+ virtual void generateAtom(Generator*, Generator::JumpList&);
+ virtual void backtrack(Generator*);
+
+ private:
+ const UChar m_ch;
+ };
+
+ class GenerateCharacterClassFunctor : public GenerateAtomFunctor {
+ public:
+ GenerateCharacterClassFunctor(const CharacterClass* charClass, bool invert)
+ : m_charClass(charClass)
+ , m_invert(invert)
+ {
+ }
+
+ virtual void generateAtom(Generator*, Generator::JumpList&);
+ virtual void backtrack(Generator*);
+
+ private:
+ const CharacterClass* m_charClass;
+ bool m_invert;
+ };
+
+ class GenerateBackreferenceFunctor : public GenerateAtomFunctor {
+ public:
+ GenerateBackreferenceFunctor(unsigned subpatternId)
+ : m_subpatternId(subpatternId)
+ {
+ }
+
+ virtual void generateAtom(Generator*, Generator::JumpList&);
+ virtual void backtrack(Generator*);
+
+ private:
+ unsigned m_subpatternId;
+ };
+
+ class GenerateParenthesesNonGreedyFunctor : public GenerateAtomFunctor {
+ public:
+ GenerateParenthesesNonGreedyFunctor(Generator::Label start, Generator::Jump success, Generator::Jump fail)
+ : m_start(start)
+ , m_success(success)
+ , m_fail(fail)
+ {
+ }
+
+ virtual void generateAtom(Generator*, Generator::JumpList&);
+ virtual void backtrack(Generator*);
+
+ private:
+ Generator::Label m_start;
+ Generator::Jump m_success;
+ Generator::Jump m_fail;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WREC.h"
+
+#if ENABLE(WREC)
+
+#include "CharacterClassConstructor.h"
+#include "Interpreter.h"
+#include "WRECFunctors.h"
+#include "WRECParser.h"
+#include "pcre_internal.h"
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+void Generator::generateEnter()
+{
+#if PLATFORM(X86_64)
+ // On x86-64 edi and esi are caller preserved, so nothing to do here.
+ // The four arguments have been passed in the registers %rdi, %rsi,
+ // %rdx, %rcx - shuffle these into the expected locations.
+ move(X86::edi, input); // (arg 1) edi -> eax
+ move(X86::ecx, output); // (arg 4) ecx -> edi
+ move(X86::edx, length); // (arg 3) edx -> ecx
+ move(X86::esi, index); // (arg 2) esi -> edx
+
+#else
+ // On x86 edi & esi are callee preserved registers.
+ push(X86::edi);
+ push(X86::esi);
+
+#if COMPILER(MSVC)
+ // Move the arguments into registers.
+ peek(input, 3);
+ peek(index, 4);
+ peek(length, 5);
+ peek(output, 6);
+#else
+ // On gcc the function is regparm(3), so the input, index, and length registers
+ // (eax, edx, and ecx respectively) already contain the appropriate values.
+ // Just load the fourth argument (output) into edi
+ peek(output, 3);
+#endif
+#endif
+
+#ifndef NDEBUG
+ // ASSERT that the output register is not null.
+ Jump outputNotNull = jnzPtr(output);
+ breakpoint();
+ outputNotNull.link(this);
+#endif
+}
+
+void Generator::generateReturnSuccess()
+{
+ // Set return value.
+ pop(X86::eax); // match begin
+ store32(X86::eax, output);
+ store32(index, Address(output, 4)); // match end
+
+ // Restore callee save registers.
+#if !PLATFORM(X86_64)
+ pop(X86::esi);
+ pop(X86::edi);
+#endif
+ ret();
+}
+
+void Generator::generateSaveIndex()
+{
+ push(index);
+}
+
+void Generator::generateIncrementIndex(Jump* failure)
+{
+ peek(index);
+ if (failure)
+ *failure = je32(length, index);
+ add32(Imm32(1), index);
+ poke(index);
+}
+
+void Generator::generateLoadCharacter(JumpList& failures)
+{
+ failures.append(je32(length, index));
+ load16(BaseIndex(input, index, TimesTwo), character);
+}
+
+// For the sake of end-of-line assertions, we treat one-past-the-end as if it
+// were part of the input string.
+void Generator::generateJumpIfNotEndOfInput(Label target)
+{
+ jle32(index, length, target);
+}
+
+void Generator::generateReturnFailure()
+{
+ pop();
+ move(Imm32(-1), X86::eax);
+#if !PLATFORM(X86_64)
+ pop(X86::esi);
+ pop(X86::edi);
+#endif
+ ret();
+}
+
+void Generator::generateBacktrack1()
+{
+ sub32(Imm32(1), index);
+}
+
+void Generator::generateBacktrackBackreference(unsigned subpatternId)
+{
+ sub32(Address(output, (2 * subpatternId + 1) * sizeof(int)), index);
+ add32(Address(output, (2 * subpatternId) * sizeof(int)), index);
+}
+
+void Generator::generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max)
+{
+ GenerateBackreferenceFunctor functor(subpatternId);
+
+ load32(Address(output, (2 * subpatternId) * sizeof(int)), character);
+ Jump skipIfEmpty = je32(Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character);
+
+ ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy);
+ if (quantifierType == Quantifier::Greedy)
+ generateGreedyQuantifier(failures, functor, min, max);
+ else
+ generateNonGreedyQuantifier(failures, functor, min, max);
+
+ skipIfEmpty.link(this);
+}
+
+void Generator::generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max)
+{
+ JumpList atomFailedList;
+ JumpList alternativeFailedList;
+
+ // (0) Setup: Save, then init repeatCount.
+ push(repeatCount);
+ move(Imm32(0), repeatCount);
+ Jump start = jump();
+
+ // (4) Quantifier failed: No more atom reading possible.
+ Label quantifierFailed(this);
+ pop(repeatCount);
+ failures.append(jump());
+
+ // (3) Alternative failed: If we can, read another atom, then fall through to (2) to try again.
+ Label alternativeFailed(this);
+ pop(index);
+ if (max != Quantifier::Infinity)
+ je32(repeatCount, Imm32(max), quantifierFailed);
+
+ // (1) Read an atom.
+ if (min)
+ start.link(this);
+ Label readAtom(this);
+ functor.generateAtom(this, atomFailedList);
+ atomFailedList.linkTo(quantifierFailed, this);
+ add32(Imm32(1), repeatCount);
+
+ // (2) Keep reading if we're under the minimum.
+ if (min > 1)
+ jl32(repeatCount, Imm32(min), readAtom);
+
+ // (3) Test the rest of the alternative.
+ if (!min)
+ start.link(this);
+ push(index);
+ m_parser.parseAlternative(alternativeFailedList);
+ alternativeFailedList.linkTo(alternativeFailed, this);
+
+ pop();
+ pop(repeatCount);
+}
+
+void Generator::generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max)
+{
+ if (!max)
+ return;
+
+ JumpList doneReadingAtomsList;
+ JumpList alternativeFailedList;
+
+ // (0) Setup: Save, then init repeatCount.
+ push(repeatCount);
+ move(Imm32(0), repeatCount);
+
+ // (1) Greedily read as many copies of the atom as possible, then jump to (2).
+ Label readAtom(this);
+ functor.generateAtom(this, doneReadingAtomsList);
+ add32(Imm32(1), repeatCount);
+ if (max == Quantifier::Infinity)
+ jump(readAtom);
+ else if (max == 1)
+ doneReadingAtomsList.append(jump());
+ else {
+ jne32(repeatCount, Imm32(max), readAtom);
+ doneReadingAtomsList.append(jump());
+ }
+
+ // (5) Quantifier failed: No more backtracking possible.
+ Label quantifierFailed(this);
+ pop(repeatCount);
+ failures.append(jump());
+
+ // (4) Alternative failed: Backtrack, then fall through to (2) to try again.
+ Label alternativeFailed(this);
+ pop(index);
+ functor.backtrack(this);
+ sub32(Imm32(1), repeatCount);
+
+ // (2) Verify that we have enough atoms.
+ doneReadingAtomsList.link(this);
+ jl32(repeatCount, Imm32(min), quantifierFailed);
+
+ // (3) Test the rest of the alternative.
+ push(index);
+ m_parser.parseAlternative(alternativeFailedList);
+ alternativeFailedList.linkTo(alternativeFailed, this);
+
+ pop();
+ pop(repeatCount);
+}
+
+void Generator::generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count)
+{
+ for (size_t i = 0; i < count;) {
+ if (i < count - 1) {
+ if (generatePatternCharacterPair(failures, sequence[i], sequence[i + 1])) {
+ i += 2;
+ continue;
+ }
+ }
+
+ generatePatternCharacter(failures, sequence[i]);
+ ++i;
+ }
+}
+
+bool Generator::generatePatternCharacterPair(JumpList& failures, int ch1, int ch2)
+{
+ if (m_parser.ignoreCase()) {
+ // Non-trivial case folding requires more than one test, so we can't
+ // test as a pair with an adjacent character.
+ if (!isASCII(ch1) && Unicode::toLower(ch1) != Unicode::toUpper(ch1))
+ return false;
+ if (!isASCII(ch2) && Unicode::toLower(ch2) != Unicode::toUpper(ch2))
+ return false;
+ }
+
+ // Optimistically consume 2 characters.
+ add32(Imm32(2), index);
+ failures.append(jg32(index, length));
+
+ // Load the characters we just consumed, offset -2 characters from index.
+ load32(BaseIndex(input, index, TimesTwo, -2 * 2), character);
+
+ if (m_parser.ignoreCase()) {
+ // Convert ASCII alphabet characters to upper case before testing for
+ // equality. (ASCII non-alphabet characters don't require upper-casing
+ // because they have no uppercase equivalents. Unicode characters don't
+ // require upper-casing because we only handle Unicode characters whose
+ // upper and lower cases are equal.)
+ int ch1Mask = 0;
+ if (isASCIIAlpha(ch1)) {
+ ch1 |= 32;
+ ch1Mask = 32;
+ }
+
+ int ch2Mask = 0;
+ if (isASCIIAlpha(ch2)) {
+ ch2 |= 32;
+ ch2Mask = 32;
+ }
+
+ int mask = ch1Mask | (ch2Mask << 16);
+ if (mask)
+ or32(Imm32(mask), character);
+ }
+ int pair = ch1 | (ch2 << 16);
+
+ failures.append(jne32(character, Imm32(pair)));
+ return true;
+}
+
+void Generator::generatePatternCharacter(JumpList& failures, int ch)
+{
+ generateLoadCharacter(failures);
+
+ // used for unicode case insensitive
+ bool hasUpper = false;
+ Jump isUpper;
+
+ // if case insensitive match
+ if (m_parser.ignoreCase()) {
+ UChar lower, upper;
+
+ // check for ascii case sensitive characters
+ if (isASCIIAlpha(ch)) {
+ or32(Imm32(32), character);
+ ch |= 32;
+ } else if (!isASCII(ch) && ((lower = Unicode::toLower(ch)) != (upper = Unicode::toUpper(ch)))) {
+ // handle unicode case sentitive characters - branch to success on upper
+ isUpper = je32(character, Imm32(upper));
+ hasUpper = true;
+ ch = lower;
+ }
+ }
+
+ // checks for ch, or lower case version of ch, if insensitive
+ failures.append(jne32(character, Imm32((unsigned short)ch)));
+
+ if (m_parser.ignoreCase() && hasUpper) {
+ // for unicode case insensitive matches, branch here if upper matches.
+ isUpper.link(this);
+ }
+
+ // on success consume the char
+ add32(Imm32(1), index);
+}
+
+void Generator::generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount)
+{
+ do {
+ // pick which range we're going to generate
+ int which = count >> 1;
+ char lo = ranges[which].begin;
+ char hi = ranges[which].end;
+
+ // check if there are any ranges or matches below lo. If not, just jl to failure -
+ // if there is anything else to check, check that first, if it falls through jmp to failure.
+ if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
+ Jump loOrAbove = jge32(character, Imm32((unsigned short)lo));
+
+ // generate code for all ranges before this one
+ if (which)
+ generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+
+ while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
+ matchDest.append(je32(character, Imm32((unsigned short)matches[*matchIndex])));
+ ++*matchIndex;
+ }
+ failures.append(jump());
+
+ loOrAbove.link(this);
+ } else if (which) {
+ Jump loOrAbove = jge32(character, Imm32((unsigned short)lo));
+
+ generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+ failures.append(jump());
+
+ loOrAbove.link(this);
+ } else
+ failures.append(jl32(character, Imm32((unsigned short)lo)));
+
+ while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
+ ++*matchIndex;
+
+ matchDest.append(jle32(character, Imm32((unsigned short)hi)));
+ // fall through to here, the value is above hi.
+
+ // shuffle along & loop around if there are any more matches to handle.
+ unsigned next = which + 1;
+ ranges += next;
+ count -= next;
+ } while (count);
+}
+
+void Generator::generateCharacterClassInverted(JumpList& matchDest, const CharacterClass& charClass)
+{
+ Jump unicodeFail;
+ if (charClass.numMatchesUnicode || charClass.numRangesUnicode) {
+ Jump isAscii = jle32(character, Imm32(0x7f));
+
+ if (charClass.numMatchesUnicode) {
+ for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) {
+ UChar ch = charClass.matchesUnicode[i];
+ matchDest.append(je32(character, Imm32(ch)));
+ }
+ }
+
+ if (charClass.numRangesUnicode) {
+ for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) {
+ UChar lo = charClass.rangesUnicode[i].begin;
+ UChar hi = charClass.rangesUnicode[i].end;
+
+ Jump below = jl32(character, Imm32(lo));
+ matchDest.append(jle32(character, Imm32(hi)));
+ below.link(this);
+ }
+ }
+
+ unicodeFail = jump();
+ isAscii.link(this);
+ }
+
+ if (charClass.numRanges) {
+ unsigned matchIndex = 0;
+ JumpList failures;
+ generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches);
+ while (matchIndex < charClass.numMatches)
+ matchDest.append(je32(character, Imm32((unsigned short)charClass.matches[matchIndex++])));
+
+ failures.link(this);
+ } else if (charClass.numMatches) {
+ // optimization: gather 'a','A' etc back together, can mask & test once.
+ Vector<char> matchesAZaz;
+
+ for (unsigned i = 0; i < charClass.numMatches; ++i) {
+ char ch = charClass.matches[i];
+ if (m_parser.ignoreCase()) {
+ if (isASCIILower(ch)) {
+ matchesAZaz.append(ch);
+ continue;
+ }
+ if (isASCIIUpper(ch))
+ continue;
+ }
+ matchDest.append(je32(character, Imm32((unsigned short)ch)));
+ }
+
+ if (unsigned countAZaz = matchesAZaz.size()) {
+ or32(Imm32(32), character);
+ for (unsigned i = 0; i < countAZaz; ++i)
+ matchDest.append(je32(character, Imm32(matchesAZaz[i])));
+ }
+ }
+
+ if (charClass.numMatchesUnicode || charClass.numRangesUnicode)
+ unicodeFail.link(this);
+}
+
+void Generator::generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert)
+{
+ generateLoadCharacter(failures);
+
+ if (invert)
+ generateCharacterClassInverted(failures, charClass);
+ else {
+ JumpList successes;
+ generateCharacterClassInverted(successes, charClass);
+ failures.append(jump());
+ successes.link(this);
+ }
+
+ add32(Imm32(1), index);
+}
+
+void Generator::generateParenthesesAssertion(JumpList& failures)
+{
+ JumpList disjunctionFailed;
+
+ push(index);
+ m_parser.parseDisjunction(disjunctionFailed);
+ Jump success = jump();
+
+ disjunctionFailed.link(this);
+ pop(index);
+ failures.append(jump());
+
+ success.link(this);
+ pop(index);
+}
+
+void Generator::generateParenthesesInvertedAssertion(JumpList& failures)
+{
+ JumpList disjunctionFailed;
+
+ push(index);
+ m_parser.parseDisjunction(disjunctionFailed);
+
+ // If the disjunction succeeded, the inverted assertion failed.
+ pop(index);
+ failures.append(jump());
+
+ // If the disjunction failed, the inverted assertion succeeded.
+ disjunctionFailed.link(this);
+ pop(index);
+}
+
+void Generator::generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail)
+{
+ jump(start);
+ success.link(this);
+ failures.append(fail);
+}
+
+Generator::Jump Generator::generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter)
+{
+ Jump skip = jump();
+ newFailures.link(this);
+ for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) {
+ store32(Imm32(-1), Address(output, (2 * i) * sizeof(int)));
+ store32(Imm32(-1), Address(output, (2 * i + 1) * sizeof(int)));
+ }
+
+ Jump newFailJump = jump();
+ skip.link(this);
+
+ return newFailJump;
+}
+
+void Generator::generateAssertionBOL(JumpList& failures)
+{
+ if (m_parser.multiline()) {
+ JumpList previousIsNewline;
+
+ // begin of input == success
+ previousIsNewline.append(je32(index, Imm32(0)));
+
+ // now check prev char against newline characters.
+ load16(BaseIndex(input, index, TimesTwo, -2), character);
+ generateCharacterClassInverted(previousIsNewline, CharacterClass::newline());
+
+ failures.append(jump());
+
+ previousIsNewline.link(this);
+ } else
+ failures.append(jne32(index, Imm32(0)));
+}
+
+void Generator::generateAssertionEOL(JumpList& failures)
+{
+ if (m_parser.multiline()) {
+ JumpList nextIsNewline;
+
+ generateLoadCharacter(nextIsNewline); // end of input == success
+ generateCharacterClassInverted(nextIsNewline, CharacterClass::newline());
+ failures.append(jump());
+ nextIsNewline.link(this);
+ } else {
+ failures.append(jne32(length, index));
+ }
+}
+
+void Generator::generateAssertionWordBoundary(JumpList& failures, bool invert)
+{
+ JumpList wordBoundary;
+ JumpList notWordBoundary;
+
+ // (1) Check if the previous value was a word char
+
+ // (1.1) check for begin of input
+ Jump atBegin = je32(index, Imm32(0));
+ // (1.2) load the last char, and chck if is word character
+ load16(BaseIndex(input, index, TimesTwo, -2), character);
+ JumpList previousIsWord;
+ generateCharacterClassInverted(previousIsWord, CharacterClass::wordchar());
+ // (1.3) if we get here, previous is not a word char
+ atBegin.link(this);
+
+ // (2) Handle situation where previous was NOT a \w
+
+ generateLoadCharacter(notWordBoundary);
+ generateCharacterClassInverted(wordBoundary, CharacterClass::wordchar());
+ // (2.1) If we get here, neither chars are word chars
+ notWordBoundary.append(jump());
+
+ // (3) Handle situation where previous was a \w
+
+ // (3.0) link success in first match to here
+ previousIsWord.link(this);
+ generateLoadCharacter(wordBoundary);
+ generateCharacterClassInverted(notWordBoundary, CharacterClass::wordchar());
+ // (3.1) If we get here, this is an end of a word, within the input.
+
+ // (4) Link everything up
+
+ if (invert) {
+ // handle the fall through case
+ wordBoundary.append(jump());
+
+ // looking for non word boundaries, so link boundary fails to here.
+ notWordBoundary.link(this);
+
+ failures.append(wordBoundary);
+ } else {
+ // looking for word boundaries, so link successes here.
+ wordBoundary.link(this);
+
+ failures.append(notWordBoundary);
+ }
+}
+
+void Generator::generateBackreference(JumpList& failures, unsigned subpatternId)
+{
+ push(index);
+ push(repeatCount);
+
+ // get the start pos of the backref into repeatCount (multipurpose!)
+ load32(Address(output, (2 * subpatternId) * sizeof(int)), repeatCount);
+
+ Jump skipIncrement = jump();
+ Label topOfLoop(this);
+
+ add32(Imm32(1), index);
+ add32(Imm32(1), repeatCount);
+ skipIncrement.link(this);
+
+ // check if we're at the end of backref (if we are, success!)
+ Jump endOfBackRef = je32(Address(output, ((2 * subpatternId) + 1) * sizeof(int)), repeatCount);
+
+ load16(BaseIndex(input, repeatCount, MacroAssembler::TimesTwo), character);
+
+ // check if we've run out of input (this would be a can o'fail)
+ Jump endOfInput = je32(length, index);
+
+ je16(character, BaseIndex(input, index, TimesTwo), topOfLoop);
+
+ endOfInput.link(this);
+
+ // Failure
+ pop(repeatCount);
+ pop(index);
+ failures.append(jump());
+
+ // Success
+ endOfBackRef.link(this);
+ pop(repeatCount);
+ pop();
+}
+
+void Generator::terminateAlternative(JumpList& successes, JumpList& failures)
+{
+ successes.append(jump());
+
+ failures.link(this);
+ peek(index);
+}
+
+void Generator::terminateDisjunction(JumpList& successes)
+{
+ successes.link(this);
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WRECGenerator_h
+#define WRECGenerator_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include "Quantifier.h"
+#include "MacroAssembler.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/unicode/Unicode.h>
+#include "WREC.h"
+
+namespace JSC {
+
+ class JSGlobalData;
+
+ namespace WREC {
+
+ class CharacterRange;
+ class GenerateAtomFunctor;
+ class Parser;
+ struct CharacterClass;
+
+ class Generator : private MacroAssembler {
+ public:
+ using MacroAssembler::Jump;
+ using MacroAssembler::JumpList;
+ using MacroAssembler::Label;
+
+ enum ParenthesesType { Capturing, NonCapturing, Assertion, InvertedAssertion, Error };
+
+ static CompiledRegExp compileRegExp(JSGlobalData*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase = false, bool multiline = false);
+
+ Generator(Parser& parser)
+ : m_parser(parser)
+ {
+ }
+
+ static const RegisterID input = X86::eax;
+ static const RegisterID length = X86::ecx;
+ static const RegisterID index = X86::edx;
+ static const RegisterID character = X86::esi;
+ static const RegisterID output = X86::edi;
+ static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match.
+
+ void generateEnter();
+ void generateSaveIndex();
+ void generateIncrementIndex(Jump* failure = 0);
+ void generateLoadCharacter(JumpList& failures);
+ void generateJumpIfNotEndOfInput(Label);
+ void generateReturnSuccess();
+ void generateReturnFailure();
+
+ void generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max);
+ void generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max);
+ void generateBacktrack1();
+ void generateBacktrackBackreference(unsigned subpatternId);
+ void generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert);
+ void generateCharacterClassInverted(JumpList& failures, const CharacterClass& charClass);
+ void generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount);
+ void generatePatternCharacter(JumpList& failures, int ch);
+ void generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count);
+ void generateAssertionWordBoundary(JumpList& failures, bool invert);
+ void generateAssertionBOL(JumpList& failures);
+ void generateAssertionEOL(JumpList& failures);
+ void generateBackreference(JumpList& failures, unsigned subpatternID);
+ void generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max);
+ void generateParenthesesAssertion(JumpList& failures);
+ void generateParenthesesInvertedAssertion(JumpList& failures);
+ Jump generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter);
+ void generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail);
+
+ void terminateAlternative(JumpList& successes, JumpList& failures);
+ void terminateDisjunction(JumpList& successes);
+
+ private:
+ bool generatePatternCharacterPair(JumpList& failures, int ch1, int ch2);
+
+ Parser& m_parser;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // WRECGenerator_h
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WRECParser.h"
+
+#if ENABLE(WREC)
+
+#include "CharacterClassConstructor.h"
+#include "WRECFunctors.h"
+
+using namespace WTF;
+
+namespace JSC { namespace WREC {
+
+// These error messages match the error messages used by PCRE.
+const char* Parser::QuantifierOutOfOrder = "numbers out of order in {} quantifier";
+const char* Parser::QuantifierWithoutAtom = "nothing to repeat";
+const char* Parser::ParenthesesUnmatched = "unmatched parentheses";
+const char* Parser::ParenthesesTypeInvalid = "unrecognized character after (?";
+const char* Parser::ParenthesesNotSupported = ""; // Not a user-visible syntax error -- just signals a syntax that WREC doesn't support yet.
+const char* Parser::CharacterClassUnmatched = "missing terminating ] for character class";
+const char* Parser::CharacterClassOutOfOrder = "range out of order in character class";
+const char* Parser::EscapeUnterminated = "\\ at end of pattern";
+
+class PatternCharacterSequence {
+typedef Generator::JumpList JumpList;
+
+public:
+ PatternCharacterSequence(Generator& generator, JumpList& failures)
+ : m_generator(generator)
+ , m_failures(failures)
+ {
+ }
+
+ size_t size() { return m_sequence.size(); }
+
+ void append(int ch)
+ {
+ m_sequence.append(ch);
+ }
+
+ void flush()
+ {
+ if (!m_sequence.size())
+ return;
+
+ m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size());
+ m_sequence.clear();
+ }
+
+ void flush(const Quantifier& quantifier)
+ {
+ if (!m_sequence.size())
+ return;
+
+ m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size() - 1);
+
+ switch (quantifier.type) {
+ case Quantifier::None:
+ case Quantifier::Error:
+ ASSERT_NOT_REACHED();
+ break;
+
+ case Quantifier::Greedy: {
+ GeneratePatternCharacterFunctor functor(m_sequence.last());
+ m_generator.generateGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max);
+ break;
+ }
+
+ case Quantifier::NonGreedy: {
+ GeneratePatternCharacterFunctor functor(m_sequence.last());
+ m_generator.generateNonGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max);
+ break;
+ }
+ }
+
+ m_sequence.clear();
+ }
+
+private:
+ Generator& m_generator;
+ JumpList& m_failures;
+ Vector<int, 8> m_sequence;
+};
+
+ALWAYS_INLINE Quantifier Parser::consumeGreedyQuantifier()
+{
+ switch (peek()) {
+ case '?':
+ consume();
+ return Quantifier(Quantifier::Greedy, 0, 1);
+
+ case '*':
+ consume();
+ return Quantifier(Quantifier::Greedy, 0);
+
+ case '+':
+ consume();
+ return Quantifier(Quantifier::Greedy, 1);
+
+ case '{': {
+ SavedState state(*this);
+ consume();
+
+ // Accept: {n}, {n,}, {n,m}.
+ // Reject: {n,m} where n > m.
+ // Ignore: Anything else, such as {n, m}.
+
+ if (!peekIsDigit()) {
+ state.restore();
+ return Quantifier();
+ }
+
+ unsigned min = consumeNumber();
+ unsigned max = min;
+
+ if (peek() == ',') {
+ consume();
+ max = peekIsDigit() ? consumeNumber() : Quantifier::Infinity;
+ }
+
+ if (peek() != '}') {
+ state.restore();
+ return Quantifier();
+ }
+ consume();
+
+ if (min > max) {
+ setError(QuantifierOutOfOrder);
+ return Quantifier(Quantifier::Error);
+ }
+
+ return Quantifier(Quantifier::Greedy, min, max);
+ }
+
+ default:
+ return Quantifier(); // No quantifier.
+ }
+}
+
+Quantifier Parser::consumeQuantifier()
+{
+ Quantifier q = consumeGreedyQuantifier();
+
+ if ((q.type == Quantifier::Greedy) && (peek() == '?')) {
+ consume();
+ q.type = Quantifier::NonGreedy;
+ }
+
+ return q;
+}
+
+bool Parser::parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert)
+{
+ Quantifier q = consumeQuantifier();
+
+ switch (q.type) {
+ case Quantifier::None: {
+ m_generator.generateCharacterClass(failures, charClass, invert);
+ break;
+ }
+
+ case Quantifier::Greedy: {
+ GenerateCharacterClassFunctor functor(&charClass, invert);
+ m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max);
+ break;
+ }
+
+ case Quantifier::NonGreedy: {
+ GenerateCharacterClassFunctor functor(&charClass, invert);
+ m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max);
+ break;
+ }
+
+ case Quantifier::Error:
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId)
+{
+ Quantifier q = consumeQuantifier();
+
+ switch (q.type) {
+ case Quantifier::None: {
+ m_generator.generateBackreference(failures, subpatternId);
+ break;
+ }
+
+ case Quantifier::Greedy:
+ case Quantifier::NonGreedy:
+ m_generator.generateBackreferenceQuantifier(failures, q.type, subpatternId, q.min, q.max);
+ return true;
+
+ case Quantifier::Error:
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseParentheses(JumpList& failures)
+{
+ ParenthesesType type = consumeParenthesesType();
+
+ // FIXME: WREC originally failed to backtrack correctly in cases such as
+ // "c".match(/(.*)c/). Now, most parentheses handling is disabled. For
+ // unsupported parentheses, we fall back on PCRE.
+
+ switch (type) {
+ case Generator::Assertion: {
+ m_generator.generateParenthesesAssertion(failures);
+
+ if (consume() != ')') {
+ setError(ParenthesesUnmatched);
+ return false;
+ }
+
+ Quantifier quantifier = consumeQuantifier();
+ if (quantifier.type != Quantifier::None && quantifier.min == 0) {
+ setError(ParenthesesNotSupported);
+ return false;
+ }
+
+ return true;
+ }
+ case Generator::InvertedAssertion: {
+ m_generator.generateParenthesesInvertedAssertion(failures);
+
+ if (consume() != ')') {
+ setError(ParenthesesUnmatched);
+ return false;
+ }
+
+ Quantifier quantifier = consumeQuantifier();
+ if (quantifier.type != Quantifier::None && quantifier.min == 0) {
+ setError(ParenthesesNotSupported);
+ return false;
+ }
+
+ return true;
+ }
+ default:
+ setError(ParenthesesNotSupported);
+ return false;
+ }
+}
+
+bool Parser::parseCharacterClass(JumpList& failures)
+{
+ bool invert = false;
+ if (peek() == '^') {
+ consume();
+ invert = true;
+ }
+
+ CharacterClassConstructor constructor(m_ignoreCase);
+
+ int ch;
+ while ((ch = peek()) != ']') {
+ switch (ch) {
+ case EndOfPattern:
+ setError(CharacterClassUnmatched);
+ return false;
+
+ case '\\': {
+ consume();
+ Escape escape = consumeEscape(true);
+
+ switch (escape.type()) {
+ case Escape::PatternCharacter: {
+ int character = PatternCharacterEscape::cast(escape).character();
+ if (character == '-')
+ constructor.flushBeforeEscapedHyphen();
+ constructor.put(character);
+ break;
+ }
+ case Escape::CharacterClass: {
+ const CharacterClassEscape& characterClassEscape = CharacterClassEscape::cast(escape);
+ ASSERT(!characterClassEscape.invert());
+ constructor.append(characterClassEscape.characterClass());
+ break;
+ }
+ case Escape::Error:
+ return false;
+ case Escape::Backreference:
+ case Escape::WordBoundaryAssertion: {
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ consume();
+ constructor.put(ch);
+ }
+ }
+ consume();
+
+ // lazily catch reversed ranges ([z-a])in character classes
+ if (constructor.isUpsideDown()) {
+ setError(CharacterClassOutOfOrder);
+ return false;
+ }
+
+ constructor.flush();
+ CharacterClass charClass = constructor.charClass();
+ return parseCharacterClassQuantifier(failures, charClass, invert);
+}
+
+bool Parser::parseNonCharacterEscape(JumpList& failures, const Escape& escape)
+{
+ switch (escape.type()) {
+ case Escape::PatternCharacter:
+ ASSERT_NOT_REACHED();
+ return false;
+
+ case Escape::CharacterClass:
+ return parseCharacterClassQuantifier(failures, CharacterClassEscape::cast(escape).characterClass(), CharacterClassEscape::cast(escape).invert());
+
+ case Escape::Backreference:
+ return parseBackreferenceQuantifier(failures, BackreferenceEscape::cast(escape).subpatternId());
+
+ case Escape::WordBoundaryAssertion:
+ m_generator.generateAssertionWordBoundary(failures, WordBoundaryAssertionEscape::cast(escape).invert());
+ return true;
+
+ case Escape::Error:
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+Escape Parser::consumeEscape(bool inCharacterClass)
+{
+ switch (peek()) {
+ case EndOfPattern:
+ setError(EscapeUnterminated);
+ return Escape(Escape::Error);
+
+ // Assertions
+ case 'b':
+ consume();
+ if (inCharacterClass)
+ return PatternCharacterEscape('\b');
+ return WordBoundaryAssertionEscape(false); // do not invert
+ case 'B':
+ consume();
+ if (inCharacterClass)
+ return PatternCharacterEscape('B');
+ return WordBoundaryAssertionEscape(true); // invert
+
+ // CharacterClassEscape
+ case 'd':
+ consume();
+ return CharacterClassEscape(CharacterClass::digits(), false);
+ case 's':
+ consume();
+ return CharacterClassEscape(CharacterClass::spaces(), false);
+ case 'w':
+ consume();
+ return CharacterClassEscape(CharacterClass::wordchar(), false);
+ case 'D':
+ consume();
+ return inCharacterClass
+ ? CharacterClassEscape(CharacterClass::nondigits(), false)
+ : CharacterClassEscape(CharacterClass::digits(), true);
+ case 'S':
+ consume();
+ return inCharacterClass
+ ? CharacterClassEscape(CharacterClass::nonspaces(), false)
+ : CharacterClassEscape(CharacterClass::spaces(), true);
+ case 'W':
+ consume();
+ return inCharacterClass
+ ? CharacterClassEscape(CharacterClass::nonwordchar(), false)
+ : CharacterClassEscape(CharacterClass::wordchar(), true);
+
+ // DecimalEscape
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ if (peekDigit() > m_numSubpatterns || inCharacterClass) {
+ // To match Firefox, we parse an invalid backreference in the range [1-7]
+ // as an octal escape.
+ return peekDigit() > 7 ? PatternCharacterEscape('\\') : PatternCharacterEscape(consumeOctal());
+ }
+
+ int value = 0;
+ do {
+ unsigned newValue = value * 10 + peekDigit();
+ if (newValue > m_numSubpatterns)
+ break;
+ value = newValue;
+ consume();
+ } while (peekIsDigit());
+
+ return BackreferenceEscape(value);
+ }
+
+ // Octal escape
+ case '0':
+ consume();
+ return PatternCharacterEscape(consumeOctal());
+
+ // ControlEscape
+ case 'f':
+ consume();
+ return PatternCharacterEscape('\f');
+ case 'n':
+ consume();
+ return PatternCharacterEscape('\n');
+ case 'r':
+ consume();
+ return PatternCharacterEscape('\r');
+ case 't':
+ consume();
+ return PatternCharacterEscape('\t');
+ case 'v':
+ consume();
+ return PatternCharacterEscape('\v');
+
+ // ControlLetter
+ case 'c': {
+ SavedState state(*this);
+ consume();
+
+ int control = consume();
+ // To match Firefox, inside a character class, we also accept numbers
+ // and '_' as control characters.
+ if ((!inCharacterClass && !isASCIIAlpha(control)) || (!isASCIIAlphanumeric(control) && control != '_')) {
+ state.restore();
+ return PatternCharacterEscape('\\');
+ }
+ return PatternCharacterEscape(control & 31);
+ }
+
+ // HexEscape
+ case 'x': {
+ consume();
+
+ SavedState state(*this);
+ int x = consumeHex(2);
+ if (x == -1) {
+ state.restore();
+ return PatternCharacterEscape('x');
+ }
+ return PatternCharacterEscape(x);
+ }
+
+ // UnicodeEscape
+ case 'u': {
+ consume();
+
+ SavedState state(*this);
+ int x = consumeHex(4);
+ if (x == -1) {
+ state.restore();
+ return PatternCharacterEscape('u');
+ }
+ return PatternCharacterEscape(x);
+ }
+
+ // IdentityEscape
+ default:
+ return PatternCharacterEscape(consume());
+ }
+}
+
+void Parser::parseAlternative(JumpList& failures)
+{
+ PatternCharacterSequence sequence(m_generator, failures);
+
+ while (1) {
+ switch (peek()) {
+ case EndOfPattern:
+ case '|':
+ case ')':
+ sequence.flush();
+ return;
+
+ case '*':
+ case '+':
+ case '?':
+ case '{': {
+ Quantifier q = consumeQuantifier();
+
+ if (q.type == Quantifier::None) {
+ sequence.append(consume());
+ continue;
+ }
+
+ if (q.type == Quantifier::Error)
+ return;
+
+ if (!sequence.size()) {
+ setError(QuantifierWithoutAtom);
+ return;
+ }
+
+ sequence.flush(q);
+ continue;
+ }
+
+ case '^':
+ consume();
+
+ sequence.flush();
+ m_generator.generateAssertionBOL(failures);
+ continue;
+
+ case '$':
+ consume();
+
+ sequence.flush();
+ m_generator.generateAssertionEOL(failures);
+ continue;
+
+ case '.':
+ consume();
+
+ sequence.flush();
+ if (!parseCharacterClassQuantifier(failures, CharacterClass::newline(), true))
+ return;
+ continue;
+
+ case '[':
+ consume();
+
+ sequence.flush();
+ if (!parseCharacterClass(failures))
+ return;
+ continue;
+
+ case '(':
+ consume();
+
+ sequence.flush();
+ if (!parseParentheses(failures))
+ return;
+ continue;
+
+ case '\\': {
+ consume();
+
+ Escape escape = consumeEscape(false);
+ if (escape.type() == Escape::PatternCharacter) {
+ sequence.append(PatternCharacterEscape::cast(escape).character());
+ continue;
+ }
+
+ sequence.flush();
+ if (!parseNonCharacterEscape(failures, escape))
+ return;
+ continue;
+ }
+
+ default:
+ sequence.append(consume());
+ continue;
+ }
+ }
+}
+
+/*
+ TOS holds index.
+*/
+void Parser::parseDisjunction(JumpList& failures)
+{
+ parseAlternative(failures);
+ if (peek() != '|')
+ return;
+
+ JumpList successes;
+ do {
+ consume();
+ m_generator.terminateAlternative(successes, failures);
+ parseAlternative(failures);
+ } while (peek() == '|');
+
+ m_generator.terminateDisjunction(successes);
+}
+
+Generator::ParenthesesType Parser::consumeParenthesesType()
+{
+ if (peek() != '?')
+ return Generator::Capturing;
+ consume();
+
+ switch (consume()) {
+ case ':':
+ return Generator::NonCapturing;
+
+ case '=':
+ return Generator::Assertion;
+
+ case '!':
+ return Generator::InvertedAssertion;
+
+ default:
+ setError(ParenthesesTypeInvalid);
+ return Generator::Error;
+ }
+}
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Parser_h
+#define Parser_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(WREC)
+
+#include "Escapes.h"
+#include "Quantifier.h"
+#include "UString.h"
+#include "WRECGenerator.h"
+#include <wtf/ASCIICType.h>
+
+namespace JSC { namespace WREC {
+
+ struct CharacterClass;
+
+ class Parser {
+ typedef Generator::JumpList JumpList;
+ typedef Generator::ParenthesesType ParenthesesType;
+
+ friend class SavedState;
+
+ public:
+ Parser(const UString& pattern, bool ignoreCase, bool multiline)
+ : m_generator(*this)
+ , m_data(pattern.data())
+ , m_size(pattern.size())
+ , m_ignoreCase(ignoreCase)
+ , m_multiline(multiline)
+ {
+ reset();
+ }
+
+ Generator& generator() { return m_generator; }
+
+ bool ignoreCase() const { return m_ignoreCase; }
+ bool multiline() const { return m_multiline; }
+
+ void recordSubpattern() { ++m_numSubpatterns; }
+ unsigned numSubpatterns() const { return m_numSubpatterns; }
+
+ const char* error() const { return m_error; }
+ const char* syntaxError() const { return m_error == ParenthesesNotSupported ? 0 : m_error; }
+
+ void parsePattern(JumpList& failures)
+ {
+ reset();
+
+ parseDisjunction(failures);
+
+ if (peek() != EndOfPattern)
+ setError(ParenthesesUnmatched); // Parsing the pattern should fully consume it.
+ }
+
+ void parseDisjunction(JumpList& failures);
+ void parseAlternative(JumpList& failures);
+ bool parseTerm(JumpList& failures);
+ bool parseNonCharacterEscape(JumpList& failures, const Escape&);
+ bool parseParentheses(JumpList& failures);
+ bool parseCharacterClass(JumpList& failures);
+ bool parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert);
+ bool parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId);
+
+ private:
+ class SavedState {
+ public:
+ SavedState(Parser& parser)
+ : m_parser(parser)
+ , m_index(parser.m_index)
+ {
+ }
+
+ void restore()
+ {
+ m_parser.m_index = m_index;
+ }
+
+ private:
+ Parser& m_parser;
+ unsigned m_index;
+ };
+
+ void reset()
+ {
+ m_index = 0;
+ m_numSubpatterns = 0;
+ m_error = 0;
+ }
+
+ void setError(const char* error)
+ {
+ if (m_error)
+ return;
+ m_error = error;
+ }
+
+ int peek()
+ {
+ if (m_index >= m_size)
+ return EndOfPattern;
+ return m_data[m_index];
+ }
+
+ int consume()
+ {
+ if (m_index >= m_size)
+ return EndOfPattern;
+ return m_data[m_index++];
+ }
+
+ bool peekIsDigit()
+ {
+ return WTF::isASCIIDigit(peek());
+ }
+
+ unsigned peekDigit()
+ {
+ ASSERT(peekIsDigit());
+ return peek() - '0';
+ }
+
+ unsigned consumeDigit()
+ {
+ ASSERT(peekIsDigit());
+ return consume() - '0';
+ }
+
+ unsigned consumeNumber()
+ {
+ int n = consumeDigit();
+ while (peekIsDigit()) {
+ n *= 10;
+ n += consumeDigit();
+ }
+ return n;
+ }
+
+ int consumeHex(int count)
+ {
+ int n = 0;
+ while (count--) {
+ if (!WTF::isASCIIHexDigit(peek()))
+ return -1;
+ n = (n << 4) | WTF::toASCIIHexValue(consume());
+ }
+ return n;
+ }
+
+ unsigned consumeOctal()
+ {
+ unsigned n = 0;
+ while (n < 32 && WTF::isASCIIOctalDigit(peek()))
+ n = n * 8 + consumeDigit();
+ return n;
+ }
+
+ ALWAYS_INLINE Quantifier consumeGreedyQuantifier();
+ Quantifier consumeQuantifier();
+ Escape consumeEscape(bool inCharacterClass);
+ ParenthesesType consumeParenthesesType();
+
+ static const int EndOfPattern = -1;
+
+ // Error messages.
+ static const char* QuantifierOutOfOrder;
+ static const char* QuantifierWithoutAtom;
+ static const char* ParenthesesUnmatched;
+ static const char* ParenthesesTypeInvalid;
+ static const char* ParenthesesNotSupported;
+ static const char* CharacterClassUnmatched;
+ static const char* CharacterClassOutOfOrder;
+ static const char* EscapeUnterminated;
+
+ Generator m_generator;
+ const UChar* m_data;
+ unsigned m_size;
+ unsigned m_index;
+ bool m_ignoreCase;
+ bool m_multiline;
+ unsigned m_numSubpatterns;
+ const char* m_error;
+ };
+
+} } // namespace JSC::WREC
+
+#endif // ENABLE(WREC)
+
+#endif // Parser_h
#ifndef WTF_ASCIICType_h
#define WTF_ASCIICType_h
+#include <wtf/Assertions.h>
#include <wtf/Platform.h>
// The behavior of many of the functions in the <ctype.h> header is dependent
namespace WTF {
+ inline bool isASCII(char c) { return !(c & ~0x7F); }
+ inline bool isASCII(unsigned short c) { return !(c & ~0x7F); }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCII(wchar_t c) { return !(c & ~0x7F); }
+#endif
+ inline bool isASCII(int c) { return !(c & ~0x7F); }
+
inline bool isASCIIAlpha(char c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
inline bool isASCIIAlpha(unsigned short c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
#endif
inline bool isASCIIAlpha(int c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
- inline bool isASCIIAlphanumeric(char c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
- inline bool isASCIIAlphanumeric(unsigned short c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
+ inline bool isASCIIAlphanumeric(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
+ inline bool isASCIIAlphanumeric(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
- inline bool isASCIIAlphanumeric(wchar_t c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
+ inline bool isASCIIAlphanumeric(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
#endif
- inline bool isASCIIAlphanumeric(int c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
+ inline bool isASCIIAlphanumeric(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
inline bool isASCIIDigit(char c) { return (c >= '0') & (c <= '9'); }
inline bool isASCIIDigit(unsigned short c) { return (c >= '0') & (c <= '9'); }
#endif
inline bool isASCIIDigit(int c) { return (c >= '0') & (c <= '9'); }
- inline bool isASCIIHexDigit(char c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'f'; }
- inline bool isASCIIHexDigit(unsigned short c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'f'; }
+ inline bool isASCIIHexDigit(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
+ inline bool isASCIIHexDigit(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
- inline bool isASCIIHexDigit(wchar_t c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'f'; }
+ inline bool isASCIIHexDigit(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
#endif
- inline bool isASCIIHexDigit(int c) { return c >= '0' && c <= '9' || (c | 0x20) >= 'a' && (c | 0x20) <= 'f'; }
+ inline bool isASCIIHexDigit(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
+
+ inline bool isASCIIOctalDigit(char c) { return (c >= '0') & (c <= '7'); }
+ inline bool isASCIIOctalDigit(unsigned short c) { return (c >= '0') & (c <= '7'); }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCIIOctalDigit(wchar_t c) { return (c >= '0') & (c <= '7'); }
+#endif
+ inline bool isASCIIOctalDigit(int c) { return (c >= '0') & (c <= '7'); }
inline bool isASCIILower(char c) { return c >= 'a' && c <= 'z'; }
inline bool isASCIILower(unsigned short c) { return c >= 'a' && c <= 'z'; }
inline bool isASCIIUpper(int c) { return c >= 'A' && c <= 'Z'; }
/*
- Statistics from a run of the PLT on the usage of isASCIISpace:
- Hex Name Count
- --- ---- -----
- ALL OTHER VALUES 689383
- x20 SPACE 294720
- x0A NEWLINE 89059
- x09 TAB 28320
- x0D CARRIAGE RETURN 0
- x0C FORMFEED 0
- x0B VERTICAL TAB 0
-
+ Statistics from a run of Apple's page load test for callers of isASCIISpace:
+
+ character count
+ --------- -----
+ non-spaces 689383
+ 20 space 294720
+ 0A \n 89059
+ 09 \t 28320
+ 0D \r 0
+ 0C \f 0
+ 0B \v 0
*/
-
inline bool isASCIISpace(char c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
inline bool isASCIISpace(unsigned short c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
#endif
inline int toASCIIUpper(int c) { return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5)); }
+ inline int toASCIIHexValue(char c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+ inline int toASCIIHexValue(unsigned short c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline int toASCIIHexValue(wchar_t c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+#endif
+ inline int toASCIIHexValue(int c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+
+ inline bool isASCIIPrintable(char c) { return c >= ' ' && c <= '~'; }
+ inline bool isASCIIPrintable(unsigned short c) { return c >= ' ' && c <= '~'; }
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ inline bool isASCIIPrintable(wchar_t c) { return c >= ' ' && c <= '~'; }
+#endif
+ inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; }
}
#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Based on Abstract AVL Tree Template v1.5 by Walt Karas
+ * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AVL_TREE_H_
+#define AVL_TREE_H_
+
+#include "Assertions.h"
+
+namespace WTF {
+
+// Here is the reference class for BSet.
+//
+// class BSet
+// {
+// public:
+//
+// class ANY_bitref
+// {
+// public:
+// operator bool ();
+// void operator = (bool b);
+// };
+//
+// // Does not have to initialize bits.
+// BSet();
+//
+// // Must return a valid value for index when 0 <= index < maxDepth
+// ANY_bitref operator [] (unsigned index);
+//
+// // Set all bits to 1.
+// void set();
+//
+// // Set all bits to 0.
+// void reset();
+// };
+
+template<unsigned maxDepth>
+class AVLTreeDefaultBSet {
+public:
+ bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; }
+ void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; }
+ void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }
+
+private:
+ bool m_data[maxDepth];
+};
+
+// How to determine maxDepth:
+// d Minimum number of nodes
+// 2 2
+// 3 4
+// 4 7
+// 5 12
+// 6 20
+// 7 33
+// 8 54
+// 9 88
+// 10 143
+// 11 232
+// 12 376
+// 13 609
+// 14 986
+// 15 1,596
+// 16 2,583
+// 17 4,180
+// 18 6,764
+// 19 10,945
+// 20 17,710
+// 21 28,656
+// 22 46,367
+// 23 75,024
+// 24 121,392
+// 25 196,417
+// 26 317,810
+// 27 514,228
+// 28 832,039
+// 29 1,346,268
+// 30 2,178,308
+// 31 3,524,577
+// 32 5,702,886
+// 33 9,227,464
+// 34 14,930,351
+// 35 24,157,816
+// 36 39,088,168
+// 37 63,245,985
+// 38 102,334,154
+// 39 165,580,140
+// 40 267,914,295
+// 41 433,494,436
+// 42 701,408,732
+// 43 1,134,903,169
+// 44 1,836,311,902
+// 45 2,971,215,072
+//
+// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28.
+// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
+
+template <class Abstractor, unsigned maxDepth = 32, class BSet = AVLTreeDefaultBSet<maxDepth> >
+class AVLTree {
+public:
+
+ typedef typename Abstractor::key key;
+ typedef typename Abstractor::handle handle;
+ typedef typename Abstractor::size size;
+
+ enum SearchType {
+ EQUAL = 1,
+ LESS = 2,
+ GREATER = 4,
+ LESS_EQUAL = EQUAL | LESS,
+ GREATER_EQUAL = EQUAL | GREATER
+ };
+
+
+ Abstractor& abstractor() { return abs; }
+
+ inline handle insert(handle h);
+
+ inline handle search(key k, SearchType st = EQUAL);
+ inline handle search_least();
+ inline handle search_greatest();
+
+ inline handle remove(key k);
+
+ inline handle subst(handle new_node);
+
+ void purge() { abs.root = null(); }
+
+ bool is_empty() { return abs.root == null(); }
+
+ AVLTree() { abs.root = null(); }
+
+ class Iterator {
+ public:
+
+ // Initialize depth to invalid value, to indicate iterator is
+ // invalid. (Depth is zero-base.)
+ Iterator() { depth = ~0U; }
+
+ void start_iter(AVLTree &tree, key k, SearchType st = EQUAL)
+ {
+ // Mask of high bit in an int.
+ const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
+
+ // Save the tree that we're going to iterate through in a
+ // member variable.
+ tree_ = &tree;
+
+ int cmp, target_cmp;
+ handle h = tree_->abs.root;
+ unsigned d = 0;
+
+ depth = ~0U;
+
+ if (h == null())
+ // Tree is empty.
+ return;
+
+ if (st & LESS)
+ // Key can be greater than key of starting node.
+ target_cmp = 1;
+ else if (st & GREATER)
+ // Key can be less than key of starting node.
+ target_cmp = -1;
+ else
+ // Key must be same as key of starting node.
+ target_cmp = 0;
+
+ for (;;) {
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0) {
+ if (st & EQUAL) {
+ // Equal node was sought and found as starting node.
+ depth = d;
+ break;
+ }
+ cmp = -target_cmp;
+ } else if (target_cmp != 0) {
+ if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) {
+ // cmp and target_cmp are both negative or both positive.
+ depth = d;
+ }
+ }
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ if (h == null())
+ break;
+ branch[d] = cmp > 0;
+ path_h[d++] = h;
+ }
+ }
+
+ void start_iter_least(AVLTree &tree)
+ {
+ tree_ = &tree;
+
+ handle h = tree_->abs.root;
+
+ depth = ~0U;
+
+ branch.reset();
+
+ while (h != null()) {
+ if (depth != ~0U)
+ path_h[depth] = h;
+ depth++;
+ h = get_lt(h);
+ }
+ }
+
+ void start_iter_greatest(AVLTree &tree)
+ {
+ tree_ = &tree;
+
+ handle h = tree_->abs.root;
+
+ depth = ~0U;
+
+ branch.set();
+
+ while (h != null()) {
+ if (depth != ~0U)
+ path_h[depth] = h;
+ depth++;
+ h = get_gt(h);
+ }
+ }
+
+ handle operator*()
+ {
+ if (depth == ~0U)
+ return null();
+
+ return depth == 0 ? tree_->abs.root : path_h[depth - 1];
+ }
+
+ void operator++()
+ {
+ if (depth != ~0U) {
+ handle h = get_gt(**this);
+ if (h == null()) {
+ do {
+ if (depth == 0) {
+ depth = ~0U;
+ break;
+ }
+ depth--;
+ } while (branch[depth]);
+ } else {
+ branch[depth] = true;
+ path_h[depth++] = h;
+ for (;;) {
+ h = get_lt(h);
+ if (h == null())
+ break;
+ branch[depth] = false;
+ path_h[depth++] = h;
+ }
+ }
+ }
+ }
+
+ void operator--()
+ {
+ if (depth != ~0U) {
+ handle h = get_lt(**this);
+ if (h == null())
+ do {
+ if (depth == 0) {
+ depth = ~0U;
+ break;
+ }
+ depth--;
+ } while (!branch[depth]);
+ else {
+ branch[depth] = false;
+ path_h[depth++] = h;
+ for (;;) {
+ h = get_gt(h);
+ if (h == null())
+ break;
+ branch[depth] = true;
+ path_h[depth++] = h;
+ }
+ }
+ }
+ }
+
+ void operator++(int) { ++(*this); }
+ void operator--(int) { --(*this); }
+
+ protected:
+
+ // Tree being iterated over.
+ AVLTree *tree_;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ // Zero-based depth of path into tree.
+ unsigned depth;
+
+ // Handles of nodes in path from root to current node (returned by *).
+ handle path_h[maxDepth - 1];
+
+ int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
+ int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); }
+ handle get_lt(handle h) { return tree_->abs.get_less(h); }
+ handle get_gt(handle h) { return tree_->abs.get_greater(h); }
+ handle null() { return tree_->abs.null(); }
+ };
+
+ template<typename fwd_iter>
+ bool build(fwd_iter p, size num_nodes)
+ {
+ if (num_nodes == 0) {
+ abs.root = null();
+ return true;
+ }
+
+ // Gives path to subtree being built. If branch[N] is false, branch
+ // less from the node at depth N, if true branch greater.
+ BSet branch;
+
+ // If rem[N] is true, then for the current subtree at depth N, it's
+ // greater subtree has one more node than it's less subtree.
+ BSet rem;
+
+ // Depth of root node of current subtree.
+ unsigned depth = 0;
+
+ // Number of nodes in current subtree.
+ size num_sub = num_nodes;
+
+ // The algorithm relies on a stack of nodes whose less subtree has
+ // been built, but whose right subtree has not yet been built. The
+ // stack is implemented as linked list. The nodes are linked
+ // together by having the "greater" handle of a node set to the
+ // next node in the list. "less_parent" is the handle of the first
+ // node in the list.
+ handle less_parent = null();
+
+ // h is root of current subtree, child is one of its children.
+ handle h, child;
+
+ for (;;) {
+ while (num_sub > 2) {
+ // Subtract one for root of subtree.
+ num_sub--;
+ rem[depth] = !!(num_sub & 1);
+ branch[depth++] = false;
+ num_sub >>= 1;
+ }
+
+ if (num_sub == 2) {
+ // Build a subtree with two nodes, slanting to greater.
+ // I arbitrarily chose to always have the extra node in the
+ // greater subtree when there is an odd number of nodes to
+ // split between the two subtrees.
+
+ h = *p;
+ p++;
+ child = *p;
+ p++;
+ set_lt(child, null());
+ set_gt(child, null());
+ set_bf(child, 0);
+ set_gt(h, child);
+ set_lt(h, null());
+ set_bf(h, 1);
+ } else { // num_sub == 1
+ // Build a subtree with one node.
+
+ h = *p;
+ p++;
+ set_lt(h, null());
+ set_gt(h, null());
+ set_bf(h, 0);
+ }
+
+ while (depth) {
+ depth--;
+ if (!branch[depth])
+ // We've completed a less subtree.
+ break;
+
+ // We've completed a greater subtree, so attach it to
+ // its parent (that is less than it). We pop the parent
+ // off the stack of less parents.
+ child = h;
+ h = less_parent;
+ less_parent = get_gt(h);
+ set_gt(h, child);
+ // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
+ num_sub <<= 1;
+ num_sub += 1 - rem[depth];
+ if (num_sub & (num_sub - 1))
+ // num_sub is not a power of 2
+ set_bf(h, 0);
+ else
+ // num_sub is a power of 2
+ set_bf(h, 1);
+ }
+
+ if (num_sub == num_nodes)
+ // We've completed the full tree.
+ break;
+
+ // The subtree we've completed is the less subtree of the
+ // next node in the sequence.
+
+ child = h;
+ h = *p;
+ p++;
+ set_lt(h, child);
+
+ // Put h into stack of less parents.
+ set_gt(h, less_parent);
+ less_parent = h;
+
+ // Proceed to creating greater than subtree of h.
+ branch[depth] = true;
+ num_sub += rem[depth++];
+
+ } // end for (;;)
+
+ abs.root = h;
+
+ return true;
+ }
+
+protected:
+
+ friend class Iterator;
+
+ // Create a class whose sole purpose is to take advantage of
+ // the "empty member" optimization.
+ struct abs_plus_root : public Abstractor {
+ // The handle of the root element in the AVL tree.
+ handle root;
+ };
+
+ abs_plus_root abs;
+
+
+ handle get_lt(handle h) { return abs.get_less(h); }
+ void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
+
+ handle get_gt(handle h) { return abs.get_greater(h); }
+ void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
+
+ int get_bf(handle h) { return abs.get_balance_factor(h); }
+ void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
+
+ int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
+ int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
+
+ handle null() { return abs.null(); }
+
+private:
+
+ // Balances subtree, returns handle of root node of subtree
+ // after balancing.
+ handle balance(handle bal_h)
+ {
+ handle deep_h;
+
+ // Either the "greater than" or the "less than" subtree of
+ // this node has to be 2 levels deeper (or else it wouldn't
+ // need balancing).
+
+ if (get_bf(bal_h) > 0) {
+ // "Greater than" subtree is deeper.
+
+ deep_h = get_gt(bal_h);
+
+ if (get_bf(deep_h) < 0) {
+ handle old_h = bal_h;
+ bal_h = get_lt(deep_h);
+
+ set_gt(old_h, get_lt(bal_h));
+ set_lt(deep_h, get_gt(bal_h));
+ set_lt(bal_h, old_h);
+ set_gt(bal_h, deep_h);
+
+ int bf = get_bf(bal_h);
+ if (bf != 0) {
+ if (bf > 0) {
+ set_bf(old_h, -1);
+ set_bf(deep_h, 0);
+ } else {
+ set_bf(deep_h, 1);
+ set_bf(old_h, 0);
+ }
+ set_bf(bal_h, 0);
+ } else {
+ set_bf(old_h, 0);
+ set_bf(deep_h, 0);
+ }
+ } else {
+ set_gt(bal_h, get_lt(deep_h));
+ set_lt(deep_h, bal_h);
+ if (get_bf(deep_h) == 0) {
+ set_bf(deep_h, -1);
+ set_bf(bal_h, 1);
+ } else {
+ set_bf(deep_h, 0);
+ set_bf(bal_h, 0);
+ }
+ bal_h = deep_h;
+ }
+ } else {
+ // "Less than" subtree is deeper.
+
+ deep_h = get_lt(bal_h);
+
+ if (get_bf(deep_h) > 0) {
+ handle old_h = bal_h;
+ bal_h = get_gt(deep_h);
+ set_lt(old_h, get_gt(bal_h));
+ set_gt(deep_h, get_lt(bal_h));
+ set_gt(bal_h, old_h);
+ set_lt(bal_h, deep_h);
+
+ int bf = get_bf(bal_h);
+ if (bf != 0) {
+ if (bf < 0) {
+ set_bf(old_h, 1);
+ set_bf(deep_h, 0);
+ } else {
+ set_bf(deep_h, -1);
+ set_bf(old_h, 0);
+ }
+ set_bf(bal_h, 0);
+ } else {
+ set_bf(old_h, 0);
+ set_bf(deep_h, 0);
+ }
+ } else {
+ set_lt(bal_h, get_gt(deep_h));
+ set_gt(deep_h, bal_h);
+ if (get_bf(deep_h) == 0) {
+ set_bf(deep_h, 1);
+ set_bf(bal_h, -1);
+ } else {
+ set_bf(deep_h, 0);
+ set_bf(bal_h, 0);
+ }
+ bal_h = deep_h;
+ }
+ }
+
+ return bal_h;
+ }
+
+};
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::insert(handle h)
+{
+ set_lt(h, null());
+ set_gt(h, null());
+ set_bf(h, 0);
+
+ if (abs.root == null())
+ abs.root = h;
+ else {
+ // Last unbalanced node encountered in search for insertion point.
+ handle unbal = null();
+ // Parent of last unbalanced node.
+ handle parent_unbal = null();
+ // Balance factor of last unbalanced node.
+ int unbal_bf;
+
+ // Zero-based depth in tree.
+ unsigned depth = 0, unbal_depth = 0;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ handle hh = abs.root;
+ handle parent = null();
+ int cmp;
+
+ do {
+ if (get_bf(hh) != 0) {
+ unbal = hh;
+ parent_unbal = parent;
+ unbal_depth = depth;
+ }
+ cmp = cmp_n_n(h, hh);
+ if (cmp == 0)
+ // Duplicate key.
+ return hh;
+ parent = hh;
+ hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
+ branch[depth++] = cmp > 0;
+ } while (hh != null());
+
+ // Add node to insert as leaf of tree.
+ if (cmp < 0)
+ set_lt(parent, h);
+ else
+ set_gt(parent, h);
+
+ depth = unbal_depth;
+
+ if (unbal == null())
+ hh = abs.root;
+ else {
+ cmp = branch[depth++] ? 1 : -1;
+ unbal_bf = get_bf(unbal);
+ if (cmp < 0)
+ unbal_bf--;
+ else // cmp > 0
+ unbal_bf++;
+ hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
+ if ((unbal_bf != -2) && (unbal_bf != 2)) {
+ // No rebalancing of tree is necessary.
+ set_bf(unbal, unbal_bf);
+ unbal = null();
+ }
+ }
+
+ if (hh != null())
+ while (h != hh) {
+ cmp = branch[depth++] ? 1 : -1;
+ if (cmp < 0) {
+ set_bf(hh, -1);
+ hh = get_lt(hh);
+ } else { // cmp > 0
+ set_bf(hh, 1);
+ hh = get_gt(hh);
+ }
+ }
+
+ if (unbal != null()) {
+ unbal = balance(unbal);
+ if (parent_unbal == null())
+ abs.root = unbal;
+ else {
+ depth = unbal_depth - 1;
+ cmp = branch[depth] ? 1 : -1;
+ if (cmp < 0)
+ set_lt(parent_unbal, unbal);
+ else // cmp > 0
+ set_gt(parent_unbal, unbal);
+ }
+ }
+ }
+
+ return h;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search(key k, typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st)
+{
+ const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
+
+ int cmp, target_cmp;
+ handle match_h = null();
+ handle h = abs.root;
+
+ if (st & LESS)
+ target_cmp = 1;
+ else if (st & GREATER)
+ target_cmp = -1;
+ else
+ target_cmp = 0;
+
+ while (h != null()) {
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0) {
+ if (st & EQUAL) {
+ match_h = h;
+ break;
+ }
+ cmp = -target_cmp;
+ } else if (target_cmp != 0)
+ if (!((cmp ^ target_cmp) & MASK_HIGH_BIT))
+ // cmp and target_cmp are both positive or both negative.
+ match_h = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ }
+
+ return match_h;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search_least()
+{
+ handle h = abs.root, parent = null();
+
+ while (h != null()) {
+ parent = h;
+ h = get_lt(h);
+ }
+
+ return parent;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::search_greatest()
+{
+ handle h = abs.root, parent = null();
+
+ while (h != null()) {
+ parent = h;
+ h = get_gt(h);
+ }
+
+ return parent;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::remove(key k)
+{
+ // Zero-based depth in tree.
+ unsigned depth = 0, rm_depth;
+
+ // Records a path into the tree. If branch[n] is true, indicates
+ // take greater branch from the nth node in the path, otherwise
+ // take the less branch. branch[0] gives branch from root, and
+ // so on.
+ BSet branch;
+
+ handle h = abs.root;
+ handle parent = null(), child;
+ int cmp, cmp_shortened_sub_with_path;
+
+ for (;;) {
+ if (h == null())
+ // No node in tree with given key.
+ return null();
+ cmp = cmp_k_n(k, h);
+ if (cmp == 0)
+ // Found node to remove.
+ break;
+ parent = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ branch[depth++] = cmp > 0;
+ cmp_shortened_sub_with_path = cmp;
+ }
+ handle rm = h;
+ handle parent_rm = parent;
+ rm_depth = depth;
+
+ // If the node to remove is not a leaf node, we need to get a
+ // leaf node, or a node with a single leaf as its child, to put
+ // in the place of the node to remove. We will get the greatest
+ // node in the less subtree (of the node to remove), or the least
+ // node in the greater subtree. We take the leaf node from the
+ // deeper subtree, if there is one.
+
+ if (get_bf(h) < 0) {
+ child = get_lt(h);
+ branch[depth] = false;
+ cmp = -1;
+ } else {
+ child = get_gt(h);
+ branch[depth] = true;
+ cmp = 1;
+ }
+ depth++;
+
+ if (child != null()) {
+ cmp = -cmp;
+ do {
+ parent = h;
+ h = child;
+ if (cmp < 0) {
+ child = get_lt(h);
+ branch[depth] = false;
+ } else {
+ child = get_gt(h);
+ branch[depth] = true;
+ }
+ depth++;
+ } while (child != null());
+
+ if (parent == rm)
+ // Only went through do loop once. Deleted node will be replaced
+ // in the tree structure by one of its immediate children.
+ cmp_shortened_sub_with_path = -cmp;
+ else
+ cmp_shortened_sub_with_path = cmp;
+
+ // Get the handle of the opposite child, which may not be null.
+ child = cmp > 0 ? get_lt(h) : get_gt(h);
+ }
+
+ if (parent == null())
+ // There were only 1 or 2 nodes in this tree.
+ abs.root = child;
+ else if (cmp_shortened_sub_with_path < 0)
+ set_lt(parent, child);
+ else
+ set_gt(parent, child);
+
+ // "path" is the parent of the subtree being eliminated or reduced
+ // from a depth of 2 to 1. If "path" is the node to be removed, we
+ // set path to the node we're about to poke into the position of the
+ // node to be removed.
+ handle path = parent == rm ? h : parent;
+
+ if (h != rm) {
+ // Poke in the replacement for the node to be removed.
+ set_lt(h, get_lt(rm));
+ set_gt(h, get_gt(rm));
+ set_bf(h, get_bf(rm));
+ if (parent_rm == null())
+ abs.root = h;
+ else {
+ depth = rm_depth - 1;
+ if (branch[depth])
+ set_gt(parent_rm, h);
+ else
+ set_lt(parent_rm, h);
+ }
+ }
+
+ if (path != null()) {
+ // Create a temporary linked list from the parent of the path node
+ // to the root node.
+ h = abs.root;
+ parent = null();
+ depth = 0;
+ while (h != path) {
+ if (branch[depth++]) {
+ child = get_gt(h);
+ set_gt(h, parent);
+ } else {
+ child = get_lt(h);
+ set_lt(h, parent);
+ }
+ parent = h;
+ h = child;
+ }
+
+ // Climb from the path node to the root node using the linked
+ // list, restoring the tree structure and rebalancing as necessary.
+ bool reduced_depth = true;
+ int bf;
+ cmp = cmp_shortened_sub_with_path;
+ for (;;) {
+ if (reduced_depth) {
+ bf = get_bf(h);
+ if (cmp < 0)
+ bf++;
+ else // cmp > 0
+ bf--;
+ if ((bf == -2) || (bf == 2)) {
+ h = balance(h);
+ bf = get_bf(h);
+ } else
+ set_bf(h, bf);
+ reduced_depth = (bf == 0);
+ }
+ if (parent == null())
+ break;
+ child = h;
+ h = parent;
+ cmp = branch[--depth] ? 1 : -1;
+ if (cmp < 0) {
+ parent = get_lt(h);
+ set_lt(h, child);
+ } else {
+ parent = get_gt(h);
+ set_gt(h, child);
+ }
+ }
+ abs.root = h;
+ }
+
+ return rm;
+}
+
+template <class Abstractor, unsigned maxDepth, class BSet>
+inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
+AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node)
+{
+ handle h = abs.root;
+ handle parent = null();
+ int cmp, last_cmp;
+
+ /* Search for node already in tree with same key. */
+ for (;;) {
+ if (h == null())
+ /* No node in tree with same key as new node. */
+ return null();
+ cmp = cmp_n_n(new_node, h);
+ if (cmp == 0)
+ /* Found the node to substitute new one for. */
+ break;
+ last_cmp = cmp;
+ parent = h;
+ h = cmp < 0 ? get_lt(h) : get_gt(h);
+ }
+
+ /* Copy tree housekeeping fields from node in tree to new node. */
+ set_lt(new_node, get_lt(h));
+ set_gt(new_node, get_gt(h));
+ set_bf(new_node, get_bf(h));
+
+ if (parent == null())
+ /* New node is also new root. */
+ abs.root = new_node;
+ else {
+ /* Make parent point to new node. */
+ if (last_cmp < 0)
+ set_lt(parent, new_node);
+ else
+ set_gt(parent, new_node);
+ }
+
+ return h;
+}
+
+}
+
+#endif
/*
- * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
*
*/
+#include "Platform.h"
+
#ifndef ALWAYS_INLINE
-#if COMPILER(GCC) && defined(NDEBUG)
-#define ALWAYS_INLINE inline __attribute__ ((__always_inline__))
+#if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
+#define ALWAYS_INLINE inline __attribute__((__always_inline__))
#elif COMPILER(MSVC) && defined(NDEBUG)
#define ALWAYS_INLINE __forceinline
#else
#ifndef NEVER_INLINE
#if COMPILER(GCC)
-#define NEVER_INLINE __attribute__ ((__noinline__))
+#define NEVER_INLINE __attribute__((__noinline__))
#else
#define NEVER_INLINE
#endif
#endif
+
+#ifndef UNLIKELY
+#if COMPILER(GCC)
+#define UNLIKELY(x) __builtin_expect((x), 0)
+#else
+#define UNLIKELY(x) (x)
+#endif
+#endif
+
+#ifndef LIKELY
+#if COMPILER(GCC)
+#define LIKELY(x) __builtin_expect((x), 1)
+#else
+#define LIKELY(x) (x)
+#endif
+#endif
+
+#ifndef NO_RETURN
+#if COMPILER(GCC)
+#define NO_RETURN __attribute((__noreturn__))
+#else
+#define NO_RETURN
+#endif
+#endif
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
*
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <CoreFoundation/CFString.h>
-#if COMPILER(MSVC)
+#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
#ifndef WINVER
#define WINVER 0x0500
#endif
--- /dev/null
+***************
+*** 63,88 ****
+ CFRelease(str);
+ CFRelease(cfFormat);
+ } else
+- #elif COMPILER(MSVC) && !PLATFORM(WIN_CE)
+- if (IsDebuggerPresent()) {
+- size_t size = 1024;
+-
+- do {
+- char* buffer = (char*)malloc(size);
+-
+- if (buffer == NULL)
+- break;
+-
+- if (_vsnprintf(buffer, size, format, args) != -1) {
+- OutputDebugStringA(buffer);
+- free(buffer);
+- break;
+- }
+-
+- free(buffer);
+- size *= 2;
+- } while (size > 1024);
+- }
+ vfprintf(stderr, format, args);
+ }
+
+--- 63,68 ----
+ CFRelease(str);
+ CFRelease(cfFormat);
+ } else
+ vfprintf(stderr, format, args);
+ }
+
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
*
#define WTF_PRETTY_FUNCTION __FUNCTION__
#endif
-// WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
-// emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
-// the attribute when being used from Objective-C code in case it decides to use %@.
+/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
+ emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include
+ the attribute when being used from Objective-C code in case it decides to use %@. */
#if COMPILER(GCC) && !defined(__OBJC__)
#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
#else
/* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */
#ifndef CRASH
-#define CRASH() *(int *)(uintptr_t)0xbbadbeef = 0
+#define CRASH() do { \
+ *(int *)(uintptr_t)0xbbadbeef = 0; \
+ ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
+} while(false)
#endif
/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */
+#if PLATFORM(WIN_CE)
+/* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
+#include <windows.h>
+#undef min
+#undef max
+#undef ERROR
+#endif
+
#if PLATFORM(WIN_OS)
/* FIXME: Change to use something other than ASSERT to avoid this conflict with win32. */
#undef ASSERT
#define ASSERT(assertion) ((void)0)
#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
#define ASSERT_NOT_REACHED() ((void)0)
+#define ASSERT_UNUSED(variable, assertion) ((void)variable)
#else
CRASH(); \
} \
while (0)
-#endif // COMPILER(MSVC7)
+#endif /* COMPILER(MSVC7) */
#define ASSERT_NOT_REACHED() do { \
WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
CRASH(); \
} while (0)
+#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
+
#endif
/* ASSERT_ARG */
#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
#endif
-#endif // WTF_Assertions_h
+#endif /* WTF_Assertions_h */
--- /dev/null
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ByteArray.h"
+
+namespace WTF {
+
+PassRefPtr<ByteArray> ByteArray::create(size_t size)
+{
+ unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)];
+ ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0);
+ return adoptRef(new (buffer) ByteArray(size));
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ByteArray_h
+#define ByteArray_h
+
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefCounted.h"
+
+namespace WTF {
+ class ByteArray : public RefCountedBase {
+ public:
+ unsigned length() const { return m_size; }
+
+ void set(unsigned index, double value)
+ {
+ if (index >= m_size)
+ return;
+ if (!(value > 0)) // Clamp NaN to 0
+ value = 0;
+ else if (value > 255)
+ value = 255;
+ m_data[index] = static_cast<unsigned char>(value + 0.5);
+ }
+
+ bool get(unsigned index, unsigned char& result) const
+ {
+ if (index >= m_size)
+ return false;
+ result = m_data[index];
+ return true;
+ }
+
+ unsigned char* data() { return m_data; }
+
+ void deref()
+ {
+ if (derefBase()) {
+ // We allocated with new unsigned char[] in create(),
+ // and then used placement new to construct the object.
+ this->~ByteArray();
+ delete[] reinterpret_cast<unsigned char*>(this);
+ }
+ }
+
+ static PassRefPtr<ByteArray> create(size_t size);
+
+ private:
+ ByteArray(size_t size)
+ : RefCountedBase(1)
+ , m_size(size)
+ {
+ }
+ size_t m_size;
+ unsigned char m_data[sizeof(size_t)];
+ };
+}
+
+#endif
--- /dev/null
+This is a copy of CONTRIBUTORS file for the Pthreads-win32 library, downloaded
+from http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/pthreads/CONTRIBUTORS?rev=1.32&cvsroot=pthreads-win32
+
+Included here to compliment the Pthreads-win32 license header in wtf/ThreadingWin.cpp file.
+WebKit is using derived sources of ThreadCondition code from Pthreads-win32.
+
+-------------------------------------------------------------------------------
+
+Contributors (in approximate order of appearance)
+
+[See also the ChangeLog file where individuals are
+attributed in log entries. Likewise in the FAQ file.]
+
+Ben Elliston bje at cygnus dot com
+ Initiated the project;
+ setup the project infrastructure (CVS, web page, etc.);
+ early prototype routines.
+Ross Johnson rpj at callisto dot canberra dot edu dot au
+ early prototype routines;
+ ongoing project coordination/maintenance;
+ implementation of spin locks and barriers;
+ various enhancements;
+ bug fixes;
+ documentation;
+ testsuite.
+Robert Colquhoun rjc at trump dot net dot au
+ Early bug fixes.
+John E. Bossom John dot Bossom at cognos dot com
+ Contributed substantial original working implementation;
+ bug fixes;
+ ongoing guidance and standards interpretation.
+Anders Norlander anorland at hem2 dot passagen dot se
+ Early enhancements and runtime checking for supported
+ Win32 routines.
+Tor Lillqvist tml at iki dot fi
+ General enhancements;
+ early bug fixes to condition variables.
+Scott Lightner scott at curriculum dot com
+ Bug fix.
+Kevin Ruland Kevin dot Ruland at anheuser-busch dot com
+ Various bug fixes.
+Mike Russo miker at eai dot com
+ Bug fix.
+Mark E. Armstrong avail at pacbell dot net
+ Bug fixes.
+Lorin Hochstein lmh at xiphos dot ca
+ general bug fixes; bug fixes to condition variables.
+Peter Slacik Peter dot Slacik at tatramed dot sk
+ Bug fixes.
+Mumit Khan khan at xraylith dot wisc dot edu
+ Fixes to work with Mingw32.
+Milan Gardian mg at tatramed dot sk
+ Bug fixes and reports/analyses of obscure problems.
+Aurelio Medina aureliom at crt dot com
+ First implementation of read-write locks.
+Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
+ Bug fix in condition variables.
+Tristan Savatier tristan at mpegtv dot com
+ WinCE port.
+Erik Hensema erik at hensema dot xs4all dot nl
+ Bug fixes.
+Rich Peters rpeters at micro-magic dot com
+Todd Owen towen at lucidcalm dot dropbear dot id dot au
+ Bug fixes to dll loading.
+Jason Nye jnye at nbnet dot nb dot ca
+ Implementation of async cancelation.
+Fred Forester fforest at eticomm dot net
+Kevin D. Clark kclark at cabletron dot com
+David Baggett dmb at itasoftware dot com
+ Bug fixes.
+Paul Redondo paul at matchvision dot com
+Scott McCaskill scott at 3dfx dot com
+ Bug fixes.
+Jef Gearhart jgearhart at tpssys dot com
+ Bug fix.
+Arthur Kantor akantor at bexusa dot com
+ Mutex enhancements.
+Steven Reddie smr at essemer dot com dot au
+ Bug fix.
+Alexander Terekhov TEREKHOV at de dot ibm dot com
+ Re-implemented and improved read-write locks;
+ (with Louis Thomas) re-implemented and improved
+ condition variables;
+ enhancements to semaphores;
+ enhancements to mutexes;
+ new mutex implementation in 'futex' style;
+ suggested a robust implementation of pthread_once
+ similar to that implemented by V.Kliathcko;
+ system clock change handling re CV timeouts;
+ bug fixes.
+Thomas Pfaff tpfaff at gmx dot net
+ Changes to make C version usable with C++ applications;
+ re-implemented mutex routines to avoid Win32 mutexes
+ and TryEnterCriticalSection;
+ procedure to fix Mingw32 thread-safety issues.
+Franco Bez franco dot bez at gmx dot de
+ procedure to fix Mingw32 thread-safety issues.
+Louis Thomas lthomas at arbitrade dot com
+ (with Alexander Terekhov) re-implemented and improved
+ condition variables.
+David Korn dgk at research dot att dot com
+ Ported to UWIN.
+Phil Frisbie, Jr. phil at hawksoft dot com
+ Bug fix.
+Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de
+ Bug fix.
+prionx at juno dot com prionx at juno dot com
+ Bug fixes.
+Max Woodbury mtew at cds dot duke dot edu
+ POSIX versioning conditionals;
+ reduced namespace pollution;
+ idea to separate routines to reduce statically
+ linked image sizes.
+Rob Fanner rfanner at stonethree dot com
+ Bug fix.
+Michael Johnson michaelj at maine dot rr dot com
+ Bug fix.
+Nicolas Barry boozai at yahoo dot com
+ Bug fixes.
+Piet van Bruggen pietvb at newbridges dot nl
+ Bug fix.
+Makoto Kato raven at oldskool dot jp
+ AMD64 port.
+Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr
+ Contributed the QueueUserAPCEx package which
+ makes preemptive async cancelation possible.
+Will Bryant will dot bryant at ecosm dot com
+ Borland compiler patch and makefile.
+Anuj Goyal anuj dot goyal at gmail dot com
+ Port to Digital Mars compiler.
+Gottlob Frege gottlobfrege at gmail dot com
+ re-implemented pthread_once (version 2)
+ (pthread_once cancellation added by rpj).
+Vladimir Kliatchko vladimir at kliatchko dot com
+ reimplemented pthread_once with the same form
+ as described by A.Terekhov (later version 2);
+ implementation of MCS (Mellor-Crummey/Scott) locks.
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CurrentTime.h"
+
+#if PLATFORM(MAC)
+#include <CoreFoundation/CFDate.h>
+#elif PLATFORM(GTK)
+#include <glib.h>
+#elif PLATFORM(WX)
+#include <wx/datetime.h>
+#elif PLATFORM(WIN_OS)
+// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
+#undef WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <time.h>
+#else // Posix systems relying on the gettimeofday()
+#include <sys/time.h>
+#endif
+
+namespace WTF {
+
+const double msPerSecond = 1000.0;
+
+#if PLATFORM(MAC)
+
+double currentTime()
+{
+ return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
+}
+
+#elif PLATFORM(GTK)
+
+// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
+// better accuracy compared with Windows implementation of g_get_current_time:
+// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
+// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
+double currentTime()
+{
+ GTimeVal now;
+ g_get_current_time(&now);
+ return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
+}
+
+#elif PLATFORM(WX)
+
+double currentTime()
+{
+ wxDateTime now = wxDateTime::UNow();
+ return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
+}
+
+#elif PLATFORM(WIN_OS)
+
+static LARGE_INTEGER qpcFrequency;
+static bool syncedTime;
+
+static double highResUpTime()
+{
+ // We use QPC, but only after sanity checking its result, due to bugs:
+ // http://support.microsoft.com/kb/274323
+ // http://support.microsoft.com/kb/895980
+ // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)."
+
+ static LARGE_INTEGER qpcLast;
+ static DWORD tickCountLast;
+ static bool inited;
+
+ LARGE_INTEGER qpc;
+ QueryPerformanceCounter(&qpc);
+ DWORD tickCount = GetTickCount();
+
+ if (inited) {
+ __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart;
+ __int64 tickCountElapsed;
+ if (tickCount >= tickCountLast)
+ tickCountElapsed = (tickCount - tickCountLast);
+ else {
+#if COMPILER(MINGW)
+ __int64 tickCountLarge = tickCount + 0x100000000ULL;
+#else
+ __int64 tickCountLarge = tickCount + 0x100000000I64;
+#endif
+ tickCountElapsed = tickCountLarge - tickCountLast;
+ }
+
+ // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms.
+ // (500ms value is from http://support.microsoft.com/kb/274323)
+ __int64 diff = tickCountElapsed - qpcElapsed;
+ if (diff > 500 || diff < -500)
+ syncedTime = false;
+ } else
+ inited = true;
+
+ qpcLast = qpc;
+ tickCountLast = tickCount;
+
+ return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);
+}
+
+static double lowResUTCTime()
+{
+#if PLATFORM(WIN_CE)
+ SYSTEMTIME systemTime;
+ GetSystemTime(&systemTime);
+ struct tm tmtime;
+ tmtime.tm_year = systemTime.wYear - 1900;
+ tmtime.tm_mon = systemTime.wMonth - 1;
+ tmtime.tm_mday = systemTime.wDay;
+ tmtime.tm_wday = systemTime.wDayOfWeek;
+ tmtime.tm_hour = systemTime.wHour;
+ tmtime.tm_min = systemTime.wMinute;
+ tmtime.tm_sec = systemTime.wSecond;
+ time_t timet = mktime(&tmtime);
+ return timet * msPerSecond + systemTime.wMilliseconds;
+#else // PLATFORM(WIN_CE)
+ struct _timeb timebuffer;
+ _ftime(&timebuffer);
+ return timebuffer.time * msPerSecond + timebuffer.millitm;
+#endif // PLATFORM(WIN_CE)
+}
+
+static bool qpcAvailable()
+{
+ static bool available;
+ static bool checked;
+
+ if (checked)
+ return available;
+
+ available = QueryPerformanceFrequency(&qpcFrequency);
+ checked = true;
+ return available;
+}
+
+double currentTime()
+{
+ // Use a combination of ftime and QueryPerformanceCounter.
+ // ftime returns the information we want, but doesn't have sufficient resolution.
+ // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals.
+ // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter
+ // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift.
+ static bool started;
+ static double syncLowResUTCTime;
+ static double syncHighResUpTime;
+ static double lastUTCTime;
+
+ double lowResTime = lowResUTCTime();
+
+ if (!qpcAvailable())
+ return lowResTime / 1000.0;
+
+ double highResTime = highResUpTime();
+
+ if (!syncedTime) {
+ timeBeginPeriod(1); // increase time resolution around low-res time getter
+ syncLowResUTCTime = lowResTime = lowResUTCTime();
+ timeEndPeriod(1); // restore time resolution
+ syncHighResUpTime = highResTime;
+ syncedTime = true;
+ }
+
+ double highResElapsed = highResTime - syncHighResUpTime;
+ double utc = syncLowResUTCTime + highResElapsed;
+
+ // force a clock re-sync if we've drifted
+ double lowResElapsed = lowResTime - syncLowResUTCTime;
+ const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy
+ if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec)
+ syncedTime = false;
+
+ // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur)
+ const double backwardTimeLimit = 2000.0;
+ if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit)
+ return lastUTCTime / 1000.0;
+ lastUTCTime = utc;
+ return utc / 1000.0;
+}
+
+#else // Other Posix systems rely on the gettimeofday().
+
+double currentTime()
+{
+ struct timeval now;
+ struct timezone zone;
+
+ gettimeofday(&now, &zone);
+ return static_cast<double>(now.tv_sec) + (double)(now.tv_usec / 1000000.0);
+}
+
+#endif
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CurrentTime_h
+#define CurrentTime_h
+
+namespace WTF {
+
+ // Returns the current system (UTC) time in seconds, starting January 1, 1970.
+ // Precision varies depending on a platform but usually is as good or better
+ // then a millisecond.
+ double currentTime();
+
+} // namespace WTF
+
+using WTF::currentTime;
+
+#endif // CurrentTime_h
+
}
}
+ template<typename T>
+ void deleteAllValues(const Deque<T>& collection)
+ {
+ typedef typename Deque<T>::const_iterator iterator;
+ iterator end = collection.end();
+ for (iterator it = collection.begin(); it != end; ++it)
+ delete *it;
+ }
+
template<typename T>
inline Deque<T>& Deque<T>::operator=(const Deque<T>& other)
{
#include "FastMalloc.h"
#include "Assertions.h"
-#if USE(MULTIPLE_THREADS)
+#if ENABLE(JSC_MULTIPLE_THREADS)
#include <pthread.h>
#endif
#define FORCE_SYSTEM_MALLOC 1
#endif
+#define TCMALLOC_TRACK_DECOMMITED_SPANS (HAVE(VIRTUALALLOC))
+
#ifndef NDEBUG
namespace WTF {
-#if USE(MULTIPLE_THREADS)
+#if ENABLE(JSC_MULTIPLE_THREADS)
static pthread_key_t isForbiddenKey;
static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
static void initializeIsForbiddenKey()
{
staticIsForbidden = false;
}
-#endif // USE(MULTIPLE_THREADS)
+#endif // ENABLE(JSC_MULTIPLE_THREADS)
} // namespace WTF
#endif // NDEBUG
#include <string.h>
namespace WTF {
-void *fastZeroedMalloc(size_t n)
+
+void* fastZeroedMalloc(size_t n)
{
- void *result = fastMalloc(n);
- if (!result)
- return 0;
+ void* result = fastMalloc(n);
memset(result, 0, n);
-#ifndef WTF_CHANGES
- MallocHook::InvokeNewHook(result, n);
-#endif
return result;
}
+void* tryFastZeroedMalloc(size_t n)
+{
+ void* result = tryFastMalloc(n);
+ if (!result)
+ return 0;
+ memset(result, 0, n);
+ return result;
}
+} // namespace WTF
+
#if FORCE_SYSTEM_MALLOC
#include <stdlib.h>
#if !PLATFORM(WIN_OS)
#include <pthread.h>
+#else
+ #include "windows.h"
#endif
namespace WTF {
-
-void *fastMalloc(size_t n)
+
+void* tryFastMalloc(size_t n)
{
ASSERT(!isForbidden());
return malloc(n);
}
-void *fastCalloc(size_t n_elements, size_t element_size)
+void* fastMalloc(size_t n)
+{
+ ASSERT(!isForbidden());
+ void* result = malloc(n);
+ if (!result)
+ CRASH();
+ return result;
+}
+
+void* tryFastCalloc(size_t n_elements, size_t element_size)
{
ASSERT(!isForbidden());
return calloc(n_elements, element_size);
}
+void* fastCalloc(size_t n_elements, size_t element_size)
+{
+ ASSERT(!isForbidden());
+ void* result = calloc(n_elements, element_size);
+ if (!result)
+ CRASH();
+ return result;
+}
+
void fastFree(void* p)
{
ASSERT(!isForbidden());
free(p);
}
-void *fastRealloc(void* p, size_t n)
+void* tryFastRealloc(void* p, size_t n)
{
ASSERT(!isForbidden());
return realloc(p, n);
}
+void* fastRealloc(void* p, size_t n)
+{
+ ASSERT(!isForbidden());
+ void* result = realloc(p, n);
+ if (!result)
+ CRASH();
+ return result;
+}
+
void releaseFastMallocFreeMemory() { }
+
+FastMallocStatistics fastMallocStatistics()
+{
+ FastMallocStatistics statistics = { 0, 0, 0, 0 };
+ return statistics;
+}
} // namespace WTF
#if PLATFORM(DARWIN)
#include "MallocZoneSupport.h"
+#include <wtf/HashSet.h>
#endif
#ifndef PRIuS
static void log(malloc_zone_t*, void*) { }
static void forceLock(malloc_zone_t*) { }
static void forceUnlock(malloc_zone_t*) { }
- static void statistics(malloc_zone_t*, malloc_statistics_t*) { }
+ static void statistics(malloc_zone_t*, malloc_statistics_t* stats) { memset(stats, 0, sizeof(malloc_statistics_t)); }
private:
FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*);
// Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
if (ClassIndex(0) < 0) {
MESSAGE("Invalid class index %d for size 0\n", ClassIndex(0));
- abort();
+ CRASH();
}
if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) {
MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize));
- abort();
+ CRASH();
}
// Compute the size classes we want to use
if (sc != kNumClasses) {
MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n",
sc, int(kNumClasses));
- abort();
+ CRASH();
}
// Initialize the mapping arrays
const size_t sc = SizeClass(size);
if (sc == 0) {
MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
- abort();
+ CRASH();
}
if (sc > 1 && size <= class_to_size[sc-1]) {
MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS
"\n", sc, size);
- abort();
+ CRASH();
}
if (sc >= kNumClasses) {
MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
- abort();
+ CRASH();
}
const size_t s = class_to_size[sc];
if (size > s) {
MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
- abort();
+ CRASH();
}
if (s == 0) {
MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
- abort();
+ CRASH();
}
}
if (free_avail_ < kAlignedSize) {
// Need more room
free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
- if (free_area_ == NULL) abort();
+ if (free_area_ == NULL) CRASH();
free_avail_ = kAllocIncrement;
}
result = free_area_;
Span* prev; // Used when in link list
void* objects; // Linked list of free objects
unsigned int free : 1; // Is the span free
+#ifndef NO_TCMALLOC_SAMPLES
unsigned int sample : 1; // Sampled object?
+#endif
unsigned int sizeclass : 8; // Size-class for small objects (or 0)
unsigned int refcount : 11; // Number of non-free objects
+ bool decommitted : 1;
#undef SPAN_HISTORY
#ifdef SPAN_HISTORY
#endif
};
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+#define ASSERT_SPAN_COMMITTED(span) ASSERT(!span->decommitted)
+#else
+#define ASSERT_SPAN_COMMITTED(span)
+#endif
+
#ifdef SPAN_HISTORY
void Event(Span* span, char op, int v = 0) {
span->history[span->nexthistory] = op;
return list->next == list;
}
-#ifndef WTF_CHANGES
static int DLL_Length(const Span* list) {
int result = 0;
for (Span* s = list->next; s != list; s = s->next) {
}
return result;
}
-#endif
#if 0 /* Not needed at the moment -- causes compiler warnings if not used */
static void DLL_Print(const char* label, const Span* list) {
typedef PackedCache<BITS, uint64_t> CacheType;
};
+#if defined(WTF_CHANGES)
+#if PLATFORM(X86_64)
+// On all known X86-64 platforms, the upper 16 bits are always unused and therefore
+// can be excluded from the PageMap key.
+// See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
+
+static const size_t kBitsUnusedOn64Bit = 16;
+#else
+static const size_t kBitsUnusedOn64Bit = 0;
+#endif
+
+// A three-level map for 64-bit machines
+template <> class MapSelector<64> {
+ public:
+ typedef TCMalloc_PageMap3<64 - kPageShift - kBitsUnusedOn64Bit> Type;
+ typedef PackedCache<64, uint64_t> CacheType;
+};
+#endif
+
// A two-level map for 32-bit machines
template <> class MapSelector<32> {
public:
- typedef TCMalloc_PageMap2<32-kPageShift> Type;
- typedef PackedCache<32-kPageShift, uint16_t> CacheType;
+ typedef TCMalloc_PageMap2<32 - kPageShift> Type;
+ typedef PackedCache<32 - kPageShift, uint16_t> CacheType;
};
// -------------------------------------------------------------------------
pagemap_.Ensure(p, 1);
return GetDescriptor(p);
}
+
+ size_t ReturnedBytes() const;
#endif
// Dump state to stderr
Span* result = ll->next;
Carve(result, n, released);
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ if (result->decommitted) {
+ TCMalloc_SystemCommit(reinterpret_cast<void*>(result->start << kPageShift), static_cast<size_t>(n << kPageShift));
+ result->decommitted = false;
+ }
+#endif
ASSERT(Check());
free_pages_ -= n;
return result;
}
Span* result = AllocLarge(n);
- if (result != NULL) return result;
+ if (result != NULL) {
+ ASSERT_SPAN_COMMITTED(result);
+ return result;
+ }
// Grow the heap and try again
if (!GrowHeap(n)) {
if (best != NULL) {
Carve(best, n, from_released);
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ if (best->decommitted) {
+ TCMalloc_SystemCommit(reinterpret_cast<void*>(best->start << kPageShift), static_cast<size_t>(n << kPageShift));
+ best->decommitted = false;
+ }
+#endif
ASSERT(Check());
free_pages_ -= n;
return best;
return leftover;
}
+#if !TCMALLOC_TRACK_DECOMMITED_SPANS
+static ALWAYS_INLINE void propagateDecommittedState(Span*, Span*) { }
+#else
+static ALWAYS_INLINE void propagateDecommittedState(Span* destination, Span* source)
+{
+ destination->decommitted = source->decommitted;
+}
+#endif
+
inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
ASSERT(n > 0);
DLL_Remove(span);
if (extra > 0) {
Span* leftover = NewSpan(span->start + n, extra);
leftover->free = 1;
+ propagateDecommittedState(leftover, span);
Event(leftover, 'S', extra);
RecordSpan(leftover);
}
}
+#if !TCMALLOC_TRACK_DECOMMITED_SPANS
+static ALWAYS_INLINE void mergeDecommittedStates(Span*, Span*) { }
+#else
+static ALWAYS_INLINE void mergeDecommittedStates(Span* destination, Span* other)
+{
+ if (other->decommitted)
+ destination->decommitted = true;
+}
+#endif
+
inline void TCMalloc_PageHeap::Delete(Span* span) {
ASSERT(Check());
ASSERT(!span->free);
ASSERT(GetDescriptor(span->start) == span);
ASSERT(GetDescriptor(span->start + span->length - 1) == span);
span->sizeclass = 0;
+#ifndef NO_TCMALLOC_SAMPLES
span->sample = 0;
+#endif
// Coalesce -- we guarantee that "p" != 0, so no bounds checking
// necessary. We do not bother resetting the stale pagemap
// Merge preceding span into this span
ASSERT(prev->start + prev->length == p);
const Length len = prev->length;
+ mergeDecommittedStates(span, prev);
DLL_Remove(prev);
DeleteSpan(prev);
span->start -= len;
// Merge next span into this span
ASSERT(next->start == p+n);
const Length len = next->length;
+ mergeDecommittedStates(span, next);
DLL_Remove(next);
DeleteSpan(next);
span->length += len;
DLL_Remove(s);
TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
static_cast<size_t>(s->length << kPageShift));
+#if TCMALLOC_TRACK_DECOMMITED_SPANS
+ s->decommitted = true;
+#endif
DLL_Prepend(&slist->returned, s);
scavenge_counter_ = std::max<size_t>(16UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay)));
pagemap_.set(span->start+i, span);
}
}
+
+#ifdef WTF_CHANGES
+size_t TCMalloc_PageHeap::ReturnedBytes() const {
+ size_t result = 0;
+ for (unsigned s = 0; s < kMaxPages; s++) {
+ const int r_length = DLL_Length(&free_[s].returned);
+ unsigned r_pages = s * r_length;
+ result += r_pages << kPageShift;
+ }
+
+ for (Span* s = large_.returned.next; s != &large_.returned; s = s->next)
+ result += s->length << kPageShift;
+ return result;
+}
+#endif
#ifndef WTF_CHANGES
static double PagesToMB(uint64_t pages) {
if (n < ask) {
// Try growing just "n" pages
ask = n;
- ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);;
+ ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
}
if (ptr == NULL) return false;
}
#ifdef WTF_CHANGES
template <class Finder, class Reader>
- void enumerateFreeObjects(Finder& finder, const Reader& reader)
+ void enumerateFreeObjects(Finder& finder, const Reader& reader, TCMalloc_Central_FreeList* remoteCentralFreeList)
{
for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0))
ASSERT(!span->objects);
ASSERT(!nonempty_.objects);
- for (Span* span = reader(nonempty_.next); span && span != &nonempty_; span = (span->next ? reader(span->next) : 0)) {
+ static const ptrdiff_t nonemptyOffset = reinterpret_cast<const char*>(&nonempty_) - reinterpret_cast<const char*>(this);
+
+ Span* remoteNonempty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + nonemptyOffset);
+ Span* remoteSpan = nonempty_.next;
+
+ for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->next, span = (span->next ? reader(span->next) : 0)) {
for (void* nextObject = span->objects; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
finder.visit(nextObject);
}
Span* span = nonempty_.next;
ASSERT(span->objects != NULL);
+ ASSERT_SPAN_COMMITTED(span);
span->refcount++;
void* result = span->objects;
span->objects = *(reinterpret_cast<void**>(result));
lock_.Lock();
return;
}
+ ASSERT_SPAN_COMMITTED(span);
ASSERT(span->length == npages);
// Cache sizeclass info eagerly. Locking is not necessary.
// (Instead of being eager, we could just replace any stale info
}
static inline void* SpanToMallocResult(Span *span) {
+ ASSERT_SPAN_COMMITTED(span);
pageheap->CacheSizeClass(span->start, 0);
return
CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
}
+#ifdef WTF_CHANGES
+template <bool crashOnFailure>
+#endif
static ALWAYS_INLINE void* do_malloc(size_t size) {
void* ret = NULL;
// size-appropriate freelist, afer replenishing it if it's empty.
ret = CheckedMallocResult(heap->Allocate(size));
}
- if (ret == NULL) errno = ENOMEM;
+ if (!ret) {
+#ifdef WTF_CHANGES
+ if (crashOnFailure) // This branch should be optimized out by the compiler.
+ CRASH();
+#else
+ errno = ENOMEM;
+#endif
+ }
return ret;
}
pageheap->CacheSizeClass(p, cl);
}
if (cl != 0) {
+#ifndef NO_TCMALLOC_SAMPLES
ASSERT(!pageheap->GetDescriptor(p)->sample);
+#endif
TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCacheIfPresent();
if (heap != NULL) {
heap->Deallocate(ptr, cl);
SpinLockHolder h(&pageheap_lock);
ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
ASSERT(span != NULL && span->start == p);
+#ifndef NO_TCMALLOC_SAMPLES
if (span->sample) {
DLL_Remove(span);
stacktrace_allocator.Delete(reinterpret_cast<StackTrace*>(span->objects));
span->objects = NULL;
}
+#endif
pageheap->Delete(span);
}
}
#ifndef WTF_CHANGES
extern "C"
+#else
+#define do_malloc do_malloc<crashOnFailure>
+
+template <bool crashOnFailure>
+void* malloc(size_t);
+
+void* fastMalloc(size_t size)
+{
+ return malloc<true>(size);
+}
+
+void* tryFastMalloc(size_t size)
+{
+ return malloc<false>(size);
+}
+
+template <bool crashOnFailure>
+ALWAYS_INLINE
#endif
void* malloc(size_t size) {
void* result = do_malloc(size);
#ifndef WTF_CHANGES
extern "C"
+#else
+template <bool crashOnFailure>
+void* calloc(size_t, size_t);
+
+void* fastCalloc(size_t n, size_t elem_size)
+{
+ return calloc<true>(n, elem_size);
+}
+
+void* tryFastCalloc(size_t n, size_t elem_size)
+{
+ return calloc<false>(n, elem_size);
+}
+
+template <bool crashOnFailure>
+ALWAYS_INLINE
#endif
void* calloc(size_t n, size_t elem_size) {
const size_t totalBytes = n * elem_size;
return result;
}
+// Since cfree isn't used anywhere, we don't compile it in.
+#ifndef WTF_CHANGES
#ifndef WTF_CHANGES
extern "C"
#endif
#endif
do_free(ptr);
}
+#endif
#ifndef WTF_CHANGES
extern "C"
+#else
+template <bool crashOnFailure>
+void* realloc(void*, size_t);
+
+void* fastRealloc(void* old_ptr, size_t new_size)
+{
+ return realloc<true>(old_ptr, new_size);
+}
+
+void* tryFastRealloc(void* old_ptr, size_t new_size)
+{
+ return realloc<false>(old_ptr, new_size);
+}
+
+template <bool crashOnFailure>
+ALWAYS_INLINE
#endif
void* realloc(void* old_ptr, size_t new_size) {
if (old_ptr == NULL) {
}
}
-#ifndef WTF_CHANGES
+#ifdef WTF_CHANGES
+#undef do_malloc
+#else
static SpinLock set_new_handler_lock = SPINLOCK_INITIALIZER;
#endif
#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
-#include <wtf/HashSet.h>
class FreeObjectFinder {
const RemoteMemoryReader& m_reader;
threadCache->enumerateFreeObjects(*this, m_reader);
}
- void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes)
+ void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes, TCMalloc_Central_FreeListPadded* remoteCentralFreeList)
{
for (unsigned i = 0; i < numSizes; i++)
- centralFreeList[i].enumerateFreeObjects(*this, m_reader);
+ centralFreeList[i].enumerateFreeObjects(*this, m_reader, remoteCentralFreeList + i);
}
};
FreeObjectFinder finder(memoryReader);
finder.findFreeObjects(threadHeaps);
- finder.findFreeObjects(centralCaches, kNumClasses);
+ finder.findFreeObjects(centralCaches, kNumClasses, mzone->m_centralCaches);
TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
#endif
+#if WTF_CHANGES
void releaseFastMallocFreeMemory()
{
// Flush free pages in the current thread cache back to the page heap.
- // Scavenging twice flushes everything
+ // Low watermark mechanism in Scavenge() prevents full return on the first pass.
+ // The second pass flushes everything.
if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) {
threadCache->Scavenge();
threadCache->Scavenge();
SpinLockHolder h(&pageheap_lock);
pageheap->ReleaseFreePages();
}
+
+FastMallocStatistics fastMallocStatistics()
+{
+ FastMallocStatistics statistics;
+ {
+ SpinLockHolder lockHolder(&pageheap_lock);
+ statistics.heapSize = static_cast<size_t>(pageheap->SystemBytes());
+ statistics.freeSizeInHeap = static_cast<size_t>(pageheap->FreeBytes());
+ statistics.returnedSize = pageheap->ReturnedBytes();
+ statistics.freeSizeInCaches = 0;
+ for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_)
+ statistics.freeSizeInCaches += threadCache->Size();
+ }
+ for (unsigned cl = 0; cl < kNumClasses; ++cl) {
+ const int length = central_cache[cl].length();
+ const int tc_length = central_cache[cl].tc_length();
+ statistics.freeSizeInCaches += ByteSizeForClass(cl) * (length + tc_length);
+ }
+ return statistics;
+}
-#if WTF_CHANGES
} // namespace WTF
#endif
namespace WTF {
- void *fastMalloc(size_t n);
- void *fastZeroedMalloc(size_t n);
- void *fastCalloc(size_t n_elements, size_t element_size);
+ // These functions call CRASH() if an allocation fails.
+ void* fastMalloc(size_t n);
+ void* fastZeroedMalloc(size_t n);
+ void* fastCalloc(size_t n_elements, size_t element_size);
+ void* fastRealloc(void* p, size_t n);
+
+ // These functions return NULL if an allocation fails.
+ void* tryFastMalloc(size_t n);
+ void* tryFastZeroedMalloc(size_t n);
+ void* tryFastCalloc(size_t n_elements, size_t element_size);
+ void* tryFastRealloc(void* p, size_t n);
+
void fastFree(void* p);
- void *fastRealloc(void* p, size_t n);
#ifndef NDEBUG
void fastMallocForbid();
#endif
void releaseFastMallocFreeMemory();
+
+ struct FastMallocStatistics {
+ size_t heapSize;
+ size_t freeSizeInHeap;
+ size_t freeSizeInCaches;
+ size_t returnedSize;
+ };
+ FastMallocStatistics fastMallocStatistics();
} // namespace WTF
using WTF::fastZeroedMalloc;
using WTF::fastCalloc;
using WTF::fastRealloc;
+using WTF::tryFastMalloc;
+using WTF::tryFastZeroedMalloc;
+using WTF::tryFastCalloc;
+using WTF::tryFastRealloc;
using WTF::fastFree;
#ifndef NDEBUG
--- /dev/null
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GOwnPtr.h"
+
+namespace WTF {
+
+template <> void freeOwnedGPtr<GError>(GError* ptr)
+{
+ if (ptr)
+ g_error_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GList>(GList* ptr)
+{
+ g_list_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GCond>(GCond* ptr)
+{
+ if (ptr)
+ g_cond_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GMutex>(GMutex* ptr)
+{
+ if (ptr)
+ g_mutex_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr)
+{
+ if (ptr)
+ g_pattern_spec_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GDir>(GDir* ptr)
+{
+ if (ptr)
+ g_dir_close(ptr);
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOwnPtr_h
+#define GOwnPtr_h
+
+#include <algorithm>
+#include <glib.h>
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+ template <typename T> inline void freeOwnedGPtr(T* ptr) { g_free(reinterpret_cast<void*>(ptr)); }
+ template<> void freeOwnedGPtr<GError>(GError*);
+ template<> void freeOwnedGPtr<GList>(GList*);
+ template<> void freeOwnedGPtr<GCond>(GCond*);
+ template<> void freeOwnedGPtr<GMutex>(GMutex*);
+ template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
+ template<> void freeOwnedGPtr<GDir>(GDir*);
+
+ template <typename T> class GOwnPtr : Noncopyable {
+ public:
+ explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
+ ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
+
+ T* get() const { return m_ptr; }
+ T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
+ T*& outPtr() { ASSERT(!m_ptr); return m_ptr; }
+
+ void set(T* ptr) { ASSERT(!ptr || m_ptr != ptr); freeOwnedGPtr(m_ptr); m_ptr = ptr; }
+ void clear() { freeOwnedGPtr(m_ptr); m_ptr = 0; }
+
+ T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+ T* operator->() const { ASSERT(m_ptr); return m_ptr; }
+
+ bool operator!() const { return !m_ptr; }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef T* GOwnPtr::*UnspecifiedBoolType;
+ operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; }
+
+ void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
+
+ private:
+ T* m_ptr;
+ };
+
+ template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b) { a.swap(b); }
+
+ template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b)
+ {
+ return a.get() == b;
+ }
+
+ template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b)
+ {
+ return a == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b)
+ {
+ return a.get() != b;
+ }
+
+ template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b)
+ {
+ return a != b.get();
+ }
+
+ template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p)
+ {
+ return p.get();
+ }
+
+} // namespace WTF
+
+using WTF::GOwnPtr;
+
+#endif // GOwnPtr_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include "Assertions.h"
#include "HashMap.h"
+#include "Vector.h"
namespace WTF {
{
m_impl.clear();
}
+
+ template<typename Value, typename HashFunctions, typename Traits, typename VectorType>
+ inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, VectorType& vector)
+ {
+ typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
+
+ vector.resize(collection.size());
+
+ iterator it = collection.begin();
+ iterator end = collection.end();
+ for (unsigned i = 0; it != end; ++it, ++i)
+ vector[i] = *it;
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, Vector<Value>& vector)
+ {
+ typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
+
+ vector.resize(collection.size());
+
+ iterator it = collection.begin();
+ iterator end = collection.end();
+ for (unsigned i = 0; it != end; ++it, ++i)
+ vector[i] = (*it).first;
+ }
+
} // namespace khtml
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
// integer hash function
+ // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+ inline unsigned intHash(uint8_t key8)
+ {
+ unsigned key = key8;
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+ // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+ inline unsigned intHash(uint16_t key16)
+ {
+ unsigned key = key16;
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
// Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
inline unsigned intHash(uint32_t key)
{
};
template<typename T> struct FloatHash {
- static unsigned hash(T key) { return intHash(*reinterpret_cast<typename IntTypes<sizeof(T)>::UnsignedType*>(&key)); }
+ static unsigned hash(T key)
+ {
+ union {
+ T key;
+ typename IntTypes<sizeof(T)>::UnsignedType bits;
+ } u;
+ u.key = key;
+ return intHash(u.bits);
+ }
static bool equal(T a, T b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
static bool equal(T a, T b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
- template<typename P> struct PtrHash<RefPtr<P> > {
- static unsigned hash(const RefPtr<P>& key) { return PtrHash<P*>::hash(key.get()); }
+ template<typename P> struct PtrHash<RefPtr<P> > : PtrHash<P*> {
+ using PtrHash<P*>::hash;
+ static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
+ using PtrHash<P*>::equal;
static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
- static const bool safeToCompareToEmptyOrDeleted = true;
+ static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
+ static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
};
// default hash function for each type
template<typename T> struct DefaultHash;
+ template<typename T, typename U> struct PairHash {
+ static unsigned hash(const std::pair<T, U>& p)
+ {
+ return intHash((static_cast<uint64_t>(DefaultHash<T>::Hash::hash(p.first)) << 32 | DefaultHash<U>::Hash::hash(p.second)));
+ }
+ static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
+ {
+ return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second);
+ }
+ static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted
+ && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
+ };
+
// make IntHash the default hash function for many integer types
+ template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
+ template<> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; };
template<> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; };
template<> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; };
template<> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; };
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; };
+#endif
+
template<> struct DefaultHash<float> { typedef FloatHash<float> Hash; };
template<> struct DefaultHash<double> { typedef FloatHash<double> Hash; };
template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
+ template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
+
+ // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+ static const unsigned stringHashingStartValue = 0x9e3779b9U;
+
} // namespace WTF
using WTF::DefaultHash;
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
private:
typedef KeyTraitsArg KeyTraits;
typedef MappedTraitsArg MappedTraits;
- typedef PairBaseHashTraits<KeyTraits, MappedTraits> ValueTraits;
+ typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
public:
typedef typename KeyTraits::TraitType KeyType;
private:
typedef HashArg HashFunctions;
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Traits KeyStorageTraits;
- typedef typename MappedTraits::StorageTraits MappedStorageTraits;
- typedef PairHashTraits<KeyStorageTraits, MappedStorageTraits> ValueStorageTraits;
-
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
-
- typedef HashTable<KeyStorageType, ValueStorageType, PairFirstExtractor<ValueStorageType>,
- StorageHashFunctions, ValueStorageTraits, KeyStorageTraits> HashTableType;
+ typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
+ HashFunctions, ValueTraits, KeyTraits> HashTableType;
public:
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashMap();
- HashMap(const HashMap&);
- HashMap& operator=(const HashMap&);
- ~HashMap();
-
void swap(HashMap&);
int size() const;
private:
pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
- void refAll();
- void derefAll();
HashTableType m_impl;
};
static const typename PairType::first_type& extract(const PairType& p) { return p.first; }
};
- template<bool canReplaceDeletedKey, typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator;
-
- template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator<true, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
+ template<typename ValueType, typename ValueTraits, typename HashFunctions>
+ struct HashMapTranslator {
typedef typename ValueType::first_type KeyType;
typedef typename ValueType::second_type MappedType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueTraits::FirstTraits KeyTraits;
- typedef typename ValueTraits::SecondTraits MappedTraits;
-
- static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
- static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
- static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped)
- {
- Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
- Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
- }
- };
- template<typename ValueType, typename ValueTraits, typename ValueStorageTraits, typename HashFunctions>
- struct HashMapTranslator<false, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> {
- typedef typename ValueType::first_type KeyType;
- typedef typename ValueType::second_type MappedType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- typedef typename ValueStorageTraits::FirstTraits KeyStorageTraits;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename ValueStorageTraits::SecondTraits MappedStorageTraits;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueTraits::FirstTraits KeyTraits;
- typedef typename ValueTraits::SecondTraits MappedTraits;
-
static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
- static bool equal(const KeyStorageType& a, const KeyType& b) { return HashFunctions::equal(*(KeyType*)&a, b); }
- static void translate(ValueStorageType& location, const KeyType& key, const MappedType& mapped)
+ static bool equal(const KeyType& a, const KeyType& b) { return HashFunctions::equal(a, b); }
+ static void translate(ValueType& location, const KeyType& key, const MappedType& mapped)
{
- if (location.first == KeyStorageTraits::deletedValue())
- location.first = KeyStorageTraits::emptyValue();
- Assigner<KeyTraits::needsRef, KeyType, KeyStorageType, KeyTraits>::assign(key, location.first);
- Assigner<MappedTraits::needsRef, MappedType, MappedStorageType, MappedTraits>::assign(mapped, location.second);
+ location.first = key;
+ location.second = mapped;
}
};
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<T, U, V, W, X>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<T, U, V, W, X>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::HashMap()
- {
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::HashMap(const HashMap& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>& HashMap<T, U, V, W, X>::operator=(const HashMap& other)
- {
- HashMap tmp(other);
- swap(tmp);
- return *this;
- }
-
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
{
m_impl.swap(other.m_impl);
}
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<T, U, V, W, X>::~HashMap()
- {
- derefAll();
- }
-
template<typename T, typename U, typename V, typename W, typename X>
inline int HashMap<T, U, V, W, X>::size() const
{
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.contains(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
{
- const bool canReplaceDeletedKey = !KeyTraits::needsDestruction || KeyStorageTraits::needsDestruction;
- typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> TranslatorType;
+ typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
}
HashMap<T, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
typename HashMap<T, U, V, W, MappedTraits>::MappedType
HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
}
template<typename T, typename U, typename V, typename W, typename X>
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, ValueStorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<T, U, V, W, X>::clear()
{
- derefAll();
m_impl.clear();
}
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(MappedType*)&it->second;
+ delete it->second;
}
template<typename T, typename U, typename V, typename W, typename X>
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(KeyType*)&it->first;
+ delete it->first;
}
template<typename T, typename U, typename V, typename W, typename X>
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
namespace WTF {
- template<typename T> struct IdentityExtractor;
-
template<typename Value, typename HashFunctions, typename Traits> class HashSet;
template<typename Value, typename HashFunctions, typename Traits>
void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
+ template<typename T> struct IdentityExtractor;
+
template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename TraitsArg = HashTraits<ValueArg> > class HashSet {
private:
typedef HashArg HashFunctions;
typedef TraitsArg ValueTraits;
- typedef typename HashKeyStorageTraits<HashFunctions, ValueTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, ValueTraits>::Traits StorageTraits;
- typedef typename StorageTraits::TraitType StorageType;
+ public:
+ typedef typename ValueTraits::TraitType ValueType;
- typedef HashTable<StorageType, StorageType, IdentityExtractor<StorageType>,
- StorageHashFunctions, StorageTraits, StorageTraits> HashTableType;
+ private:
+ typedef HashTable<ValueType, ValueType, IdentityExtractor<ValueType>,
+ HashFunctions, ValueTraits, ValueTraits> HashTableType;
public:
- typedef typename ValueTraits::TraitType ValueType;
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashSet();
- HashSet(const HashSet&);
- HashSet& operator=(const HashSet&);
- ~HashSet();
-
void swap(HashSet&);
int size() const;
const_iterator find(const ValueType&) const;
bool contains(const ValueType&) const;
- // the return value is a pair of an interator to the new value's location,
- // and a bool that is true if an new entry was added
+ // An alternate version of find() that finds the object by hashing and comparing
+ // with some other type, to avoid the cost of type conversion. HashTranslator
+ // must have the following function members:
+ // static unsigned hash(const T&);
+ // static bool equal(const ValueType&, const T&);
+ template<typename T, typename HashTranslator> iterator find(const T&);
+ template<typename T, typename HashTranslator> const_iterator find(const T&) const;
+ template<typename T, typename HashTranslator> bool contains(const T&) const;
+
+ // The return value is a pair of an interator to the new value's location,
+ // and a bool that is true if an new entry was added.
pair<iterator, bool> add(const ValueType&);
- // a special version of add() that finds the object by hashing and comparing
+ // An alternate version of add() that finds the object by hashing and comparing
// with some other type, to avoid the cost of type conversion if the object is already
- // in the table. HashTranslator should have the following methods:
+ // in the table. HashTranslator must have the following methods:
// static unsigned hash(const T&);
// static bool equal(const ValueType&, const T&);
// static translate(ValueType&, const T&, unsigned hashCode);
void clear();
private:
- void refAll();
- void derefAll();
-
friend void deleteAllValues<>(const HashSet&);
HashTableType m_impl;
static const T& extract(const T& t) { return t; }
};
- template<bool canReplaceDeletedValue, typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator;
-
- template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator<true, ValueType, ValueTraits, StorageTraits, HashFunctions> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
- static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const ValueType& key, const ValueType&)
- {
- Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
- }
- };
-
- template<typename ValueType, typename ValueTraits, typename StorageTraits, typename HashFunctions>
- struct HashSetTranslator<false, ValueType, ValueTraits, StorageTraits, HashFunctions> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
- static bool equal(const StorageType& a, const ValueType& b) { return HashFunctions::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const ValueType& key, const ValueType&)
- {
- if (location == StorageTraits::deletedValue())
- location = StorageTraits::emptyValue();
- Assigner<ValueTraits::needsRef, ValueType, StorageType, ValueTraits>::assign(key, location);
- }
- };
-
- template<bool canReplaceDeletedValue, typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter;
-
- template<typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter<true, ValueType, StorageTraits, T, Translator> {
- typedef typename StorageTraits::TraitType StorageType;
+ template<typename ValueType, typename ValueTraits, typename T, typename Translator>
+ struct HashSetTranslatorAdapter {
static unsigned hash(const T& key) { return Translator::hash(key); }
- static bool equal(const StorageType& a, const T& b) { return Translator::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const T& key, const T&, unsigned hashCode)
+ static bool equal(const ValueType& a, const T& b) { return Translator::equal(a, b); }
+ static void translate(ValueType& location, const T& key, const T&, unsigned hashCode)
{
- Translator::translate(*(ValueType*)&location, key, hashCode);
+ Translator::translate(location, key, hashCode);
}
};
- template<typename ValueType, typename StorageTraits, typename T, typename Translator>
- struct HashSetTranslatorAdapter<false, ValueType, StorageTraits, T, Translator> {
- typedef typename StorageTraits::TraitType StorageType;
- static unsigned hash(const T& key) { return Translator::hash(key); }
- static bool equal(const StorageType& a, const T& b) { return Translator::equal(*(const ValueType*)&a, b); }
- static void translate(StorageType& location, const T& key, const T&, unsigned hashCode)
- {
- if (location == StorageTraits::deletedValue())
- location = StorageTraits::emptyValue();
- Translator::translate(*(ValueType*)&location, key, hashCode);
- }
- };
-
- template<typename T, typename U, typename V>
- inline void HashSet<T, U, V>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V>
- inline void HashSet<T, U, V>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::HashSet()
- {
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::HashSet(const HashSet& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>& HashSet<T, U, V>::operator=(const HashSet& other)
- {
- HashSet tmp(other);
- swap(tmp);
- return *this;
- }
-
template<typename T, typename U, typename V>
inline void HashSet<T, U, V>::swap(HashSet& other)
{
m_impl.swap(other.m_impl);
}
- template<typename T, typename U, typename V>
- inline HashSet<T, U, V>::~HashSet()
- {
- derefAll();
- }
-
template<typename T, typename U, typename V>
inline int HashSet<T, U, V>::size() const
{
template<typename T, typename U, typename V>
inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::find(const ValueType& value)
{
- return m_impl.find(*(const StorageType*)&value);
+ return m_impl.find(value);
}
template<typename T, typename U, typename V>
inline typename HashSet<T, U, V>::const_iterator HashSet<T, U, V>::find(const ValueType& value) const
{
- return m_impl.find(*(const StorageType*)&value);
+ return m_impl.find(value);
}
template<typename T, typename U, typename V>
inline bool HashSet<T, U, V>::contains(const ValueType& value) const
{
- return m_impl.contains(*(const StorageType*)&value);
+ return m_impl.contains(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ typename HashSet<Value, HashFunctions, Traits>::iterator
+ inline HashSet<Value, HashFunctions, Traits>::find(const T& value)
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template find<T, Adapter>(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ typename HashSet<Value, HashFunctions, Traits>::const_iterator
+ inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template find<T, Adapter>(value);
+ }
+
+ template<typename Value, typename HashFunctions, typename Traits>
+ template<typename T, typename Translator>
+ inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const
+ {
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+ return m_impl.template contains<T, Adapter>(value);
}
template<typename T, typename U, typename V>
- pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType &value)
+ pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType& value)
{
- const bool canReplaceDeletedValue = !ValueTraits::needsDestruction || StorageTraits::needsDestruction;
- typedef HashSetTranslator<canReplaceDeletedValue, ValueType, ValueTraits, StorageTraits, HashFunctions> Translator;
- return m_impl.template add<ValueType, ValueType, Translator>(value, value);
+ return m_impl.add(value);
}
template<typename Value, typename HashFunctions, typename Traits>
pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
HashSet<Value, HashFunctions, Traits>::add(const T& value)
{
- const bool canReplaceDeletedValue = !ValueTraits::needsDestruction || StorageTraits::needsDestruction;
- typedef HashSetTranslatorAdapter<canReplaceDeletedValue, ValueType, StorageTraits, T, Translator> Adapter;
+ typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
return m_impl.template addPassingHashCode<T, T, Adapter>(value, value);
}
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, StorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
template<typename T, typename U, typename V>
inline void HashSet<T, U, V>::clear()
{
- derefAll();
m_impl.clear();
}
typedef typename HashTableType::const_iterator iterator;
iterator end = collection.end();
for (iterator it = collection.begin(); it != end; ++it)
- delete *(ValueType*)&*it;
+ delete *it;
}
template<typename T, typename U, typename V>
/*
- This file is part of the KDE libraries
-
- Copyright (C) 2005 Apple Computer
+ Copyright (C) 2005 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
static HashTableStats logger;
+static Mutex& hashTableStatsMutex()
+{
+ AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+ return mutex;
+}
+
HashTableStats::~HashTableStats()
{
- printf("\nkhtml::HashTable statistics\n\n");
+ // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown
+ // if any thread was killed while holding the mutex.
+ printf("\nWTF::HashTable statistics\n\n");
printf("%d accesses\n", numAccesses);
printf("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
printf("longest collision chain: %d\n", maxCollisions);
void HashTableStats::recordCollisionAtCount(int count)
{
+ MutexLocker lock(hashTableStatsMutex());
if (count > maxCollisions)
maxCollisions = count;
numCollisions++;
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Levin <levin@chromium.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include "FastMalloc.h"
#include "HashTraits.h"
#include <wtf/Assertions.h>
+#include <wtf/Threading.h>
namespace WTF {
struct HashTableStats {
~HashTableStats();
+ // All of the variables are accessed in ~HashTableStats when the static struct is destroyed.
+
+ // The following variables are all atomically incremented when modified.
static int numAccesses;
- static int numCollisions;
- static int collisionGraph[4096];
- static int maxCollisions;
static int numRehashes;
static int numRemoves;
static int numReinserts;
+
+ // The following variables are only modified in the recordCollisionAtCount method within a mutex.
+ static int maxCollisions;
+ static int numCollisions;
+ static int collisionGraph[4096];
+
static void recordCollisionAtCount(int count);
};
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
class HashTableConstIterator;
-#if CHECK_HASHTABLE_ITERATORS
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
-#else
+
+#if !CHECK_HASHTABLE_ITERATORS
+
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
inline void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
inline void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
+
#endif
typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
-
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
class HashTableConstIterator {
private:
#if CHECK_HASHTABLE_ITERATORS
public:
+ // Any modifications of the m_next or m_previous of an iterator that is in a linked list of a HashTable::m_iterator,
+ // should be guarded with m_table->m_mutex.
mutable const HashTableType* m_table;
mutable const_iterator* m_next;
mutable const_iterator* m_previous;
void clear();
static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); }
- static bool isDeletedBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::deletedValue(); }
+ static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); }
+ template<typename T, typename HashTranslator> ValueType* lookup(const T&);
#if CHECK_HASHTABLE_CONSISTENCY
void checkTableConsistency() const;
typedef pair<ValueType*, bool> LookupType;
typedef pair<LookupType, unsigned> FullLookupType;
- template<typename T, typename HashTranslator> ValueType* lookup(const T&);
LookupType lookupForWriting(const Key& key) { return lookupForWriting<Key, IdentityTranslatorType>(key); };
template<typename T, typename HashTranslator> FullLookupType fullLookupForWriting(const T&);
template<typename T, typename HashTranslator> LookupType lookupForWriting(const T&);
+ template<typename T, typename HashTranslator> void checkKey(const T&);
+
void removeAndInvalidateWithoutEntryConsistencyCheck(ValueType*);
void removeAndInvalidate(ValueType*);
void remove(ValueType*);
void reinsert(ValueType&);
static void initializeBucket(ValueType& bucket) { new (&bucket) ValueType(Traits::emptyValue()); }
- static void deleteBucket(ValueType& bucket) { assignDeleted<ValueType, Traits>(bucket); }
+ static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); }
FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
{ return FullLookupType(LookupType(position, found), hash); }
#if CHECK_HASHTABLE_ITERATORS
public:
+ // All access to m_iterators should be guarded with m_mutex.
mutable const_iterator* m_iterators;
+ mutable Mutex m_mutex;
#endif
};
return key;
}
+#if ASSERT_DISABLED
+
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
template<typename T, typename HashTranslator>
- inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
+ inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T&)
{
- ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
+ }
+
+#else
+
+ template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
+ template<typename T, typename HashTranslator>
+ void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T& key)
+ {
+ if (!HashFunctions::safeToCompareToEmptyOrDeleted)
+ return;
+ ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
+ ValueType deletedValue = Traits::emptyValue();
+ deletedValue.~ValueType();
+ Traits::constructDeletedValue(deletedValue);
+ ASSERT(!HashTranslator::equal(Extractor::extract(deletedValue), key));
+ new (&deletedValue) ValueType(Traits::emptyValue());
+ }
+
#endif
+ template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
+ template<typename T, typename HashTranslator>
+ inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
+ {
+ checkKey<T, HashTranslator>(key);
+
int k = 0;
int sizeMask = m_tableSizeMask;
ValueType* table = m_table;
unsigned h = HashTranslator::hash(key);
int i = h & sizeMask;
+ if (!table)
+ return 0;
+
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookupForWriting(const T& key)
{
ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
int k = 0;
ValueType* table = m_table;
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::fullLookupForWriting(const T& key)
{
ASSERT(m_table);
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
int k = 0;
ValueType* table = m_table;
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
template<typename T, typename Extra, typename HashTranslator>
inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra& extra)
{
-#if !ASSERT_DISABLED
- if (HashFunctions::safeToCompareToEmptyOrDeleted) {
- ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
- ASSERT(!HashTranslator::equal(KeyTraits::deletedValue(), key));
- }
-#endif
+ checkKey<T, HashTranslator>(key);
invalidateIterators();
int i = h & sizeMask;
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numAccesses;
+ atomicIncrement(&HashTableStats::numAccesses);
int probeCount = 0;
#endif
}
if (deletedEntry) {
+ initializeBucket(*deletedEntry);
entry = deletedEntry;
--m_deletedCount;
}
++m_keyCount;
if (shouldExpand()) {
- // FIXME: this makes an extra copy on expand. Probably not that bad since
+ // FIXME: This makes an extra copy on expand. Probably not that bad since
// expand is rare, but would be better to have a version of expand that can
- // follow a pivot entry and return the new position
+ // follow a pivot entry and return the new position.
KeyType enteredKey = Extractor::extract(*entry);
expand();
- return std::make_pair(find(enteredKey), true);
+ pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
+ ASSERT(p.first != end());
+ return p;
}
checkTableConsistency();
template<typename T, typename Extra, typename HashTranslator>
inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::addPassingHashCode(const T& key, const Extra& extra)
{
+ checkKey<T, HashTranslator>(key);
+
invalidateIterators();
if (!m_table)
FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key);
- ValueType *entry = lookupResult.first.first;
+ ValueType* entry = lookupResult.first.first;
bool found = lookupResult.first.second;
unsigned h = lookupResult.second;
if (found)
return std::make_pair(makeKnownGoodIterator(entry), false);
- if (isDeletedBucket(*entry))
+ if (isDeletedBucket(*entry)) {
+ initializeBucket(*entry);
--m_deletedCount;
+ }
HashTranslator::translate(*entry, key, extra, h);
++m_keyCount;
if (shouldExpand()) {
- // FIXME: this makes an extra copy on expand. Probably not that bad since
+ // FIXME: This makes an extra copy on expand. Probably not that bad since
// expand is rare, but would be better to have a version of expand that can
- // follow a pivot entry and return the new position
+ // follow a pivot entry and return the new position.
KeyType enteredKey = Extractor::extract(*entry);
expand();
- return std::make_pair(find(enteredKey), true);
+ pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
+ ASSERT(p.first != end());
+ return p;
}
checkTableConsistency();
ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numReinserts;
+ atomicIncrement(&HashTableStats::numReinserts);
#endif
- Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookupForWriting(Extractor::extract(entry)).first));
+ Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
if (!m_table)
return end();
- ValueType* entry = const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key);
+ ValueType* entry = const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
if (!entry)
return end();
if (!m_table)
return false;
- return const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key);
+ return const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos)
{
#if DUMP_HASHTABLE_STATS
- ++HashTableStats::numRemoves;
+ atomicIncrement(&HashTableStats::numRemoves);
#endif
deleteBucket(*pos);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
- Value *HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
+ Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
{
// would use a template member function with explicit specializations here, but
// gcc doesn't appear to support that
if (Traits::emptyValueIsZero)
- return static_cast<ValueType *>(fastZeroedMalloc(size * sizeof(ValueType)));
+ return static_cast<ValueType*>(fastZeroedMalloc(size * sizeof(ValueType)));
ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType)));
for (int i = 0; i < size; i++)
initializeBucket(result[i]);
}
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
- void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType *table, int size)
+ void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType* table, int size)
{
- if (Traits::needsDestruction)
- for (int i = 0; i < size; ++i)
- table[i].~ValueType();
+ if (Traits::needsDestruction) {
+ for (int i = 0; i < size; ++i) {
+ if (!isDeletedBucket(table[i]))
+ table[i].~ValueType();
+ }
+ }
fastFree(table);
}
checkTableConsistencyExceptSize();
int oldTableSize = m_tableSize;
- ValueType *oldTable = m_table;
+ ValueType* oldTable = m_table;
#if DUMP_HASHTABLE_STATS
if (oldTableSize != 0)
- ++HashTableStats::numRehashes;
+ atomicIncrement(&HashTableStats::numRehashes);
#endif
m_tableSize = newTableSize;
invalidateIterators();
other.invalidateIterators();
- ValueType *tmp_table = m_table;
+ ValueType* tmp_table = m_table;
m_table = other.m_table;
other.m_table = tmp_table;
int count = 0;
int deletedCount = 0;
for (int j = 0; j < m_tableSize; ++j) {
- ValueType *entry = m_table + j;
+ ValueType* entry = m_table + j;
if (isEmptyBucket(*entry))
continue;
template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators()
{
+ MutexLocker lock(m_mutex);
const_iterator* next;
for (const_iterator* p = m_iterators; p; p = next) {
next = p->m_next;
if (!table) {
it->m_next = 0;
} else {
+ MutexLocker lock(table->m_mutex);
ASSERT(table->m_iterators != it);
it->m_next = table->m_iterators;
table->m_iterators = it;
ASSERT(!it->m_next);
ASSERT(!it->m_previous);
} else {
+ MutexLocker lock(it->m_table->m_mutex);
if (it->m_next) {
ASSERT(it->m_next->m_previous == it);
it->m_next->m_previous = it->m_previous;
return a.m_impl != b.m_impl;
}
- // reference count manager
-
- template<typename ValueTraits, typename ValueStorageTraits> struct NeedsRef {
- static const bool value = ValueTraits::needsRef && !ValueStorageTraits::needsRef;
- };
- template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
- struct NeedsRef<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
- typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
- typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
- static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
- static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
- static const bool value = firstNeedsRef || secondNeedsRef;
- };
-
- template<bool needsRef, typename ValueTraits, typename ValueStorageTraits> struct RefCounterBase;
-
- template<typename ValueTraits, typename ValueStorageTraits>
- struct RefCounterBase<false, ValueTraits, ValueStorageTraits> {
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static void ref(const ValueStorageType&) { }
- static void deref(const ValueStorageType&) { }
- };
-
- template<typename ValueTraits, typename ValueStorageTraits>
- struct RefCounterBase<true, ValueTraits, ValueStorageTraits> {
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static void ref(const ValueStorageType& v) { ValueTraits::ref(v); }
- static void deref(const ValueStorageType& v) { ValueTraits::deref(v); }
- };
-
- template<typename ValueTraits, typename ValueStorageTraits> struct RefCounter {
- typedef typename ValueTraits::TraitType ValueType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static const bool needsRef = NeedsRef<ValueTraits, ValueStorageTraits>::value;
- typedef RefCounterBase<needsRef, ValueTraits, ValueStorageTraits> Base;
- static void ref(const ValueStorageType& v) { Base::ref(v); }
- static void deref(const ValueStorageType& v) { Base::deref(v); }
- };
-
- template<typename FirstTraits, typename SecondTraits, typename ValueStorageTraits>
- struct RefCounter<PairBaseHashTraits<FirstTraits, SecondTraits>, ValueStorageTraits> {
- typedef typename FirstTraits::TraitType FirstType;
- typedef typename SecondTraits::TraitType SecondType;
- typedef typename ValueStorageTraits::FirstTraits FirstStorageTraits;
- typedef typename ValueStorageTraits::SecondTraits SecondStorageTraits;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
- static const bool firstNeedsRef = NeedsRef<FirstTraits, FirstStorageTraits>::value;
- static const bool secondNeedsRef = NeedsRef<SecondTraits, SecondStorageTraits>::value;
- typedef RefCounterBase<firstNeedsRef, FirstTraits, FirstStorageTraits> FirstBase;
- typedef RefCounterBase<secondNeedsRef, SecondTraits, SecondStorageTraits> SecondBase;
- static void ref(const ValueStorageType& v) {
- FirstBase::ref(v.first);
- SecondBase::ref(v.second);
- }
- static void deref(const ValueStorageType& v) {
- FirstBase::deref(v.first);
- SecondBase::deref(v.second);
- }
- };
-
- template<bool needsRef, typename HashTableType, typename ValueTraits> struct HashTableRefCounterBase;
-
- template<typename HashTableType, typename ValueTraits>
- struct HashTableRefCounterBase<false, HashTableType, ValueTraits>
- {
- static void refAll(HashTableType&) { }
- static void derefAll(HashTableType&) { }
- };
-
- template<typename HashTableType, typename ValueTraits>
- struct HashTableRefCounterBase<true, HashTableType, ValueTraits>
- {
- typedef typename HashTableType::iterator iterator;
- typedef RefCounter<ValueTraits, typename HashTableType::ValueTraits> ValueRefCounter;
- static void refAll(HashTableType&);
- static void derefAll(HashTableType&);
- };
-
- template<typename HashTableType, typename ValueTraits>
- void HashTableRefCounterBase<true, HashTableType, ValueTraits>::refAll(HashTableType& table)
- {
- iterator end = table.end();
- for (iterator it = table.begin(); it != end; ++it)
- ValueRefCounter::ref(*it);
- }
-
- template<typename HashTableType, typename ValueTraits>
- void HashTableRefCounterBase<true, HashTableType, ValueTraits>::derefAll(HashTableType& table)
- {
- iterator end = table.end();
- for (iterator it = table.begin(); it != end; ++it)
- ValueRefCounter::deref(*it);
- }
-
- template<typename HashTableType, typename ValueTraits> struct HashTableRefCounter {
- static const bool needsRef = NeedsRef<ValueTraits, typename HashTableType::ValueTraits>::value;
- typedef HashTableRefCounterBase<needsRef, HashTableType, ValueTraits> Base;
- static void refAll(HashTableType& table) { Base::refAll(table); }
- static void derefAll(HashTableType& table) { Base::derefAll(table); }
- };
-
- // helper template for HashMap and HashSet.
- template<bool needsRef, typename FromType, typename ToType, typename FromTraits> struct Assigner;
-
- template<typename FromType, typename ToType, typename FromTraits> struct Assigner<false, FromType, ToType, FromTraits> {
- typedef union {
- FromType m_from;
- ToType m_to;
- } UnionType;
-
- static void assign(const FromType& from, ToType& to) { reinterpret_cast<UnionType*>(&to)->m_from = from; }
- };
-
- template<typename FromType, typename ToType, typename FromTraits> struct Assigner<true, FromType, ToType, FromTraits> {
- static void assign(const FromType& from, ToType& to)
- {
- ToType oldTo = to;
- memcpy(&to, &from, sizeof(FromType));
- FromTraits::ref(to);
- FromTraits::deref(oldTo);
- }
- };
-
- template<typename FromType, typename FromTraits> struct Assigner<false, FromType, FromType, FromTraits> {
- static void assign(const FromType& from, FromType& to) { to = from; }
- };
-
- template<typename FromType, typename FromTraits> struct Assigner<true, FromType, FromType, FromTraits> {
- static void assign(const FromType& from, FromType& to) { to = from; }
- };
-
} // namespace WTF
#include "HashIterators.h"
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
template<> struct IsInteger<long long> { static const bool value = true; };
template<> struct IsInteger<unsigned long long> { static const bool value = true; };
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<> struct IsInteger<wchar_t> { static const bool value = true; };
+#endif
+
COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true);
COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true);
COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true);
COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true);
COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+ COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true);
+#endif
+
COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false);
COMPILE_ASSERT(!IsInteger<const char* >::value, WTF_IsInteger_const_char_pointer_false);
COMPILE_ASSERT(!IsInteger<volatile char* >::value, WTF_IsInteger_volatile_char_pointer__false);
template<typename T> struct HashTraits;
template<bool isInteger, typename T> struct GenericHashTraitsBase;
- template<typename T> struct GenericHashTraitsBase<true, T> {
- typedef T TraitType;
- typedef HashTraits<typename IntTypes<sizeof(T)>::SignedType> StorageTraits;
- static const bool emptyValueIsZero = true;
- static const bool needsDestruction = false;
- };
+
template<typename T> struct GenericHashTraitsBase<false, T> {
- typedef T TraitType;
- typedef HashTraits<T> StorageTraits;
static const bool emptyValueIsZero = false;
static const bool needsDestruction = true;
};
+ // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned).
+ template<typename T> struct GenericHashTraitsBase<true, T> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static void constructDeletedValue(T& slot) { slot = static_cast<T>(-1); }
+ static bool isDeletedValue(T value) { return value == static_cast<T>(-1); }
+ };
+
template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> {
+ typedef T TraitType;
static T emptyValue() { return T(); }
- static const bool needsRef = false;
};
template<typename T> struct HashTraits : GenericHashTraits<T> { };
- // signed integer traits may not be appropriate for all uses since they disallow 0 and -1 as keys
- template<> struct HashTraits<signed char> : GenericHashTraits<int> {
- static signed char deletedValue() { return -1; }
- };
- template<> struct HashTraits<short> : GenericHashTraits<int> {
- static short deletedValue() { return -1; }
- };
- template<> struct HashTraits<int> : GenericHashTraits<int> {
- static int deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned int> : GenericHashTraits<unsigned int> {
- static unsigned int deletedValue() { return static_cast<unsigned int>(-1); }
- };
- template<> struct HashTraits<long> : GenericHashTraits<long> {
- static long deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned long> : GenericHashTraits<unsigned long> {
- static unsigned long deletedValue() { return static_cast<unsigned long>(-1); }
- };
- template<> struct HashTraits<long long> : GenericHashTraits<long long> {
- static long long deletedValue() { return -1; }
- };
- template<> struct HashTraits<unsigned long long> : GenericHashTraits<unsigned long long> {
- static unsigned long long deletedValue() { return static_cast<unsigned long long>(-1); }
- };
-
- template<typename T> struct FloatHashTraits {
- typedef T TraitType;
- typedef HashTraits<T> StorageTraits;
+ template<typename T> struct FloatHashTraits : GenericHashTraits<T> {
+ static const bool needsDestruction = false;
static T emptyValue() { return std::numeric_limits<T>::infinity(); }
- static T deletedValue() { return -std::numeric_limits<T>::infinity(); }
+ static void constructDeletedValue(T& slot) { slot = -std::numeric_limits<T>::infinity(); }
+ static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); }
+ };
+
+ template<> struct HashTraits<float> : FloatHashTraits<float> { };
+ template<> struct HashTraits<double> : FloatHashTraits<double> { };
+
+ // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1.
+ template<typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> {
static const bool emptyValueIsZero = false;
static const bool needsDestruction = false;
- static const bool needsRef = false;
- };
- template<> struct HashTraits<float> : FloatHashTraits<float> {
- };
- template<> struct HashTraits<double> : FloatHashTraits<double> {
+ static T emptyValue() { return std::numeric_limits<T>::max(); }
+ static void constructDeletedValue(T& slot) { slot = std::numeric_limits<T>::max() - 1; }
+ static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; }
};
template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> {
- typedef HashTraits<typename IntTypes<sizeof(P*)>::SignedType> StorageTraits;
static const bool emptyValueIsZero = true;
static const bool needsDestruction = false;
- static P* deletedValue() { return reinterpret_cast<P*>(-1); }
+ static void constructDeletedValue(P*& slot) { slot = reinterpret_cast<P*>(-1); }
+ static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
};
template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > {
- typedef HashTraits<typename IntTypes<sizeof(P*)>::SignedType> StorageTraits;
- typedef typename StorageTraits::TraitType StorageType;
static const bool emptyValueIsZero = true;
- static const bool needsRef = true;
-
- typedef union {
- P* m_p;
- StorageType m_s;
- } UnionType;
-
- static void ref(const StorageType& s)
- {
- if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p)
- const_cast<P*>(p)->ref();
- }
- static void deref(const StorageType& s)
- {
- if (const P* p = reinterpret_cast<const UnionType*>(&s)->m_p)
- const_cast<P*>(p)->deref();
- }
- };
-
- // template to set deleted values
-
- template<typename Traits> struct DeletedValueAssigner {
- static void assignDeletedValue(typename Traits::TraitType& location) { location = Traits::deletedValue(); }
+ static void constructDeletedValue(RefPtr<P>& slot) { new (&slot) RefPtr<P>(HashTableDeletedValue); }
+ static bool isDeletedValue(const RefPtr<P>& value) { return value.isHashTableDeletedValue(); }
};
- template<typename T, typename Traits> inline void assignDeleted(T& location)
- {
- DeletedValueAssigner<Traits>::assignDeletedValue(location);
- }
-
// special traits for pairs, helpful for their use in HashMap implementation
- template<typename FirstTraits, typename SecondTraits> struct PairHashTraits;
-
template<typename FirstTraitsArg, typename SecondTraitsArg>
- struct PairBaseHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > {
+ struct PairHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > {
typedef FirstTraitsArg FirstTraits;
typedef SecondTraitsArg SecondTraits;
typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
- typedef PairHashTraits<typename FirstTraits::StorageTraits, typename SecondTraits::StorageTraits> StorageTraits;
-
static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-
- static TraitType emptyValue()
- {
- return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue());
- }
- };
-
- template<typename FirstTraits, typename SecondTraits>
- struct PairHashTraits : PairBaseHashTraits<FirstTraits, SecondTraits> {
- typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
+ static TraitType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
- static TraitType deletedValue()
- {
- return TraitType(FirstTraits::deletedValue(), SecondTraits::emptyValue());
- }
-
- static void assignDeletedValue(TraitType& location)
- {
- assignDeleted<typename FirstTraits::TraitType, FirstTraits>(location.first);
- location.second = SecondTraits::emptyValue();
- }
+ static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
+ static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
template<typename First, typename Second>
struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { };
- template<typename FirstTraits, typename SecondTraits>
- struct DeletedValueAssigner<PairHashTraits<FirstTraits, SecondTraits> >
- {
- static void assignDeletedValue(pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType>& location)
- {
- PairHashTraits<FirstTraits, SecondTraits>::assignDeletedValue(location);
- }
- };
-
- template<typename First, typename Second>
- struct DeletedValueAssigner<HashTraits<pair<First, Second> > >
- {
- static void assignDeletedValue(pair<First, Second>& location)
- {
- HashTraits<pair<First, Second> >::assignDeletedValue(location);
- }
- };
-
- // hash functions and traits that are equivalent (for code sharing)
-
- template<typename HashArg, typename TraitsArg> struct HashKeyStorageTraits {
- typedef HashArg Hash;
- typedef TraitsArg Traits;
- };
- template<typename P> struct HashKeyStorageTraits<PtrHash<P*>, HashTraits<P*> > {
- typedef typename IntTypes<sizeof(P*)>::SignedType IntType;
- typedef IntHash<IntType> Hash;
- typedef HashTraits<IntType> Traits;
- };
- template<typename P> struct HashKeyStorageTraits<PtrHash<RefPtr<P> >, HashTraits<RefPtr<P> > > {
- typedef typename IntTypes<sizeof(P*)>::SignedType IntType;
- typedef IntHash<IntType> Hash;
- typedef HashTraits<IntType> Traits;
- };
-
} // namespace WTF
using WTF::HashTraits;
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
// order - iterating it will always give back values in the order
// in which they are added.
- // In theory it would be possible to add prepend, insertAfter, insertBefore,
+ // In theory it would be possible to add prepend, insertAfter
// and an append that moves the element to the end even if already present,
// but unclear yet if these are needed.
typedef ListHashSetNodeHashFunctions<ValueArg, HashArg> NodeHash;
typedef HashTable<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplType;
+ typedef HashTableIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator;
+ typedef HashTableConstIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator;
typedef HashArg HashFunctions;
const_iterator find(const ValueType&) const;
bool contains(const ValueType&) const;
- // the return value is a pair of an interator to the new value's location,
+ // the return value is a pair of an iterator to the new value's location,
// and a bool that is true if an new entry was added
pair<iterator, bool> add(const ValueType&);
+ pair<iterator, bool> insertBefore(const ValueType& beforeValue, const ValueType& newValue);
+ pair<iterator, bool> insertBefore(iterator it, const ValueType&);
+
void remove(const ValueType&);
void remove(iterator);
void clear();
private:
void unlinkAndDelete(Node*);
void appendNode(Node*);
+ void insertNodeBefore(Node* beforeNode, Node* newNode);
void deleteAllNodes();
iterator makeIterator(Node*);
const_iterator makeConstIterator(Node*) const;
const_iterator& operator--()
{
ASSERT(m_position != m_set->m_head);
- m_position = m_position->m_prev;
+ if (!m_position)
+ m_position = m_set->m_tail;
+ else
+ m_position = m_position->m_prev;
return *this;
}
std::swap(m_head, other.m_head);
std::swap(m_tail, other.m_tail);
m_allocator.swap(other.m_allocator);
- return *this;
}
template<typename T, typename U>
inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::find(const ValueType& value)
{
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
- typename ImplType::iterator it = m_impl.template find<ValueType, Translator>(value);
+ ImplTypeIterator it = m_impl.template find<ValueType, Translator>(value);
if (it == m_impl.end())
return end();
return makeIterator(*it);
inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::find(const ValueType& value) const
{
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
- typename ImplType::const_iterator it = m_impl.template find<ValueType, Translator>(value);
+ ImplTypeConstIterator it = m_impl.template find<ValueType, Translator>(value);
if (it == m_impl.end())
return end();
return makeConstIterator(*it);
return std::make_pair(makeIterator(*result.first), result.second);
}
+ template<typename T, typename U>
+ pair<typename ListHashSet<T, U>::iterator, bool> ListHashSet<T, U>::insertBefore(iterator it, const ValueType& newValue)
+ {
+ typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
+ pair<typename ImplType::iterator, bool> result = m_impl.template add<ValueType, NodeAllocator*, Translator>(newValue, m_allocator.get());
+ if (result.second)
+ insertNodeBefore(it.node(), *result.first);
+ return std::make_pair(makeIterator(*result.first), result.second);
+
+ }
+
+ template<typename T, typename U>
+ pair<typename ListHashSet<T, U>::iterator, bool> ListHashSet<T, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue)
+ {
+ return insertBefore(find(beforeValue), newValue);
+ }
+
template<typename T, typename U>
inline void ListHashSet<T, U>::remove(iterator it)
{
m_tail = node;
}
+ template<typename T, typename U>
+ void ListHashSet<T, U>::insertNodeBefore(Node* beforeNode, Node* newNode)
+ {
+ if (!beforeNode)
+ return appendNode(newNode);
+
+ newNode->m_next = beforeNode;
+ newNode->m_prev = beforeNode->m_prev;
+ if (beforeNode->m_prev)
+ beforeNode->m_prev->m_next = newNode;
+ beforeNode->m_prev = newNode;
+
+ if (!newNode->m_prev)
+ m_head = newNode;
+ }
+
template<typename T, typename U>
void ListHashSet<T, U>::deleteAllNodes()
{
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
// see comment in PassRefPtr.h for why this takes const reference
template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
- ~ListRefPtr() {
+ ~ListRefPtr()
+ {
RefPtr<T> reaper = this->release();
- while (reaper && reaper->refcount() == 1)
+ while (reaper && reaper->hasOneRef())
reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
}
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef Locker_h
+#define Locker_h
+
+#include <wtf/Noncopyable.h>
+
+namespace WTF {
+
+template <typename T> class Locker : Noncopyable {
+public:
+ Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
+ ~Locker() { m_lockable.unlock(); }
+private:
+ T& m_lockable;
+};
+
+}
+
+using WTF::Locker;
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "StdLibExtras.h"
+#include "Threading.h"
+#include "Vector.h"
+
+namespace WTF {
+
+struct FunctionWithContext {
+ MainThreadFunction* function;
+ void* context;
+ ThreadCondition* syncFlag;
+
+ FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
+ : function(function)
+ , context(context)
+ , syncFlag(syncFlag)
+ {
+ }
+};
+
+typedef Vector<FunctionWithContext> FunctionQueue;
+
+static bool callbacksPaused; // This global variable is only accessed from main thread.
+
+Mutex& mainThreadFunctionQueueMutex()
+{
+ DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
+ return staticMutex;
+}
+
+static FunctionQueue& functionQueue()
+{
+ DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ());
+ return staticFunctionQueue;
+}
+
+#if !PLATFORM(WIN)
+void initializeMainThread()
+{
+ mainThreadFunctionQueueMutex();
+}
+#endif
+
+void dispatchFunctionsFromMainThread()
+{
+ ASSERT(isMainThread());
+
+ if (callbacksPaused)
+ return;
+
+ FunctionQueue queueCopy;
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ queueCopy.swap(functionQueue());
+ }
+
+ for (unsigned i = 0; i < queueCopy.size(); ++i) {
+ FunctionWithContext& invocation = queueCopy[i];
+ invocation.function(invocation.context);
+ if (invocation.syncFlag)
+ invocation.syncFlag->signal();
+ }
+}
+
+void callOnMainThread(MainThreadFunction* function, void* context)
+{
+ ASSERT(function);
+
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ functionQueue().append(FunctionWithContext(function, context));
+ }
+
+ scheduleDispatchFunctionsOnMainThread();
+}
+
+void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
+{
+ ASSERT(function);
+
+ if (isMainThread()) {
+ function(context);
+ return;
+ }
+
+ ThreadCondition syncFlag;
+ Mutex conditionMutex;
+
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ functionQueue().append(FunctionWithContext(function, context, &syncFlag));
+ conditionMutex.lock();
+ }
+
+ scheduleDispatchFunctionsOnMainThread();
+ syncFlag.wait(conditionMutex);
+}
+
+void setMainThreadCallbacksPaused(bool paused)
+{
+ ASSERT(isMainThread());
+
+ if (callbacksPaused == paused)
+ return;
+
+ callbacksPaused = paused;
+
+ if (!callbacksPaused)
+ scheduleDispatchFunctionsOnMainThread();
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MainThread_h
+#define MainThread_h
+
+namespace WTF {
+
+class Mutex;
+
+typedef void MainThreadFunction(void*);
+
+void callOnMainThread(MainThreadFunction*, void* context);
+void callOnMainThreadAndWait(MainThreadFunction*, void* context);
+
+void setMainThreadCallbacksPaused(bool paused);
+
+// Must be called from the main thread (Darwin is an exception to this rule).
+void initializeMainThread();
+
+// These functions are internal to the callOnMainThread implementation.
+void dispatchFunctionsFromMainThread();
+void scheduleDispatchFunctionsOnMainThread();
+Mutex& mainThreadFunctionQueueMutex();
+
+} // namespace WTF
+
+using WTF::callOnMainThread;
+using WTF::setMainThreadCallbacksPaused;
+
+#endif // MainThread_h
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include <math.h>
#include <stdlib.h>
-#include <time.h>
-#if PLATFORM(SOLARIS) && COMPILER(GCC)
+#if PLATFORM(SOLARIS)
#include <ieeefp.h>
#endif
-#if COMPILER(MSVC)
+#if PLATFORM(OPENBSD)
+#include <sys/types.h>
+#include <machine/ieee.h>
+#endif
+#if COMPILER(MSVC)
+#if PLATFORM(WIN_CE)
+#include <stdlib.h>
+#else
#include <xmath.h>
+#endif
#include <limits>
#if HAVE(FLOAT_H)
const float piOverFourFloat = static_cast<float>(M_PI_4);
#endif
-#if PLATFORM(SOLARIS) && COMPILER(GCC)
+#if PLATFORM(DARWIN)
+
+// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
+inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
+
+#define ceil(x) wtf_ceil(x)
+
+#endif
+
+#if PLATFORM(SOLARIS)
#ifndef isfinite
inline bool isfinite(double x) { return finite(x) && !isnand(x); }
#endif
-#if COMPILER(MSVC)
+#if PLATFORM(OPENBSD)
+
+#ifndef isfinite
+inline bool isfinite(double x) { return finite(x); }
+#endif
+#ifndef signbit
+inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
+#endif
+
+#endif
+
+#if COMPILER(MSVC) || COMPILER(RVCT)
-inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
-inline bool isnan(double num) { return !!_isnan(num); }
inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); }
inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); }
inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); }
inline float roundf(float num) { return num > 0 ? floorf(num + 0.5f) : ceilf(num - 0.5f); }
-inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); }
+#endif
+
+#if COMPILER(MSVC)
+
+inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
+inline bool isnan(double num) { return !!_isnan(num); }
+inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
+
inline double nextafter(double x, double y) { return _nextafter(x, y); }
inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
inline double wtf_atan2(double x, double y)
{
- static double posInf = std::numeric_limits<double>::infinity();
- static double negInf = -std::numeric_limits<double>::infinity();
- static double nan = std::numeric_limits<double>::quiet_NaN();
+ double posInf = std::numeric_limits<double>::infinity();
+ double negInf = -std::numeric_limits<double>::infinity();
+ double nan = std::numeric_limits<double>::quiet_NaN();
double result = nan;
#define fmod(x, y) wtf_fmod(x, y)
#define pow(x, y) wtf_pow(x, y)
-#if defined(_CRT_RAND_S)
-// Initializes the random number generator.
-inline void wtf_random_init()
-{
- // No need to initialize for rand_s.
-}
-
-// Returns a pseudo-random number in the range [0, 1).
-inline double wtf_random()
-{
- unsigned u;
- rand_s(&u);
-
- return static_cast<double>(u) / (static_cast<double>(UINT_MAX) + 1.0);
-}
-#endif // _CRT_RAND_S
-
#endif // COMPILER(MSVC)
-#if !COMPILER(MSVC) || !defined(_CRT_RAND_S)
-
-// Initializes the random number generator.
-inline void wtf_random_init()
-{
- srand(static_cast<unsigned>(time(0)));
-}
-
-// Returns a pseudo-random number in the range [0, 1).
-inline double wtf_random()
-{
- return static_cast<double>(rand()) / (static_cast<double>(RAND_MAX) + 1.0);
-}
-
-#endif // #if COMPILER(MSVC)
-
inline double deg2rad(double d) { return d * piDouble / 180.0; }
inline double rad2deg(double r) { return r * 180.0 / piDouble; }
inline double deg2grad(double d) { return d * 400.0 / 360.0; }
inline double grad2deg(double g) { return g * 360.0 / 400.0; }
+inline double turn2deg(double t) { return t * 360.0; }
+inline double deg2turn(double d) { return d / 360.0; }
inline double rad2grad(double r) { return r * 200.0 / piDouble; }
inline double grad2rad(double g) { return g * piDouble / 200.0; }
inline float rad2deg(float r) { return r * 180.0f / piFloat; }
inline float deg2grad(float d) { return d * 400.0f / 360.0f; }
inline float grad2deg(float g) { return g * 360.0f / 400.0f; }
+inline float turn2deg(float t) { return t * 360.0f; }
+inline float deg2turn(float d) { return d / 360.0f; }
inline float rad2grad(float r) { return r * 200.0f / piFloat; }
inline float grad2rad(float g) { return g * piFloat / 200.0f; }
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MessageQueue_h
+#define MessageQueue_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Deque.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Threading.h>
+
+namespace WTF {
+
+ enum MessageQueueWaitResult {
+ MessageQueueTerminated, // Queue was destroyed while waiting for message.
+ MessageQueueTimeout, // Timeout was specified and it expired.
+ MessageQueueMessageReceived, // A message was successfully received and returned.
+ };
+
+ template<typename DataType>
+ class MessageQueue : Noncopyable {
+ public:
+ MessageQueue() : m_killed(false) {}
+
+ void append(const DataType&);
+ void prepend(const DataType&);
+ bool waitForMessage(DataType&);
+ MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
+ void kill();
+
+ bool tryGetMessage(DataType&);
+ bool killed() const;
+
+ // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
+ bool isEmpty();
+
+ private:
+ mutable Mutex m_mutex;
+ ThreadCondition m_condition;
+ Deque<DataType> m_queue;
+ bool m_killed;
+ };
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::append(const DataType& message)
+ {
+ MutexLocker lock(m_mutex);
+ m_queue.append(message);
+ m_condition.signal();
+ }
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::prepend(const DataType& message)
+ {
+ MutexLocker lock(m_mutex);
+ m_queue.prepend(message);
+ m_condition.signal();
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
+ {
+ MutexLocker lock(m_mutex);
+
+ while (!m_killed && m_queue.isEmpty())
+ m_condition.wait(m_mutex);
+
+ if (m_killed)
+ return false;
+
+ ASSERT(!m_queue.isEmpty());
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return true;
+ }
+
+ template<typename DataType>
+ inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
+ {
+ MutexLocker lock(m_mutex);
+ bool timedOut = false;
+
+ while (!m_killed && !timedOut && m_queue.isEmpty())
+ timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
+
+ if (m_killed)
+ return MessageQueueTerminated;
+
+ if (timedOut)
+ return MessageQueueTimeout;
+
+ ASSERT(!m_queue.isEmpty());
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return MessageQueueMessageReceived;
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
+ {
+ MutexLocker lock(m_mutex);
+ if (m_killed)
+ return false;
+ if (m_queue.isEmpty())
+ return false;
+
+ result = m_queue.first();
+ m_queue.removeFirst();
+ return true;
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::isEmpty()
+ {
+ MutexLocker lock(m_mutex);
+ if (m_killed)
+ return true;
+ return m_queue.isEmpty();
+ }
+
+ template<typename DataType>
+ inline void MessageQueue<DataType>::kill()
+ {
+ MutexLocker lock(m_mutex);
+ m_killed = true;
+ m_condition.broadcast();
+ }
+
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::killed() const
+ {
+ MutexLocker lock(m_mutex);
+ return m_killed;
+ }
+}
+
+using WTF::MessageQueue;
+// MessageQueueWaitResult enum and all its values.
+using WTF::MessageQueueWaitResult;
+using WTF::MessageQueueTerminated;
+using WTF::MessageQueueTimeout;
+using WTF::MessageQueueMessageReceived;
+
+#endif // MessageQueue_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NotFound_h
+#define NotFound_h
+
+namespace WTF {
+
+ const size_t notFound = static_cast<size_t>(-1);
+
+} // namespace WTF
+
+#endif // NotFound_h
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
#define WTF_OwnPtr_h
#include <algorithm>
+#include <memory>
#include <wtf/Assertions.h>
#include <wtf/Noncopyable.h>
typedef ValueType* PtrType;
explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+ OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { }
~OwnPtr() { deleteOwnedPtr(m_ptr); }
PtrType get() const { return m_ptr; }
PtrType release() { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
+ // FIXME: This should be renamed to adopt.
void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; }
+
+ void adopt(std::auto_ptr<ValueType> autoPtr) { ASSERT(!autoPtr.get() || m_ptr != autoPtr.get()); deleteOwnedPtr(m_ptr); m_ptr = autoPtr.release(); }
+
void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; }
ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
*
bool operator!() const { return !m_ptr; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+ operator bool() const { return m_ptr; }
+#else
typedef T* PassRefPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
-
+#endif
PassRefPtr& operator=(T*);
PassRefPtr& operator=(const PassRefPtr&);
template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WTF_Platform_h
/* be used regardless of operating environment */
#ifdef __APPLE__
#define WTF_PLATFORM_DARWIN 1
+#include <TargetConditionals.h>
#endif
/* PLATFORM(WIN_OS) */
#define WTF_PLATFORM_WIN_OS 1
#endif
+/* PLATFORM(WIN_CE) */
+/* Operating system level dependencies for Windows CE that should be used */
+/* regardless of operating environment */
+/* Note that for this platform PLATFORM(WIN_OS) is also defined. */
+#if defined(_WIN32_WCE)
+#define WTF_PLATFORM_WIN_CE 1
+#endif
+
/* PLATFORM(FREEBSD) */
/* Operating system level dependencies for FreeBSD-like systems that */
/* should be used regardless of operating environment */
#define WTF_PLATFORM_FREEBSD 1
#endif
+/* PLATFORM(OPENBSD) */
+/* Operating system level dependencies for OpenBSD systems that */
+/* should be used regardless of operating environment */
+#ifdef __OpenBSD__
+#define WTF_PLATFORM_OPENBSD 1
+#endif
+
/* PLATFORM(SOLARIS) */
/* Operating system level dependencies for Solaris that should be used */
/* regardless of operating environment */
#define WTF_PLATFORM_SOLARIS 1
#endif
+#if defined (__S60__) || defined (__SYMBIAN32__)
+/* we are cross-compiling, it is not really windows */
+#undef WTF_PLATFORM_WIN_OS
+#undef WTF_PLATFORM_WIN
+#undef WTF_PLATFORM_CAIRO
+#define WTF_PLATFORM_S60 1
+#define WTF_PLATFORM_SYMBIAN 1
+#endif
+
+
+/* PLATFORM(NETBSD) */
+/* Operating system level dependencies for NetBSD that should be used */
+/* regardless of operating environment */
+#if defined(__NetBSD__)
+#define WTF_PLATFORM_NETBSD 1
+#endif
+
/* PLATFORM(UNIX) */
/* Operating system level dependencies for Unix-like systems that */
/* should be used regardless of operating environment */
#if PLATFORM(DARWIN) \
|| PLATFORM(FREEBSD) \
+ || PLATFORM(S60) \
+ || PLATFORM(NETBSD) \
|| defined(unix) \
|| defined(__unix) \
|| defined(__unix__) \
- || defined (__NetBSD__) \
|| defined(_AIX)
#define WTF_PLATFORM_UNIX 1
#endif
/* Operating environments */
+/* PLATFORM(CHROMIUM) */
/* PLATFORM(QT) */
/* PLATFORM(GTK) */
/* PLATFORM(MAC) */
/* PLATFORM(WIN) */
-#if defined(BUILDING_QT__)
+#if defined(BUILDING_CHROMIUM__)
+#define WTF_PLATFORM_CHROMIUM 1
+#elif defined(BUILDING_QT__)
#define WTF_PLATFORM_QT 1
/* PLATFORM(KDE) */
#define WTF_PLATFORM_WIN 1
#endif
+/* PLATFORM(IPHONE) */
+#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+#define WTF_PLATFORM_IPHONE 1
+#endif
+
+/* PLATFORM(IPHONE_SIMULATOR) */
+#if TARGET_IPHONE_SIMULATOR
+#define WTF_PLATFORM_IPHONE 1
+#define WTF_PLATFORM_IPHONE_SIMULATOR 1
+#else
+#define WTF_PLATFORM_IPHONE_SIMULATOR 0
+#endif
+
+#if !defined(WTF_PLATFORM_IPHONE)
+#define WTF_PLATFORM_IPHONE 0
+#endif
+
/* Graphics engines */
-/* PLATFORM(CG) */
-/* PLATFORM(CAIRO) */
-#if PLATFORM(MAC)
+/* PLATFORM(CG) and PLATFORM(CI) */
+#define WTF_PLATFORM_CG 1
+
+/* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */
+#if PLATFORM(CHROMIUM)
+#if PLATFORM(DARWIN)
#define WTF_PLATFORM_CG 1
#define WTF_PLATFORM_CI 1
-#elif !PLATFORM(QT) && !PLATFORM(WX)
-#define WTF_PLATFORM_CAIRO 1
+#define WTF_USE_ATSUI 1
+#else
+#define WTF_PLATFORM_SKIA 1
+#endif
#endif
-
-#ifdef __S60__
-// we are cross-compiling, it is not really windows
-#undef WTF_PLATFORM_WIN_OS
-#undef WTF_PLATFORM_WIN
-#undef WTF_PLATFORM_CAIRO
-#define WTF_PLATFORM_S60 1
-#define WTF_PLATFORM_SYMBIAN 1
+/* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */
+/* FIXME: This should be changed from a blacklist to a whitelist */
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM)
+#define WTF_PLATFORM_CAIRO 1
#endif
/* CPU */
#define WTF_PLATFORM_ARM 1
#if defined(__ARMEB__)
#define WTF_PLATFORM_BIG_ENDIAN 1
-#elif !defined(__ARM_EABI__) && !defined(__ARMEB__) && !defined(__ARMEL__)
+#elif !defined(__ARM_EABI__) && !defined(__ARMEB__) && !defined(__VFP_FP__)
#define WTF_PLATFORM_MIDDLE_ENDIAN 1
#endif
#if !defined(__ARM_EABI__)
#define WTF_PLATFORM_X86_64 1
#endif
-/* PLATFORM(MAC) */
-#if PLATFORM(DARWIN)
-#define WTF_PLATFORM_CG 1
-#define WTF_PLATFORM_MAC 1
-#include <TargetConditionals.h>
+/* PLATFORM(SPARC64) */
+#if defined(__sparc64__)
+#define WTF_PLATFORM_SPARC64 1
+#define WTF_PLATFORM_BIG_ENDIAN 1
#endif
-/* PLATFORM(IPHONE) */
-#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
-#define WTF_PLATFORM_IPHONE 1
-#endif
-
-/* PLATFORM(IPHONE_SIMULATOR) */
-#if TARGET_IPHONE_SIMULATOR
-#define WTF_PLATFORM_IPHONE 1
-#define WTF_PLATFORM_IPHONE_SIMULATOR 1
-#else
-#define WTF_PLATFORM_IPHONE_SIMULATOR 0
+/* PLATFORM(WIN_CE) && PLATFORM(QT)
+ We can not determine the endianess at compile time. For
+ Qt for Windows CE the endianess is specified in the
+ device specific makespec
+*/
+#if PLATFORM(WIN_CE) && PLATFORM(QT)
+# include <QtGlobal>
+# undef WTF_PLATFORM_BIG_ENDIAN
+# undef WTF_PLATFORM_MIDDLE_ENDIAN
+# if Q_BYTE_ORDER == Q_BIG_EDIAN
+# define WTF_PLATFORM_BIG_ENDIAN 1
+# endif
#endif
/* Compiler */
#define WTF_COMPILER_GCC 1
#endif
+/* COMPILER(MINGW) */
+#if defined(MINGW) || defined(__MINGW32__)
+#define WTF_COMPILER_MINGW 1
+#endif
+
/* COMPILER(BORLAND) */
/* not really fully supported - is this relevant any more? */
#if defined(__BORLANDC__)
#define WTF_COMPILER_CYGWIN 1
#endif
-/* multiple threads only supported on Mac for now */
-#define WTF_USE_MULTIPLE_THREADS 1
+/* COMPILER(RVCT) */
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define WTF_COMPILER_RVCT 1
+#endif
+
+/* COMPILER(WINSCW) */
+#if defined(__WINSCW__)
+#define WTF_COMPILER_WINSCW 1
+#endif
-/* for Unicode, KDE uses Qt, everything else uses ICU */
+#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
+#define ENABLE_JSC_MULTIPLE_THREADS 1
+#endif
+
+/* for Unicode, KDE uses Qt */
#if PLATFORM(KDE) || PLATFORM(QT)
#define WTF_USE_QT4_UNICODE 1
#elif PLATFORM(SYMBIAN)
#define WTF_USE_SYMBIAN_UNICODE 1
+#elif PLATFORM(GTK)
+/* The GTK+ Unicode backend is configurable */
#else
#define WTF_USE_ICU_UNICODE 1
#endif
-#if PLATFORM(IPHONE_SIMULATOR)
-#define ENABLE_WEB_SCRIPT_DEBUG_SERVER 1
-#else
-#define ENABLE_WEB_SCRIPT_DEBUG_SERVER 0
-#endif
+#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN)
#define WTF_PLATFORM_CF 1
#define WTF_USE_PTHREADS 1
+#endif
+#define WTF_PLATFORM_CF 1
+#define WTF_USE_PTHREADS 1
#define ENABLE_FTPDIR 1
-#define ENABLE_JAVA_BINDINGS 0
+#define ENABLE_JIT 0
+#define ENABLE_MAC_JAVA_BRIDGE 0
#define ENABLE_ICONDATABASE 0
-#define ENABLE_NETSCAPE_API 0
#define ENABLE_TOUCH_EVENTS 1
-#define ENABLE_DASHBOARD_SUPPORT 0
#define ENABLE_IPHONE_PPT 1
-
-#if !defined(WTF_PLATFORM_IPHONE)
-#define WTF_PLATFORM_IPHONE 0
-#endif
-
-#if PLATFORM(DARWIN) && defined(__LP64__)
-#define ENABLE_NETSCAPE_API 0
-#endif
+#define ENABLE_GEOLOCATION 1
+#define ENABLE_NETSCAPE_PLUGIN_API 0
+#define HAVE_READLINE 1
+#define DONT_FINALIZE_ON_MAIN_THREAD 1
+#define HAVE_MADV_FREE 1
+#define ENABLE_REPAINT_THROTTLING 1
+#define ENABLE_RESPECT_EXIF_ORIENTATION 1
#if PLATFORM(WIN)
#define WTF_USE_WININET 1
#define WTF_USE_PTHREADS 1
#endif
-#if PLATFORM(QT)
-#define USE_SYSTEM_MALLOC 1
+#if PLATFORM(GTK)
+#if HAVE(PTHREAD_H)
+#define WTF_USE_PTHREADS 1
+#endif
#endif
-#if !defined(ENABLE_FTPDIR)
-#define ENABLE_FTPDIR 1
+#if !defined(HAVE_ACCESSIBILITY)
+#define HAVE_ACCESSIBILITY 1
+#endif /* !defined(HAVE_ACCESSIBILITY) */
+
+#if COMPILER(GCC)
+#define HAVE_COMPUTED_GOTO 1
+#endif
+
+#if PLATFORM(DARWIN)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 1
+#define HAVE_MERGESORT 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TIMEB_H 1
+
+#elif PLATFORM(WIN_OS)
+
+#define HAVE_FLOAT_H 1
+#if PLATFORM(WIN_CE)
+#define HAVE_ERRNO_H 0
+#else
+#define HAVE_SYS_TIMEB_H 1
+#endif
+#define HAVE_VIRTUALALLOC 1
+
+#elif PLATFORM(SYMBIAN)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 0
+#define HAVE_SBRK 1
+
+#define HAVE_SYS_TIME_H 1
+#define HAVE_STRINGS_H 1
+
+#if !COMPILER(RVCT)
+#define HAVE_SYS_PARAM_H 1
#endif
-#if !defined(ENABLE_JAVA_BINDINGS)
-#define ENABLE_JAVA_BINDINGS 1
+#else
+
+/* FIXME: is this actually used or do other platforms generate their own config.h? */
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+
#endif
+/* ENABLE macro defaults */
+
#if !defined(ENABLE_ICONDATABASE)
#define ENABLE_ICONDATABASE 1
#endif
#define ENABLE_DATABASE 1
#endif
+#if !defined(ENABLE_JAVASCRIPT_DEBUGGER)
+#define ENABLE_JAVASCRIPT_DEBUGGER 1
+#endif
+
#if !defined(ENABLE_FTPDIR)
#define ENABLE_FTPDIR 1
#endif
-#if !defined(ENABLE_NETSCAPE_API)
-#define ENABLE_NETSCAPE_API 1
+#if !defined(ENABLE_DASHBOARD_SUPPORT)
+#define ENABLE_DASHBOARD_SUPPORT 0
#endif
-#if !defined(ENABLE_TOUCH_EVENTS)
-#define ENABLE_TOUCH_EVENTS 0
+#if !defined(ENABLE_MAC_JAVA_BRIDGE)
+#define ENABLE_MAC_JAVA_BRIDGE 0
#endif
-#if !defined(ENABLE_DASHBOARD_SUPPORT)
-#define ENABLE_DASHBOARD_SUPPORT 1
+#if !defined(ENABLE_NETSCAPE_PLUGIN_API)
+#define ENABLE_NETSCAPE_PLUGIN_API 1
+#endif
+
+#if !defined(ENABLE_RESPECT_EXIF_ORIENTATION)
+#define ENABLE_RESPECT_EXIF_ORIENTATION 0
+#endif
+
+#if !defined(ENABLE_TOUCH_EVENTS)
+#define ENABLE_TOUCH_EVENTS 0
#endif
#if !defined(ENABLE_IPHONE_PPT)
#define ENABLE_IPHONE_PPT 0
#endif
+#if !defined(ENABLE_OPCODE_STATS)
+#define ENABLE_OPCODE_STATS 0
+#endif
+
+#if !defined(ENABLE_CODEBLOCK_SAMPLING)
+#define ENABLE_CODEBLOCK_SAMPLING 0
+#endif
+
+#if ENABLE(CODEBLOCK_SAMPLING) && !defined(ENABLE_OPCODE_SAMPLING)
+#define ENABLE_OPCODE_SAMPLING 1
+#endif
+
+#if !defined(ENABLE_OPCODE_SAMPLING)
+#define ENABLE_OPCODE_SAMPLING 0
+#endif
+
+#if !defined(ENABLE_GEOLOCATION)
+#define ENABLE_GEOLOCATION 0
+#endif
+
+#if !defined(ENABLE_TEXT_CARET)
+#define ENABLE_TEXT_CARET 1
+#endif
+
+#if !defined(WTF_USE_ALTERNATE_JSIMMEDIATE) && PLATFORM(X86_64) && PLATFORM(MAC)
+#define WTF_USE_ALTERNATE_JSIMMEDIATE 1
+#endif
+
+#if !defined(ENABLE_REPAINT_THROTTLING)
+#define ENABLE_REPAINT_THROTTLING 0
+#endif
+
+#if !defined(ENABLE_JIT)
+/* x86-64 support is under development. */
+#if PLATFORM(X86_64) && PLATFORM(MAC)
+ #define ENABLE_JIT 0
+ #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+/* The JIT is tested & working on x86 Mac */
+#elif PLATFORM(X86) && PLATFORM(MAC)
+ #define ENABLE_JIT 1
+ #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+/* The JIT is tested & working on x86 Windows */
+#elif PLATFORM(X86) && PLATFORM(WIN)
+ #define ENABLE_JIT 1
+ #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+#endif
+ #define ENABLE_JIT_OPTIMIZE_CALL 1
+ #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
+ #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1
+#endif
+
+#if ENABLE(JIT)
+#if !(USE(JIT_STUB_ARGUMENT_VA_LIST) || USE(JIT_STUB_ARGUMENT_REGISTER) || USE(JIT_STUB_ARGUMENT_STACK))
+#error Please define one of the JIT_STUB_ARGUMENT settings.
+#elif (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_REGISTER)) \
+ || (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_STACK)) \
+ || (USE(JIT_STUB_ARGUMENT_REGISTER) && USE(JIT_STUB_ARGUMENT_STACK))
+#error Please do not define more than one of the JIT_STUB_ARGUMENT settings.
+#endif
+#endif
+
+/* WREC supports x86 & x86-64, and has been tested on Mac and Windows ('cept on 64-bit on Mac). */
+#if (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(MAC)) \
+ || (!defined(ENABLE_WREC) && PLATFORM(X86_64) && PLATFORM(MAC)) \
+ || (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(WIN))
+#define ENABLE_WREC 1
+#endif
+
+#if ENABLE(JIT) || ENABLE(WREC)
+#define ENABLE_ASSEMBLER 1
+#endif
+
+#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS)
+#define ENABLE_PAN_SCROLLING 1
+#endif
+
+#if !defined(ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER)
+#define ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER 1
+#endif
+
+/* Use the QtXmlStreamReader implementation for XMLTokenizer */
+#if PLATFORM(QT)
+#if !ENABLE(XSLT)
+#define WTF_USE_QXMLSTREAM 1
+#endif
+#endif
+
+#if !PLATFORM(QT)
+#define WTF_USE_FONT_FAST_PATH 1
+#endif
+
#endif /* WTF_Platform_h */
--- /dev/null
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PtrAndFlags_h
+#define PtrAndFlags_h
+
+#include <wtf/Assertions.h>
+
+namespace WTF {
+ template<class T, typename FlagEnum> class PtrAndFlags {
+ public:
+ PtrAndFlags() : m_ptrAndFlags(0) {}
+
+ bool isFlagSet(FlagEnum flagNumber) const { ASSERT(flagNumber < 2); return m_ptrAndFlags & (1 << flagNumber); }
+ void setFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags |= (1 << flagNumber);}
+ void clearFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags &= ~(1 << flagNumber);}
+ T* get() const { return reinterpret_cast<T*>(m_ptrAndFlags & ~3); }
+ void set(T* ptr) { ASSERT(!(reinterpret_cast<intptr_t>(ptr) & 3)); m_ptrAndFlags = reinterpret_cast<intptr_t>(ptr) | (m_ptrAndFlags & 3);}
+ private:
+ intptr_t m_ptrAndFlags;
+ };
+} // namespace WTF
+
+using WTF::PtrAndFlags;
+
+#endif // PtrAndFlags_h
--- /dev/null
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RandomNumber.h"
+
+#include "RandomNumberSeed.h"
+
+#include <limits>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace WTF {
+
+double weakRandomNumber()
+{
+#if COMPILER(MSVC) && defined(_CRT_RAND_S)
+ // rand_s is incredibly slow on windows so we fall back on rand for Math.random
+ return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0);
+#else
+ return randomNumber();
+#endif
+}
+
+double randomNumber()
+{
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+ static bool s_initialized = false;
+ if (!s_initialized) {
+ initializeRandomNumberGenerator();
+ s_initialized = true;
+ }
+#endif
+
+#if COMPILER(MSVC) && defined(_CRT_RAND_S)
+ uint32_t bits;
+ rand_s(&bits);
+ return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
+#elif PLATFORM(DARWIN)
+ uint32_t bits = arc4random();
+ return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
+#elif PLATFORM(UNIX)
+ uint32_t part1 = random() & (RAND_MAX - 1);
+ uint32_t part2 = random() & (RAND_MAX - 1);
+ // random only provides 31 bits
+ uint64_t fullRandom = part1;
+ fullRandom <<= 31;
+ fullRandom |= part2;
+
+ // Mask off the low 53bits
+ fullRandom &= (1LL << 53) - 1;
+ return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
+#else
+ uint32_t part1 = rand() & (RAND_MAX - 1);
+ uint32_t part2 = rand() & (RAND_MAX - 1);
+ // rand only provides 31 bits, and the low order bits of that aren't very random
+ // so we take the high 26 bits of part 1, and the high 27 bits of part2.
+ part1 >>= 5; // drop the low 5 bits
+ part2 >>= 4; // drop the low 4 bits
+ uint64_t fullRandom = part1;
+ fullRandom <<= 27;
+ fullRandom |= part2;
+
+ // Mask off the low 53bits
+ fullRandom &= (1LL << 53) - 1;
+ return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
+#endif
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_RandomNumber_h
+#define WTF_RandomNumber_h
+
+namespace WTF {
+
+ // Returns a pseudo-random number in the range [0, 1), attempts to be
+ // cryptographically secure if possible on the target platform
+ double randomNumber();
+
+ // Returns a pseudo-random number in the range [0, 1), attempts to
+ // produce a reasonable "random" number fast.
+ // We only need this because rand_s is so slow on windows.
+ double weakRandomNumber();
+
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_RandomNumberSeed_h
+#define WTF_RandomNumberSeed_h
+
+#include <stdlib.h>
+#include <time.h>
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if PLATFORM(UNIX)
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+// Internal JavaScriptCore usage only
+namespace WTF {
+
+inline void initializeRandomNumberGenerator()
+{
+#if PLATFORM(DARWIN)
+ // On Darwin we use arc4random which initialises itself.
+#elif COMPILER(MSVC) && defined(_CRT_RAND_S)
+ // On Windows we use rand_s which intialises itself
+#elif PLATFORM(UNIX)
+ // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
+ timeval time;
+ gettimeofday(&time, 0);
+ srandom(static_cast<unsigned>(time.tv_usec * getpid()));
+#else
+ srand(static_cast<unsigned>(time(0)));
+#endif
+}
+
+inline void initializeWeakRandomNumberGenerator()
+{
+#if COMPILER(MSVC) && defined(_CRT_RAND_S)
+ // We need to initialise windows rand() explicitly for Math.random
+ unsigned seed = 0;
+ rand_s(&seed);
+ srand(seed);
+#endif
+}
+}
+
+#endif
namespace WTF {
-template<class T> class RefCounted : Noncopyable {
+// This base class holds the non-template methods and attributes.
+// The RefCounted class inherits from it reducing the template bloat
+// generated by the compiler (technique called template hoisting).
+class RefCountedBase : Noncopyable {
public:
- RefCounted(int initialRefCount = 0)
+ void ref()
+ {
+ ASSERT(!m_deletionHasBegun);
+ ++m_refCount;
+ }
+
+ bool hasOneRef() const
+ {
+ ASSERT(!m_deletionHasBegun);
+ return m_refCount == 1;
+ }
+
+ int refCount() const
+ {
+ return m_refCount;
+ }
+
+protected:
+ RefCountedBase(int initialRefCount)
: m_refCount(initialRefCount)
#ifndef NDEBUG
, m_deletionHasBegun(false)
{
}
- void ref()
- {
- ASSERT(!m_deletionHasBegun);
- ++m_refCount;
- }
+ ~RefCountedBase() {}
- void deref()
+ // Returns whether the pointer should be freed or not.
+ bool derefBase()
{
ASSERT(!m_deletionHasBegun);
ASSERT(m_refCount > 0);
#ifndef NDEBUG
m_deletionHasBegun = true;
#endif
- delete static_cast<T*>(this);
- } else
- --m_refCount;
+ return true;
+ }
+
+ --m_refCount;
+ return false;
}
- bool hasOneRef()
+protected:
+ int m_refCount;
+#ifndef NDEBUG
+ bool m_deletionHasBegun;
+#endif
+};
+
+
+template<class T> class RefCounted : public RefCountedBase {
+public:
+ RefCounted(int initialRefCount = 1)
+ : RefCountedBase(initialRefCount)
{
- ASSERT(!m_deletionHasBegun);
- return m_refCount == 1;
}
- int refCount() const
+ void deref()
{
- return m_refCount;
+ if (derefBase())
+ delete static_cast<T*>(this);
}
-private:
- int m_refCount;
-#ifndef NDEBUG
- bool m_deletionHasBegun;
-#endif
+protected:
+ ~RefCounted() {}
};
} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RefCountedLeakCounter.h"
+
+#include <wtf/HashCountedSet.h>
+
+namespace WTF {
+
+#ifdef NDEBUG
+
+void RefCountedLeakCounter::suppressMessages(const char*) { }
+void RefCountedLeakCounter::cancelMessageSuppression(const char*) { }
+
+RefCountedLeakCounter::RefCountedLeakCounter(const char*) { }
+RefCountedLeakCounter::~RefCountedLeakCounter() { }
+
+void RefCountedLeakCounter::increment() { }
+void RefCountedLeakCounter::decrement() { }
+
+#else
+
+#define LOG_CHANNEL_PREFIX Log
+static WTFLogChannel LogRefCountedLeaks = { 0x00000000, "", WTFLogChannelOn };
+
+typedef HashCountedSet<const char*, PtrHash<const char*> > ReasonSet;
+static ReasonSet* leakMessageSuppressionReasons;
+
+void RefCountedLeakCounter::suppressMessages(const char* reason)
+{
+ if (!leakMessageSuppressionReasons)
+ leakMessageSuppressionReasons = new ReasonSet;
+ leakMessageSuppressionReasons->add(reason);
+}
+
+void RefCountedLeakCounter::cancelMessageSuppression(const char* reason)
+{
+ ASSERT(leakMessageSuppressionReasons);
+ ASSERT(leakMessageSuppressionReasons->contains(reason));
+ leakMessageSuppressionReasons->remove(reason);
+}
+
+RefCountedLeakCounter::RefCountedLeakCounter(const char* description)
+ : m_description(description)
+{
+}
+
+RefCountedLeakCounter::~RefCountedLeakCounter()
+{
+ static bool loggedSuppressionReason;
+ if (m_count) {
+ if (!leakMessageSuppressionReasons || leakMessageSuppressionReasons->isEmpty())
+ LOG(RefCountedLeaks, "LEAK: %u %s", m_count, m_description);
+ else if (!loggedSuppressionReason) {
+ // This logs only one reason. Later we could change it so we log all the reasons.
+ LOG(RefCountedLeaks, "No leak checking done: %s", leakMessageSuppressionReasons->begin()->first);
+ loggedSuppressionReason = true;
+ }
+ }
+}
+
+void RefCountedLeakCounter::increment()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ atomicIncrement(&m_count);
+#else
+ ++m_count;
+#endif
+}
+
+void RefCountedLeakCounter::decrement()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ atomicDecrement(&m_count);
+#else
+ --m_count;
+#endif
+}
+
+#endif
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RefCountedLeakCounter_h
+#define RefCountedLeakCounter_h
+
+#include "Assertions.h"
+#include "Threading.h"
+
+namespace WTF {
+
+ struct RefCountedLeakCounter {
+ static void suppressMessages(const char*);
+ static void cancelMessageSuppression(const char*);
+
+ explicit RefCountedLeakCounter(const char* description);
+ ~RefCountedLeakCounter();
+
+ void increment();
+ void decrement();
+
+#ifndef NDEBUG
+ private:
+ volatile int m_count;
+ const char* m_description;
+#endif
+ };
+
+} // namespace WTF
+
+#endif
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
template <typename T> class PassRefPtr;
+ enum HashTableDeletedValueType { HashTableDeletedValue };
+
template <typename T> class RefPtr {
public:
- RefPtr() : m_ptr(0) {}
+ RefPtr() : m_ptr(0) { }
RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); }
RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); }
// see comment in PassRefPtr.h for why this takes const reference
// Special constructor for cases where we overwrite an object in place.
RefPtr(PlacementNewAdoptType) { }
+ // Hash table deleted values, which are only constructed and never copied or destroyed.
+ RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+ bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
~RefPtr() { if (T* ptr = m_ptr) ptr->deref(); }
template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
T& operator*() const { return *m_ptr; }
- ALWAYS_INLINE T *operator->() const { return m_ptr; }
+ ALWAYS_INLINE T* operator->() const { return m_ptr; }
bool operator!() const { return !m_ptr; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+ operator bool() const { return m_ptr; }
+#else
typedef T* RefPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
+#endif
RefPtr& operator=(const RefPtr&);
RefPtr& operator=(T*);
void swap(RefPtr&);
private:
+ static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
T* m_ptr;
};
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
// This specialization is a direct copy of HashMap, with overloaded functions
// to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn.
- // FIXME: Is there a better way to do this that doesn't just copy HashMap?
+ // FIXME: Find a better way that doesn't require an entire copy of the HashMap template.
+ template<typename RawKeyType, typename ValueType, typename ValueTraits, typename HashFunctions>
+ struct RefPtrHashMapRawKeyTranslator {
+ typedef typename ValueType::first_type KeyType;
+ typedef typename ValueType::second_type MappedType;
+ typedef typename ValueTraits::FirstTraits KeyTraits;
+ typedef typename ValueTraits::SecondTraits MappedTraits;
+
+ static unsigned hash(RawKeyType key) { return HashFunctions::hash(key); }
+ static bool equal(const KeyType& a, RawKeyType b) { return HashFunctions::equal(a, b); }
+ static void translate(ValueType& location, RawKeyType key, const MappedType& mapped)
+ {
+ location.first = key;
+ location.second = mapped;
+ }
+ };
+
template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
private:
typedef KeyTraitsArg KeyTraits;
typedef MappedTraitsArg MappedTraits;
- typedef PairBaseHashTraits<KeyTraits, MappedTraits> ValueTraits;
+ typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
public:
typedef typename KeyTraits::TraitType KeyType;
private:
typedef HashArg HashFunctions;
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Hash StorageHashFunctions;
-
- typedef typename HashKeyStorageTraits<HashFunctions, KeyTraits>::Traits KeyStorageTraits;
- typedef typename MappedTraits::StorageTraits MappedStorageTraits;
- typedef PairHashTraits<KeyStorageTraits, MappedStorageTraits> ValueStorageTraits;
+ typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
+ HashFunctions, ValueTraits, KeyTraits> HashTableType;
- typedef typename KeyStorageTraits::TraitType KeyStorageType;
- typedef typename MappedStorageTraits::TraitType MappedStorageType;
- typedef typename ValueStorageTraits::TraitType ValueStorageType;
-
- typedef HashTable<KeyStorageType, ValueStorageType, PairFirstExtractor<ValueStorageType>,
- StorageHashFunctions, ValueStorageTraits, KeyStorageTraits> HashTableType;
+ typedef RefPtrHashMapRawKeyTranslator<RawKeyType, ValueType, ValueTraits, HashFunctions>
+ RawKeyTranslator;
public:
typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
- HashMap();
- HashMap(const HashMap&);
- HashMap& operator=(const HashMap&);
- ~HashMap();
-
void swap(HashMap&);
int size() const;
bool contains(RawKeyType) const;
MappedType get(const KeyType&) const;
MappedType get(RawKeyType) const;
+ MappedType inlineGet(RawKeyType) const;
// replaces value but not key if key is already present
// return value is a pair of the iterator to the key location,
private:
pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
pair<iterator, bool> inlineAdd(RawKeyType, const MappedType&);
- void refAll();
- void derefAll();
HashTableType m_impl;
};
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<RefPtr<T>, U, V, W, X>::refAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::refAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline void HashMap<RefPtr<T>, U, V, W, X>::derefAll()
- {
- HashTableRefCounter<HashTableType, ValueTraits>::derefAll(m_impl);
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::HashMap()
- {
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::HashMap(const HashMap& other)
- : m_impl(other.m_impl)
- {
- refAll();
- }
-
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>& HashMap<RefPtr<T>, U, V, W, X>::operator=(const HashMap& other)
- {
- HashMap tmp(other);
- swap(tmp);
- return *this;
- }
-
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other)
{
m_impl.swap(other.m_impl);
}
- template<typename T, typename U, typename V, typename W, typename X>
- inline HashMap<RefPtr<T>, U, V, W, X>::~HashMap()
- {
- derefAll();
- }
-
template<typename T, typename U, typename V, typename W, typename X>
inline int HashMap<RefPtr<T>, U, V, W, X>::size() const
{
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key)
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.find(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const
{
- return m_impl.find(*(const KeyStorageType*)&key);
+ return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.contains(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const
{
- return m_impl.contains(*(const KeyStorageType*)&key);
+ return m_impl.template contains<RawKeyType, RawKeyTranslator>(key);
}
template<typename T, typename U, typename V, typename W, typename X>
inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
{
- const bool canReplaceDeletedKey = !KeyTraits::needsDestruction || KeyStorageTraits::needsDestruction;
- typedef HashMapTranslator<canReplaceDeletedKey, ValueType, ValueTraits, ValueStorageTraits, HashFunctions> TranslatorType;
+ typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
}
inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, const MappedType& mapped)
{
- return inlineAdd(*(const KeyType*)&key, mapped);
+ return m_impl.template add<RawKeyType, MappedType, RawKeyTranslator>(key, mapped);
}
template<typename T, typename U, typename V, typename W, typename X>
HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, const MappedType& mapped)
{
pair<iterator, bool> result = inlineAdd(key, mapped);
- if (!result.second)
+ if (!result.second) {
// add call above didn't change anything, so set the mapped value
result.first->second = mapped;
+ }
return result;
}
typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
}
template<typename T, typename U, typename V, typename W, typename MappedTraits>
typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
- HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
+ inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const
{
- if (m_impl.isEmpty())
- return MappedTraits::emptyValue();
- ValueStorageType* entry = const_cast<HashTableType&>(m_impl).lookup(*(const KeyStorageType*)&key);
+ ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<RawKeyType, RawKeyTranslator>(key);
if (!entry)
return MappedTraits::emptyValue();
- return ((ValueType *)entry)->second;
+ return entry->second;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename MappedTraits>
+ typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
+ HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
+ {
+ return inlineGet(key);
}
template<typename T, typename U, typename V, typename W, typename X>
if (it.m_impl == m_impl.end())
return;
m_impl.checkTableConsistency();
- RefCounter<ValueTraits, ValueStorageTraits>::deref(*it.m_impl);
m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
}
template<typename T, typename U, typename V, typename W, typename X>
inline void HashMap<RefPtr<T>, U, V, W, X>::clear()
{
- derefAll();
m_impl.clear();
}
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_StdLibExtras_h
+#define WTF_StdLibExtras_h
+
+#include <wtf/Platform.h>
+#include <wtf/Assertions.h>
+
+// Use these to declare and define a static local variable (static T;) so that
+// it is leaked so that its destructors are not called at exit. Using this
+// macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
+#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
+#define DEFINE_STATIC_LOCAL(type, name, arguments) \
+ static type* name##Ptr = new type arguments; \
+ type& name = *name##Ptr
+#else
+#define DEFINE_STATIC_LOCAL(type, name, arguments) \
+ static type& name = *new type arguments
+#endif
+
+namespace WTF {
+
+ /*
+ * C++'s idea of a reinterpret_cast lacks sufficient cojones.
+ */
+ template<typename TO, typename FROM>
+ TO bitwise_cast(FROM in)
+ {
+ COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal);
+ union {
+ FROM from;
+ TO to;
+ } u;
+ u.from = in;
+ return u.to;
+ }
+
+} // namespace WTF
+
+#endif
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#ifndef WTF_StringExtras_h
#define WTF_StringExtras_h
-#include <stdio.h>
#include <stdarg.h>
+#include <stdio.h>
#if COMPILER(MSVC)
-inline int snprintf(char *str, size_t size, const char* format, ...)
+inline int snprintf(char* buffer, size_t count, const char* format, ...)
{
int result;
va_list args;
va_start(args, format);
- result = _vsnprintf(str, size, format, args);
+ result = _vsnprintf(buffer, count, format, args);
va_end(args);
return result;
}
-#if COMPILER(MSVC7)
-// MSVC8 and above define this function
-#define vsnprintf snprintf
+#if COMPILER(MSVC7) || PLATFORM(WIN_CE)
+
+inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
+{
+ return _vsnprintf(buffer, count, format, args);
+}
+
#endif
-inline int strncasecmp(const char* s1, const char* s2, size_t len) { return strnicmp(s1, s2, len); }
+#if PLATFORM(WIN_CE)
+
+inline int strnicmp(const char* string1, const char* string2, size_t count)
+{
+ return _strnicmp(string1, string2, count);
+}
+
+inline int stricmp(const char* string1, const char* string2)
+{
+ return _stricmp(string1, string2);
+}
+
+inline char* strdup(const char* strSource)
+{
+ return _strdup(strSource);
+}
+
+#endif
+
+inline int strncasecmp(const char* s1, const char* s2, size_t len)
+{
+ return strnicmp(s1, s2, len);
+}
+
+inline int strcasecmp(const char* s1, const char* s2)
+{
+ return stricmp(s1, s2);
+}
#endif
#else
#include <sys/types.h>
#endif
-#include <stdlib.h> /* for abort() */
-#if COMPILER(MSVC)
+#if PLATFORM(WIN_OS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
("isync\n\t"
"eieio\n\t"
"stw %1, %0"
-#if PLATFORM(DARWIN)
+#if PLATFORM(DARWIN) || PLATFORM(PPC)
: "=o" (lockword_)
#else
: "=m" (lockword_)
// from taking 30 seconds to 16 seconds.
// Sleep for a few milliseconds
-#if COMPILER(MSVC)
+#if PLATFORM(WIN_OS)
Sleep(2);
#else
struct timespec tm;
pthread_mutex_t private_lock_;
inline void Init() {
- if (pthread_mutex_init(&private_lock_, NULL) != 0) abort();
+ if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH();
}
inline void Finalize() {
- if (pthread_mutex_destroy(&private_lock_) != 0) abort();
+ if (pthread_mutex_destroy(&private_lock_) != 0) CRASH();
}
inline void Lock() {
- if (pthread_mutex_lock(&private_lock_) != 0) abort();
+ if (pthread_mutex_lock(&private_lock_) != 0) CRASH();
}
inline void Unlock() {
- if (pthread_mutex_unlock(&private_lock_) != 0) abort();
+ if (pthread_mutex_unlock(&private_lock_) != 0) CRASH();
}
};
extra = alignment - pagesize;
}
void* result = mmap(NULL, size + extra,
- PROT_READ|PROT_WRITE,
+ PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
mmapFileDescriptor, 0);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
devmem_failure = true;
return NULL;
}
- void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE,
MAP_SHARED, physmem_fd, physmem_base);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
devmem_failure = true;
void TCMalloc_SystemRelease(void* start, size_t length)
{
- UNUSED_PARAM(start);
- UNUSED_PARAM(length);
-#if HAVE(MADV_DONTNEED)
+#if HAVE(MADV_FREE) || HAVE(MADV_DONTNEED)
+#if HAVE(MADV_FREE)
+ const int advice = MADV_FREE;
+#else
+ const int advice = MADV_DONTNEED;
+#endif
if (FLAGS_malloc_devmem_start) {
// It's not safe to use MADV_DONTNEED if we've been mapping
// /dev/mem for heap memory
if (new_end > new_start) {
// Note -- ignoring most return codes, because if this fails it
// doesn't matter...
- // The msync call with MS_KILLPAGES on Leopard is equivalent to an
- // madvise call with MADV_FREE on SnowLeopard
- while (msync(reinterpret_cast<char*>(new_start), new_end - new_start,
- MS_KILLPAGES) == -1 &&
+ while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start,
+ advice) == -1 &&
errno == EAGAIN) {
// NOP
}
#endif
#if HAVE(MMAP)
- void *newAddress = mmap(start, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, mmapFileDescriptor, 0);
- UNUSED_PARAM(newAddress);
+ void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, mmapFileDescriptor, 0);
// If the mmap failed then that's ok, we just won't return the memory to the system.
- ASSERT(newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
+ ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
return;
#endif
+
+#if !HAVE(MADV_DONTNEED) && !HAVE(MMAP)
+ UNUSED_PARAM(start);
+ UNUSED_PARAM(length);
+#endif
+}
+
+#if HAVE(VIRTUALALLOC)
+void TCMalloc_SystemCommit(void*, size_t)
+{
}
+#endif
// be released, partial pages will not.)
extern void TCMalloc_SystemRelease(void* start, size_t length);
+#if HAVE(VIRTUALALLOC)
+extern void TCMalloc_SystemCommit(void* start, size_t length);
+#else
+inline void TCMalloc_SystemCommit(void*, size_t) { }
+#endif
+
#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Jian Li <jianli@chromium.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Thread local storage is implemented by using either pthread API or Windows
+ * native API. There is subtle semantic discrepancy for the cleanup function
+ * implementation as noted below:
+ * @ In pthread implementation, the destructor function will be called
+ * repeatedly if there is still non-NULL value associated with the function.
+ * @ In Windows native implementation, the destructor function will be called
+ * only once.
+ * This semantic discrepancy does not impose any problem because nowhere in
+ * WebKit the repeated call bahavior is utilized.
+ */
+
+#ifndef WTF_ThreadSpecific_h
+#define WTF_ThreadSpecific_h
+
+#include <wtf/Noncopyable.h>
+
+#if USE(PTHREADS)
+#include <pthread.h>
+#elif PLATFORM(WIN_OS)
+#include <windows.h>
+#endif
+
+namespace WTF {
+
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+// ThreadSpecificThreadExit should be called each time when a thread is detached.
+// This is done automatically for threads created with WTF::createThread.
+void ThreadSpecificThreadExit();
+#endif
+
+template<typename T> class ThreadSpecific : Noncopyable {
+public:
+ ThreadSpecific();
+ T* operator->();
+ operator T*();
+ T& operator*();
+ ~ThreadSpecific();
+
+private:
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+ friend void ThreadSpecificThreadExit();
+#endif
+
+ T* get();
+ void set(T*);
+ void static destroy(void* ptr);
+
+#if USE(PTHREADS) || PLATFORM(WIN_OS)
+ struct Data : Noncopyable {
+ Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
+
+ T* value;
+ ThreadSpecific<T>* owner;
+#if !USE(PTHREADS)
+ void (*destructor)(void*);
+#endif
+ };
+#endif
+
+#if USE(PTHREADS)
+ pthread_key_t m_key;
+#elif PLATFORM(WIN_OS)
+ int m_index;
+#endif
+};
+
+#if USE(PTHREADS)
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+{
+ int error = pthread_key_create(&m_key, destroy);
+ if (error)
+ CRASH();
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+ pthread_key_delete(m_key); // Does not invoke destructor functions.
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(pthread_getspecific(m_key));
+ return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+ ASSERT(!get());
+ pthread_setspecific(m_key, new Data(ptr, this));
+}
+
+#elif PLATFORM(WIN_OS)
+
+// The maximum number of TLS keys that can be created. For simplification, we assume that:
+// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
+// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
+const int kMaxTlsKeySize = 256;
+
+extern long g_tls_key_count;
+extern DWORD g_tls_keys[kMaxTlsKeySize];
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+ : m_index(-1)
+{
+ DWORD tls_key = TlsAlloc();
+ if (tls_key == TLS_OUT_OF_INDEXES)
+ CRASH();
+
+ m_index = InterlockedIncrement(&g_tls_key_count) - 1;
+ if (m_index >= kMaxTlsKeySize)
+ CRASH();
+ g_tls_keys[m_index] = tls_key;
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+ // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached.
+ TlsFree(g_tls_keys[m_index]);
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
+ return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+ ASSERT(!get());
+ Data* data = new Data(ptr, this);
+ data->destructor = &ThreadSpecific<T>::destroy;
+ TlsSetValue(g_tls_keys[m_index], data);
+}
+
+#else
+#error ThreadSpecific is not implemented for this platform.
+#endif
+
+template<typename T>
+inline void ThreadSpecific<T>::destroy(void* ptr)
+{
+ Data* data = static_cast<Data*>(ptr);
+
+#if USE(PTHREADS)
+ // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
+ // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
+ pthread_setspecific(data->owner->m_key, ptr);
+#endif
+
+ data->value->~T();
+ fastFree(data->value);
+
+#if USE(PTHREADS)
+ pthread_setspecific(data->owner->m_key, 0);
+#elif PLATFORM(WIN_OS)
+ TlsSetValue(g_tls_keys[data->owner->m_index], 0);
+#else
+#error ThreadSpecific is not implemented for this platform.
+#endif
+
+ delete data;
+}
+
+template<typename T>
+inline ThreadSpecific<T>::operator T*()
+{
+ T* ptr = static_cast<T*>(get());
+ if (!ptr) {
+ // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls
+ // needs to access the value, to avoid recursion.
+ ptr = static_cast<T*>(fastMalloc(sizeof(T)));
+ set(ptr);
+ new (ptr) T;
+ }
+ return ptr;
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::operator->()
+{
+ return operator T*();
+}
+
+template<typename T>
+inline T& ThreadSpecific<T>::operator*()
+{
+ return *operator T*();
+}
+
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2009 Jian Li <jianli@chromium.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "ThreadSpecific.h"
+#include <wtf/Noncopyable.h>
+
+#if USE(PTHREADS)
+#error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation.
+#endif
+
+namespace WTF {
+
+long g_tls_key_count = 0;
+DWORD g_tls_keys[kMaxTlsKeySize];
+
+void ThreadSpecificThreadExit()
+{
+ for (long i = 0; i < g_tls_key_count; i++) {
+ // The layout of ThreadSpecific<T>::Data does not depend on T. So we are safe to do the static cast to ThreadSpecific<int> in order to access its data member.
+ ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(g_tls_keys[i]));
+ if (data)
+ data->destructor(data);
+ }
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+namespace WTF {
+
+struct NewThreadContext {
+ NewThreadContext(ThreadFunction entryPoint, void* data)
+ : entryPoint(entryPoint)
+ , data(data)
+ { }
+
+ ThreadFunction entryPoint;
+ void* data;
+
+ Mutex creationMutex;
+};
+
+static void* threadEntryPoint(void* contextData)
+{
+ NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
+
+ // Block until our creating thread has completed any extra setup work
+ {
+ MutexLocker locker(context->creationMutex);
+ }
+
+ // Grab the info that we need out of the context, then deallocate it.
+ ThreadFunction entryPoint = context->entryPoint;
+ void* data = context->data;
+ delete context;
+
+ return entryPoint(data);
+}
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
+{
+ NewThreadContext* context = new NewThreadContext(entryPoint, data);
+
+ // Prevent the thread body from executing until we've established the thread identifier
+ MutexLocker locker(context->creationMutex);
+
+ return createThreadInternal(threadEntryPoint, context, name);
+}
+
+#if PLATFORM(MAC) || PLATFORM(WIN)
+
+// This function is deprecated but needs to be kept around for backward
+// compatibility. Use the 3-argument version of createThread above.
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data);
+
+ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
+{
+ return createThread(entryPoint, data, 0);
+}
+#endif
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
+ * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
+ * is virtually identical to the Apple license above but is included here for completeness.
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Threading_h
+#define Threading_h
+
+#include <wtf/Platform.h>
+
+#if PLATFORM(WIN_CE)
+#include <windows.h>
+#endif
+
+#include <wtf/Assertions.h>
+#include <wtf/Locker.h>
+#include <wtf/Noncopyable.h>
+
+#if PLATFORM(WIN_OS) && !PLATFORM(WIN_CE)
+#include <windows.h>
+#elif PLATFORM(DARWIN)
+#include <libkern/OSAtomic.h>
+#elif COMPILER(GCC)
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
+#include <ext/atomicity.h>
+#else
+#include <bits/atomicity.h>
+#endif
+#endif
+
+#if USE(PTHREADS)
+#include <pthread.h>
+#elif PLATFORM(GTK)
+#include <wtf/GOwnPtr.h>
+typedef struct _GMutex GMutex;
+typedef struct _GCond GCond;
+#endif
+
+#if USE(PTHREADS) && (PLATFORM(MAC) || PLATFORM(IPHONE))
+#ifdef __OBJC__
+@class NSThread;
+#else
+class NSThread;
+#endif
+#endif
+
+#if PLATFORM(QT)
+#include <qglobal.h>
+QT_BEGIN_NAMESPACE
+class QMutex;
+class QWaitCondition;
+QT_END_NAMESPACE
+#endif
+
+#include <stdint.h>
+
+// For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc).
+#define AtomicallyInitializedStatic(T, name) \
+ WTF::lockAtomicallyInitializedStaticMutex(); \
+ static T name; \
+ WTF::unlockAtomicallyInitializedStaticMutex();
+
+namespace WTF {
+
+typedef uint32_t ThreadIdentifier;
+typedef void* (*ThreadFunction)(void* argument);
+
+// Returns 0 if thread creation failed
+ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
+
+ThreadIdentifier currentThread();
+bool isMainThread();
+int waitForThreadCompletion(ThreadIdentifier, void**);
+void detachThread(ThreadIdentifier);
+
+#if USE(PTHREADS)
+typedef pthread_mutex_t PlatformMutex;
+typedef pthread_cond_t PlatformCondition;
+#elif PLATFORM(GTK)
+typedef GOwnPtr<GMutex> PlatformMutex;
+typedef GOwnPtr<GCond> PlatformCondition;
+#elif PLATFORM(QT)
+typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
+typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
+#elif PLATFORM(WIN_OS)
+struct PlatformMutex {
+ CRITICAL_SECTION m_internalMutex;
+ size_t m_recursionCount;
+};
+struct PlatformCondition {
+ size_t m_waitersGone;
+ size_t m_waitersBlocked;
+ size_t m_waitersToUnblock;
+ HANDLE m_blockLock;
+ HANDLE m_blockQueue;
+ HANDLE m_unblockLock;
+
+ bool timedWait(PlatformMutex&, DWORD durationMilliseconds);
+ void signal(bool unblockAll);
+};
+#else
+typedef void* PlatformMutex;
+typedef void* PlatformCondition;
+#endif
+
+class Mutex : Noncopyable {
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ bool tryLock();
+ void unlock();
+
+public:
+ PlatformMutex& impl() { return m_mutex; }
+private:
+ PlatformMutex m_mutex;
+};
+
+typedef Locker<Mutex> MutexLocker;
+
+class ThreadCondition : Noncopyable {
+public:
+ ThreadCondition();
+ ~ThreadCondition();
+
+ void wait(Mutex& mutex);
+ // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past.
+ // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime().
+ bool timedWait(Mutex&, double absoluteTime);
+ void signal();
+ void broadcast();
+
+private:
+ PlatformCondition m_condition;
+};
+
+#if PLATFORM(WIN_OS)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WIN_CE)
+inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); }
+inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
+#else
+inline void atomicIncrement(int volatile* addend) { InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
+inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
+#endif
+
+#elif PLATFORM(DARWIN)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addend) { OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
+inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
+
+#elif COMPILER(GCC)
+#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+
+inline void atomicIncrement(int volatile* addend) { __gnu_cxx::__atomic_add(addend, 1); }
+inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
+
+#endif
+
+template<class T> class ThreadSafeShared : Noncopyable {
+public:
+ ThreadSafeShared(int initialRefCount = 1)
+ : m_refCount(initialRefCount)
+ {
+ }
+
+ void ref()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ atomicIncrement(&m_refCount);
+#else
+ MutexLocker locker(m_mutex);
+ ++m_refCount;
+#endif
+ }
+
+ void deref()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ if (atomicDecrement(&m_refCount) <= 0)
+#else
+ {
+ MutexLocker locker(m_mutex);
+ --m_refCount;
+ }
+ if (m_refCount <= 0)
+#endif
+ delete static_cast<T*>(this);
+ }
+
+ bool hasOneRef()
+ {
+ return refCount() == 1;
+ }
+
+ int refCount() const
+ {
+#if !USE(LOCKFREE_THREADSAFESHARED)
+ MutexLocker locker(m_mutex);
+#endif
+ return static_cast<int const volatile &>(m_refCount);
+ }
+
+private:
+ int m_refCount;
+#if !USE(LOCKFREE_THREADSAFESHARED)
+ mutable Mutex m_mutex;
+#endif
+};
+
+// This function must be called from the main thread. It is safe to call it repeatedly.
+// Darwin is an exception to this rule: it is OK to call it from any thread, the only requirement is that the calls are not reentrant.
+void initializeThreading();
+
+#if USE(PTHREADS) && (PLATFORM(MAC) || PLATFORM(IPHONE))
+void initializeMainNSThread();
+NSThread *mainNSThread();
+#endif
+
+void lockAtomicallyInitializedStaticMutex();
+void unlockAtomicallyInitializedStaticMutex();
+
+} // namespace WTF
+
+using WTF::Mutex;
+using WTF::MutexLocker;
+using WTF::ThreadCondition;
+using WTF::ThreadIdentifier;
+using WTF::ThreadSafeShared;
+
+using WTF::createThread;
+using WTF::currentThread;
+using WTF::isMainThread;
+using WTF::detachThread;
+using WTF::waitForThreadCompletion;
+
+#endif // Threading_h
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+#if !USE(PTHREADS)
+
+#include "CurrentTime.h"
+#include "HashMap.h"
+#include "MainThread.h"
+#include "RandomNumberSeed.h"
+
+#include <glib.h>
+#include <limits.h>
+
+namespace WTF {
+
+static Mutex* atomicallyInitializedStaticMutex;
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ ASSERT(g_thread_supported());
+
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ initializeRandomNumberGenerator();
+ mainThreadIdentifier = currentThread();
+ initializeMainThread();
+ }
+}
+
+void lockAtomicallyInitializedStaticMutex()
+{
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+static HashMap<ThreadIdentifier, GThread*>& threadMap()
+{
+ static HashMap<ThreadIdentifier, GThread*> map;
+ return map;
+}
+
+static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (i->second == thread)
+ return i->first;
+ }
+
+ return 0;
+}
+
+static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
+{
+ ASSERT(!identifierByGthreadHandle(thread));
+
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, thread);
+
+ return identifierCount++;
+}
+
+static GThread* threadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ return threadMap().get(id);
+}
+
+static void clearThreadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(id));
+
+ threadMap().remove(id);
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
+{
+ GThread* thread;
+ if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+
+ ThreadIdentifier threadID = establishIdentifierForThread(thread);
+ return threadID;
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ GThread* thread = threadForIdentifier(threadID);
+
+ void* joinResult = g_thread_join(thread);
+ if (result)
+ *result = joinResult;
+
+ clearThreadForIdentifier(threadID);
+ return 0;
+}
+
+void detachThread(ThreadIdentifier)
+{
+}
+
+ThreadIdentifier currentThread()
+{
+ GThread* currentThread = g_thread_self();
+ if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForThread(currentThread);
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+ : m_mutex(g_mutex_new())
+{
+}
+
+Mutex::~Mutex()
+{
+}
+
+void Mutex::lock()
+{
+ g_mutex_lock(m_mutex.get());
+}
+
+bool Mutex::tryLock()
+{
+ return g_mutex_trylock(m_mutex.get());
+}
+
+void Mutex::unlock()
+{
+ g_mutex_unlock(m_mutex.get());
+}
+
+ThreadCondition::ThreadCondition()
+ : m_condition(g_cond_new())
+{
+}
+
+ThreadCondition::~ThreadCondition()
+{
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ g_cond_wait(m_condition.get(), mutex.impl().get());
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
+{
+ // Time is in the past - return right away.
+ if (absoluteTime < currentTime())
+ return false;
+
+ // Time is too far in the future for g_cond_timed_wait - wait forever.
+ if (absoluteTime > INT_MAX) {
+ wait(mutex);
+ return true;
+ }
+
+ int timeSeconds = static_cast<int>(absoluteTime);
+ int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0);
+
+ GTimeVal targetTime;
+ targetTime.tv_sec = timeSeconds;
+ targetTime.tv_usec = timeMicroseconds;
+
+ return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
+}
+
+void ThreadCondition::signal()
+{
+ g_cond_signal(m_condition.get());
+}
+
+void ThreadCondition::broadcast()
+{
+ g_cond_broadcast(m_condition.get());
+}
+
+
+}
+
+#endif // !USE(PTHREADS)
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+namespace WTF {
+
+void initializeThreading() { }
+ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; }
+int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
+void detachThread(ThreadIdentifier) { }
+ThreadIdentifier currentThread() { return 0; }
+bool isMainThread() { return true; }
+
+Mutex::Mutex() { }
+Mutex::~Mutex() { }
+void Mutex::lock() { }
+bool Mutex::tryLock() { return false; }
+void Mutex::unlock() { }
+
+ThreadCondition::ThreadCondition() { }
+ThreadCondition::~ThreadCondition() { }
+void ThreadCondition::wait(Mutex& mutex) { }
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { return false; }
+void ThreadCondition::signal() { }
+void ThreadCondition::broadcast() { }
+
+void lockAtomicallyInitializedStaticMutex() { }
+void unlockAtomicallyInitializedStaticMutex() { }
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "Threading.h"
+
+#include "StdLibExtras.h"
+
+#if USE(PTHREADS)
+
+#include "CurrentTime.h"
+#include "HashMap.h"
+#include "MainThread.h"
+#include "RandomNumberSeed.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+
+namespace WTF {
+
+typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
+
+static Mutex* atomicallyInitializedStaticMutex;
+
+static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
+
+static Mutex& threadMapMutex()
+{
+ DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ initializeRandomNumberGenerator();
+ mainThreadIdentifier = currentThread();
+ initializeMainNSThread();
+ initializeMainThread();
+ }
+}
+
+void lockAtomicallyInitializedStaticMutex()
+{
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+static ThreadMap& threadMap()
+{
+ DEFINE_STATIC_LOCAL(ThreadMap, map, ());
+ return map;
+}
+
+static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ThreadMap::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (pthread_equal(i->second, pthreadHandle))
+ return i->first;
+ }
+
+ return 0;
+}
+
+static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+{
+ ASSERT(!identifierByPthreadHandle(pthreadHandle));
+
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, pthreadHandle);
+
+ return identifierCount++;
+}
+
+static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ return threadMap().get(id);
+}
+
+static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(id));
+
+ threadMap().remove(id);
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
+{
+ pthread_t threadHandle;
+ if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
+ LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+
+ return establishIdentifierForPthreadHandle(threadHandle);
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+
+ int joinResult = pthread_join(pthreadHandle, result);
+ if (joinResult == EDEADLK)
+ LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
+
+ clearPthreadHandleForIdentifier(threadID);
+ return joinResult;
+}
+
+void detachThread(ThreadIdentifier threadID)
+{
+ ASSERT(threadID);
+
+ pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+
+ pthread_detach(pthreadHandle);
+
+ clearPthreadHandleForIdentifier(threadID);
+}
+
+ThreadIdentifier currentThread()
+{
+ pthread_t currentThread = pthread_self();
+ if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForPthreadHandle(currentThread);
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+{
+ pthread_mutex_init(&m_mutex, NULL);
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&m_mutex);
+}
+
+void Mutex::lock()
+{
+ if (pthread_mutex_lock(&m_mutex) != 0)
+ ASSERT(false);
+}
+
+bool Mutex::tryLock()
+{
+ int result = pthread_mutex_trylock(&m_mutex);
+
+ if (result == 0)
+ return true;
+ else if (result == EBUSY)
+ return false;
+
+ ASSERT(false);
+ return false;
+}
+
+void Mutex::unlock()
+{
+ if (pthread_mutex_unlock(&m_mutex) != 0)
+ ASSERT(false);
+}
+
+ThreadCondition::ThreadCondition()
+{
+ pthread_cond_init(&m_condition, NULL);
+}
+
+ThreadCondition::~ThreadCondition()
+{
+ pthread_cond_destroy(&m_condition);
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
+ ASSERT(false);
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
+{
+ if (absoluteTime < currentTime())
+ return false;
+
+ if (absoluteTime > INT_MAX) {
+ wait(mutex);
+ return true;
+ }
+
+ int timeSeconds = static_cast<int>(absoluteTime);
+ int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
+
+ timespec targetTime;
+ targetTime.tv_sec = timeSeconds;
+ targetTime.tv_nsec = timeNanoseconds;
+
+ return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
+}
+
+void ThreadCondition::signal()
+{
+ if (pthread_cond_signal(&m_condition) != 0)
+ ASSERT(false);
+}
+
+void ThreadCondition::broadcast()
+{
+ if (pthread_cond_broadcast(&m_condition) != 0)
+ ASSERT(false);
+}
+
+} // namespace WTF
+
+#endif // USE(PTHREADS)
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "Threading.h"
+
+#include "CurrentTime.h"
+#include "HashMap.h"
+#include "MainThread.h"
+#include "RandomNumberSeed.h"
+
+#include <QCoreApplication>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+
+namespace WTF {
+
+class ThreadPrivate : public QThread {
+public:
+ ThreadPrivate(ThreadFunction entryPoint, void* data);
+ void run();
+ void* getReturnValue() { return m_returnValue; }
+private:
+ void* m_data;
+ ThreadFunction m_entryPoint;
+ void* m_returnValue;
+};
+
+ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint, void* data)
+ : m_data(data)
+ , m_entryPoint(entryPoint)
+ , m_returnValue(0)
+{
+}
+
+void ThreadPrivate::run()
+{
+ m_returnValue = m_entryPoint(m_data);
+}
+
+
+static Mutex* atomicallyInitializedStaticMutex;
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+static HashMap<ThreadIdentifier, QThread*>& threadMap()
+{
+ static HashMap<ThreadIdentifier, QThread*> map;
+ return map;
+}
+
+static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
+{
+ MutexLocker locker(threadMapMutex());
+
+ HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
+ for (; i != threadMap().end(); ++i) {
+ if (i->second == thread)
+ return i->first;
+ }
+
+ return 0;
+}
+
+static ThreadIdentifier establishIdentifierForThread(QThread*& thread)
+{
+ ASSERT(!identifierByQthreadHandle(thread));
+
+ MutexLocker locker(threadMapMutex());
+
+ static ThreadIdentifier identifierCount = 1;
+
+ threadMap().add(identifierCount, thread);
+
+ return identifierCount++;
+}
+
+static void clearThreadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ ASSERT(threadMap().contains(id));
+
+ threadMap().remove(id);
+}
+
+static QThread* threadForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+
+ return threadMap().get(id);
+}
+
+void initializeThreading()
+{
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ initializeRandomNumberGenerator();
+ QThread* mainThread = QCoreApplication::instance()->thread();
+ mainThreadIdentifier = identifierByQthreadHandle(mainThread);
+ if (!mainThreadIdentifier)
+ mainThreadIdentifier = establishIdentifierForThread(mainThread);
+ initializeMainThread();
+ }
+}
+
+void lockAtomicallyInitializedStaticMutex()
+{
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
+{
+ ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
+ if (!thread) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+ thread->start();
+
+ QThread* threadRef = static_cast<QThread*>(thread);
+
+ return establishIdentifierForThread(threadRef);
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ QThread* thread = threadForIdentifier(threadID);
+
+ bool res = thread->wait();
+
+ clearThreadForIdentifier(threadID);
+ if (result)
+ *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
+
+ return !res;
+}
+
+void detachThread(ThreadIdentifier)
+{
+}
+
+ThreadIdentifier currentThread()
+{
+ QThread* currentThread = QThread::currentThread();
+ if (ThreadIdentifier id = identifierByQthreadHandle(currentThread))
+ return id;
+ return establishIdentifierForThread(currentThread);
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+ : m_mutex(new QMutex())
+{
+}
+
+Mutex::~Mutex()
+{
+ delete m_mutex;
+}
+
+void Mutex::lock()
+{
+ m_mutex->lock();
+}
+
+bool Mutex::tryLock()
+{
+ return m_mutex->tryLock();
+}
+
+void Mutex::unlock()
+{
+ m_mutex->unlock();
+}
+
+ThreadCondition::ThreadCondition()
+ : m_condition(new QWaitCondition())
+{
+}
+
+ThreadCondition::~ThreadCondition()
+{
+ delete m_condition;
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ m_condition->wait(mutex.impl());
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
+{
+ double currentTime = WTF::currentTime();
+
+ // Time is in the past - return immediately.
+ if (absoluteTime < currentTime)
+ return false;
+
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
+ // Qt defines wait for up to ULONG_MAX milliseconds.
+ if (intervalMilliseconds >= ULONG_MAX)
+ intervalMilliseconds = ULONG_MAX;
+
+ return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
+}
+
+void ThreadCondition::signal()
+{
+ m_condition->wakeOne();
+}
+
+void ThreadCondition::broadcast()
+{
+ m_condition->wakeAll();
+}
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * There are numerous academic and practical works on how to implement pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast
+ * functions on Win32. Here is one example: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html which is widely credited as a 'starting point'
+ * of modern attempts. There are several more or less proven implementations, one in Boost C++ library (http://www.boost.org) and another
+ * in pthreads-win32 (http://sourceware.org/pthreads-win32/).
+ *
+ * The number of articles and discussions is the evidence of significant difficulties in implementing these primitives correctly.
+ * The brief search of revisions, ChangeLog entries, discussions in comp.programming.threads and other places clearly documents
+ * numerous pitfalls and performance problems the authors had to overcome to arrive to the suitable implementations.
+ * Optimally, WebKit would use one of those supported/tested libraries directly. To roll out our own implementation is impractical,
+ * if even for the lack of sufficient testing. However, a faithful reproduction of the code from one of the popular supported
+ * libraries seems to be a good compromise.
+ *
+ * The early Boost implementation (http://www.boxbackup.org/trac/browser/box/nick/win/lib/win32/boost_1_32_0/libs/thread/src/condition.cpp?rev=30)
+ * is identical to pthreads-win32 (http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32).
+ * Current Boost uses yet another (although seemingly equivalent) algorithm which came from their 'thread rewrite' effort.
+ *
+ * This file includes timedWait/signal/broadcast implementations translated to WebKit coding style from the latest algorithm by
+ * Alexander Terekhov and Louis Thomas, as captured here: http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32
+ * It replaces the implementation of their previous algorithm, also documented in the same source above.
+ * The naming and comments are left very close to original to enable easy cross-check.
+ *
+ * The corresponding Pthreads-win32 License is included below, and CONTRIBUTORS file which it refers to is added to
+ * source directory (as CONTRIBUTORS.pthreads-win32).
+ */
+
+/*
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "config.h"
+#include "Threading.h"
+
+#include "MainThread.h"
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#include "ThreadSpecific.h"
+#endif
+#include <process.h>
+#include <windows.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RandomNumberSeed.h>
+
+namespace WTF {
+
+// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadName all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
+static const DWORD MS_VC_EXCEPTION = 0x406D1388;
+
+#pragma pack(push, 8)
+typedef struct tagTHREADNAME_INFO {
+ DWORD dwType; // must be 0x1000
+ LPCSTR szName; // pointer to name (in user addr space)
+ DWORD dwThreadID; // thread ID (-1=caller thread)
+ DWORD dwFlags; // reserved for future use, must be zero
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+static void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+{
+ // Visual Studio has a 31-character limit on thread names. Longer names will
+ // be truncated silently, but we'd like callers to know about the limit.
+ ASSERT_ARG(szThreadName, strlen(szThreadName) <= 31);
+
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
+ } __except (EXCEPTION_CONTINUE_EXECUTION) {
+ }
+}
+
+static Mutex* atomicallyInitializedStaticMutex;
+
+void lockAtomicallyInitializedStaticMutex()
+{
+ ASSERT(atomicallyInitializedStaticMutex);
+ atomicallyInitializedStaticMutex->lock();
+}
+
+void unlockAtomicallyInitializedStaticMutex()
+{
+ atomicallyInitializedStaticMutex->unlock();
+}
+
+static ThreadIdentifier mainThreadIdentifier;
+
+static Mutex& threadMapMutex()
+{
+ static Mutex mutex;
+ return mutex;
+}
+
+void initializeThreading()
+{
+ if (!atomicallyInitializedStaticMutex) {
+ atomicallyInitializedStaticMutex = new Mutex;
+ threadMapMutex();
+ initializeRandomNumberGenerator();
+ initializeMainThread();
+ mainThreadIdentifier = currentThread();
+ setThreadName(mainThreadIdentifier, "Main Thread");
+ }
+}
+
+static HashMap<DWORD, HANDLE>& threadMap()
+{
+ static HashMap<DWORD, HANDLE> map;
+ return map;
+}
+
+static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle)
+{
+ MutexLocker locker(threadMapMutex());
+ ASSERT(!threadMap().contains(threadID));
+ threadMap().add(threadID, threadHandle);
+}
+
+static HANDLE threadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+ return threadMap().get(id);
+}
+
+static void clearThreadHandleForIdentifier(ThreadIdentifier id)
+{
+ MutexLocker locker(threadMapMutex());
+ ASSERT(threadMap().contains(id));
+ threadMap().remove(id);
+}
+
+struct ThreadFunctionInvocation {
+ ThreadFunctionInvocation(ThreadFunction function, void* data) : function(function), data(data) {}
+
+ ThreadFunction function;
+ void* data;
+};
+
+static unsigned __stdcall wtfThreadEntryPoint(void* param)
+{
+ ThreadFunctionInvocation invocation = *static_cast<ThreadFunctionInvocation*>(param);
+ delete static_cast<ThreadFunctionInvocation*>(param);
+
+ void* result = invocation.function(invocation.data);
+
+#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+ // Do the TLS cleanup.
+ ThreadSpecificThreadExit();
+#endif
+
+ return reinterpret_cast<unsigned>(result);
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName)
+{
+ unsigned threadIdentifier = 0;
+ ThreadIdentifier threadID = 0;
+ ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
+ HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
+ if (!threadHandle) {
+ LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
+ return 0;
+ }
+
+ if (threadName)
+ setThreadName(threadIdentifier, threadName);
+
+ threadID = static_cast<ThreadIdentifier>(threadIdentifier);
+ storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
+
+ return threadID;
+}
+
+int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
+{
+ ASSERT(threadID);
+
+ HANDLE threadHandle = threadHandleForIdentifier(threadID);
+ if (!threadHandle)
+ LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID);
+
+ DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE);
+ if (joinResult == WAIT_FAILED)
+ LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
+
+ CloseHandle(threadHandle);
+ clearThreadHandleForIdentifier(threadID);
+
+ return joinResult;
+}
+
+void detachThread(ThreadIdentifier threadID)
+{
+ ASSERT(threadID);
+
+ HANDLE threadHandle = threadHandleForIdentifier(threadID);
+ if (threadHandle)
+ CloseHandle(threadHandle);
+ clearThreadHandleForIdentifier(threadID);
+}
+
+ThreadIdentifier currentThread()
+{
+ return static_cast<ThreadIdentifier>(GetCurrentThreadId());
+}
+
+bool isMainThread()
+{
+ return currentThread() == mainThreadIdentifier;
+}
+
+Mutex::Mutex()
+{
+ m_mutex.m_recursionCount = 0;
+ InitializeCriticalSection(&m_mutex.m_internalMutex);
+}
+
+Mutex::~Mutex()
+{
+ DeleteCriticalSection(&m_mutex.m_internalMutex);
+}
+
+void Mutex::lock()
+{
+ EnterCriticalSection(&m_mutex.m_internalMutex);
+ ++m_mutex.m_recursionCount;
+}
+
+bool Mutex::tryLock()
+{
+ // This method is modeled after the behavior of pthread_mutex_trylock,
+ // which will return an error if the lock is already owned by the
+ // current thread. Since the primitive Win32 'TryEnterCriticalSection'
+ // treats this as a successful case, it changes the behavior of several
+ // tests in WebKit that check to see if the current thread already
+ // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
+ DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
+
+ if (result != 0) { // We got the lock
+ // If this thread already had the lock, we must unlock and
+ // return false so that we mimic the behavior of POSIX's
+ // pthread_mutex_trylock:
+ if (m_mutex.m_recursionCount > 0) {
+ LeaveCriticalSection(&m_mutex.m_internalMutex);
+ return false;
+ }
+
+ ++m_mutex.m_recursionCount;
+ return true;
+ }
+
+ return false;
+}
+
+void Mutex::unlock()
+{
+ --m_mutex.m_recursionCount;
+ LeaveCriticalSection(&m_mutex.m_internalMutex);
+}
+
+bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds)
+{
+ // Enter the wait state.
+ DWORD res = WaitForSingleObject(m_blockLock, INFINITE);
+ ASSERT(res == WAIT_OBJECT_0);
+ ++m_waitersBlocked;
+ res = ReleaseSemaphore(m_blockLock, 1, 0);
+ ASSERT(res);
+
+ LeaveCriticalSection(&mutex.m_internalMutex);
+
+ // Main wait - use timeout.
+ bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT);
+
+ res = WaitForSingleObject(m_unblockLock, INFINITE);
+ ASSERT(res == WAIT_OBJECT_0);
+
+ int signalsLeft = m_waitersToUnblock;
+
+ if (m_waitersToUnblock)
+ --m_waitersToUnblock;
+ else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore
+ // timeout or spurious wakeup occured, normalize the m_waitersGone count
+ // this may occur if many calls to wait with a timeout are made and
+ // no call to notify_* is made
+ res = WaitForSingleObject(m_blockLock, INFINITE);
+ ASSERT(res == WAIT_OBJECT_0);
+ m_waitersBlocked -= m_waitersGone;
+ res = ReleaseSemaphore(m_blockLock, 1, 0);
+ ASSERT(res);
+ m_waitersGone = 0;
+ }
+
+ res = ReleaseMutex(m_unblockLock);
+ ASSERT(res);
+
+ if (signalsLeft == 1) {
+ res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate.
+ ASSERT(res);
+ }
+
+ EnterCriticalSection (&mutex.m_internalMutex);
+
+ return !timedOut;
+}
+
+void PlatformCondition::signal(bool unblockAll)
+{
+ unsigned signalsToIssue = 0;
+
+ DWORD res = WaitForSingleObject(m_unblockLock, INFINITE);
+ ASSERT(res == WAIT_OBJECT_0);
+
+ if (m_waitersToUnblock) { // the gate is already closed
+ if (!m_waitersBlocked) { // no-op
+ res = ReleaseMutex(m_unblockLock);
+ ASSERT(res);
+ return;
+ }
+
+ if (unblockAll) {
+ signalsToIssue = m_waitersBlocked;
+ m_waitersToUnblock += m_waitersBlocked;
+ m_waitersBlocked = 0;
+ } else {
+ signalsToIssue = 1;
+ ++m_waitersToUnblock;
+ --m_waitersBlocked;
+ }
+ } else if (m_waitersBlocked > m_waitersGone) {
+ res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate.
+ ASSERT(res == WAIT_OBJECT_0);
+ if (m_waitersGone != 0) {
+ m_waitersBlocked -= m_waitersGone;
+ m_waitersGone = 0;
+ }
+ if (unblockAll) {
+ signalsToIssue = m_waitersBlocked;
+ m_waitersToUnblock = m_waitersBlocked;
+ m_waitersBlocked = 0;
+ } else {
+ signalsToIssue = 1;
+ m_waitersToUnblock = 1;
+ --m_waitersBlocked;
+ }
+ } else { // No-op.
+ res = ReleaseMutex(m_unblockLock);
+ ASSERT(res);
+ return;
+ }
+
+ res = ReleaseMutex(m_unblockLock);
+ ASSERT(res);
+
+ if (signalsToIssue) {
+ res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0);
+ ASSERT(res);
+ }
+}
+
+static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
+
+ThreadCondition::ThreadCondition()
+{
+ m_condition.m_waitersGone = 0;
+ m_condition.m_waitersBlocked = 0;
+ m_condition.m_waitersToUnblock = 0;
+ m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0);
+ m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0);
+ m_condition.m_unblockLock = CreateMutex(0, 0, 0);
+
+ if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_unblockLock) {
+ if (m_condition.m_blockLock)
+ CloseHandle(m_condition.m_blockLock);
+ if (m_condition.m_blockQueue)
+ CloseHandle(m_condition.m_blockQueue);
+ if (m_condition.m_unblockLock)
+ CloseHandle(m_condition.m_unblockLock);
+ }
+}
+
+ThreadCondition::~ThreadCondition()
+{
+ CloseHandle(m_condition.m_blockLock);
+ CloseHandle(m_condition.m_blockQueue);
+ CloseHandle(m_condition.m_unblockLock);
+}
+
+void ThreadCondition::wait(Mutex& mutex)
+{
+ m_condition.timedWait(mutex.impl(), INFINITE);
+}
+
+bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
+{
+ double currentTime = WTF::currentTime();
+
+ // Time is in the past - return immediately.
+ if (absoluteTime < currentTime)
+ return false;
+
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
+ if (intervalMilliseconds >= INT_MAX)
+ intervalMilliseconds = INT_MAX;
+
+ return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
+}
+
+void ThreadCondition::signal()
+{
+ m_condition.signal(false); // Unblock only 1 thread.
+}
+
+void ThreadCondition::broadcast()
+{
+ m_condition.signal(true); // Unblock all threads.
+}
+
+} // namespace WTF
-/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2006 Apple Computer, Inc.
*
#define UNUSED_PARAM(x) (void)x
-#endif // WTF_UnusedParam_h
+#endif /* WTF_UnusedParam_h */
#include "Assertions.h"
#include "FastMalloc.h"
#include "Noncopyable.h"
+#include "NotFound.h"
#include "VectorTraits.h"
#include <limits>
#include <stdlib.h>
#include <utility>
namespace WTF {
-
+
using std::min;
using std::max;
-
+
// WTF_ALIGN_OF / WTF_ALIGNED
-#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW)
-#define WTF_ALIGN_OF(type) __alignof__(type)
-#define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
-#elif COMPILER(MSVC)
-#define WTF_ALIGN_OF(type) __alignof(type)
-#define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
-#else
-#error WTF_ALIGN macros need alignment control.
-#endif
-
-#if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
- typedef char __attribute__((__may_alias__)) AlignedBufferChar;
-#else
- typedef char AlignedBufferChar;
-#endif
-
+ #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW)
+ #define WTF_ALIGN_OF(type) __alignof__(type)
+ #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
+ #elif COMPILER(MSVC)
+ #define WTF_ALIGN_OF(type) __alignof(type)
+ #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
+ #else
+ #error WTF_ALIGN macros need alignment control.
+ #endif
+
+ #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
+ typedef char __attribute__((__may_alias__)) AlignedBufferChar;
+ #else
+ typedef char AlignedBufferChar;
+ #endif
+
template <size_t size, size_t alignment> struct AlignedBuffer;
template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); };
template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
-
+
template <bool needsDestruction, typename T>
class VectorDestructor;
-
+
template<typename T>
struct VectorDestructor<false, T>
{
static void destruct(T*, T*) {}
};
-
+
template<typename T>
struct VectorDestructor<true, T>
{
cur->~T();
}
};
-
+
template <bool needsInitialization, bool canInitializeWithMemset, typename T>
class VectorInitializer;
-
+
template<bool ignore, typename T>
struct VectorInitializer<false, ignore, T>
{
static void initialize(T*, T*) {}
};
-
+
template<typename T>
struct VectorInitializer<true, false, T>
{
new (cur) T;
}
};
-
+
template<typename T>
struct VectorInitializer<true, true, T>
{
memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
}
};
-
+
template <bool canMoveWithMemcpy, typename T>
class VectorMover;
-
+
template<typename T>
struct VectorMover<false, T>
{
}
}
};
-
+
template<typename T>
struct VectorMover<true, T>
{
memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
}
};
-
+
template <bool canCopyWithMemcpy, typename T>
class VectorCopier;
-
+
template<typename T>
struct VectorCopier<false, T>
{
}
}
};
-
+
template<typename T>
struct VectorCopier<true, T>
{
memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
}
};
-
+
template <bool canFillWithMemset, typename T>
class VectorFiller;
-
+
template<typename T>
struct VectorFiller<false, T>
{
}
}
};
-
+
template<typename T>
struct VectorFiller<true, T>
{
return true;
}
};
-
+
template<typename T>
struct VectorComparer<true, T>
{
{
VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
}
-
+
static void initialize(T* begin, T* end)
{
VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
}
-
+
static void move(const T* src, const T* srcEnd, T* dst)
{
VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
}
-
+
static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
{
VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
}
-
+
static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
{
VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
}
-
+
static void uninitializedFill(T* dst, T* dstEnd, const T& val)
{
VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
}
};
-
+
template<typename T>
class VectorBufferBase : Noncopyable {
public:
CRASH();
m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
}
-
+
void deallocateBuffer(T* bufferToDeallocate)
{
if (m_buffer == bufferToDeallocate) {
}
fastFree(bufferToDeallocate);
}
-
+
T* buffer() { return m_buffer; }
const T* buffer() const { return m_buffer; }
T** bufferSlot() { return &m_buffer; }
size_t capacity() const { return m_capacity; }
-
+
T* releaseBuffer()
{
T* buffer = m_buffer;
m_capacity = 0;
return buffer;
}
-
+
protected:
VectorBufferBase()
- : m_buffer(0)
- , m_capacity(0)
+ : m_buffer(0)
+ , m_capacity(0)
{
}
-
+
VectorBufferBase(T* buffer, size_t capacity)
- : m_buffer(buffer)
- , m_capacity(capacity)
+ : m_buffer(buffer)
+ , m_capacity(capacity)
{
}
-
+
~VectorBufferBase()
{
// FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
}
-
+
T* m_buffer;
size_t m_capacity;
};
-
+
template<typename T, size_t inlineCapacity>
class VectorBuffer;
-
+
template<typename T>
class VectorBuffer<T, 0> : private VectorBufferBase<T> {
private:
VectorBuffer()
{
}
-
+
VectorBuffer(size_t capacity)
{
allocateBuffer(capacity);
}
-
+
~VectorBuffer()
{
deallocateBuffer(buffer());
}
void restoreInlineBufferIfNeeded() { }
-
+
using Base::allocateBuffer;
using Base::deallocateBuffer;
-
+
using Base::buffer;
using Base::bufferSlot;
using Base::capacity;
-
+
using Base::releaseBuffer;
private:
using Base::m_buffer;
using Base::m_capacity;
};
-
+
template<typename T, size_t inlineCapacity>
class VectorBuffer : private VectorBufferBase<T> {
private:
typedef VectorBufferBase<T> Base;
public:
VectorBuffer()
- : Base(inlineBuffer(), inlineCapacity)
+ : Base(inlineBuffer(), inlineCapacity)
{
}
-
+
VectorBuffer(size_t capacity)
- : Base(inlineBuffer(), inlineCapacity)
+ : Base(inlineBuffer(), inlineCapacity)
{
allocateBuffer(capacity);
}
-
+
~VectorBuffer()
{
deallocateBuffer(buffer());
}
-
+
void allocateBuffer(size_t newCapacity)
{
if (newCapacity > inlineCapacity)
Base::allocateBuffer(newCapacity);
}
-
+
void deallocateBuffer(T* bufferToDeallocate)
{
if (bufferToDeallocate == inlineBuffer())
m_buffer = inlineBuffer();
m_capacity = inlineCapacity;
}
-
+
using Base::buffer;
using Base::bufferSlot;
using Base::capacity;
-
+
T* releaseBuffer()
{
if (buffer() == inlineBuffer())
return 0;
return Base::releaseBuffer();
}
-
+
private:
using Base::m_buffer;
using Base::m_capacity;
-
+
static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
+#if PLATFORM(ARM)
+ // FIXME: <rdar://problem/6546253&6546260>
+ T* inlineBuffer() { return reinterpret_cast<T*>(static_cast<void*>(m_inlineBuffer.buffer)); }
+#else
T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); }
-
+#endif
+
AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
};
-
+
template<typename T, size_t inlineCapacity = 0>
class Vector {
-private:
- typedef VectorBuffer<T, inlineCapacity> Buffer;
- typedef VectorTypeOperations<T> TypeOperations;
-
-public:
- typedef T ValueType;
-
- typedef T* iterator;
- typedef const T* const_iterator;
-
- Vector()
- : m_size(0)
+ private:
+ typedef VectorBuffer<T, inlineCapacity> Buffer;
+ typedef VectorTypeOperations<T> TypeOperations;
+
+ public:
+ typedef T ValueType;
+
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ Vector()
+ : m_size(0)
+ {
+ }
+
+ explicit Vector(size_t size)
+ : m_size(size)
+ , m_buffer(size)
+ {
+ if (begin())
+ TypeOperations::initialize(begin(), end());
+ }
+
+ ~Vector()
+ {
+ if (m_size) shrink(0);
+ }
+
+ Vector(const Vector&);
+ template<size_t otherCapacity>
+ Vector(const Vector<T, otherCapacity>&);
+
+ Vector& operator=(const Vector&);
+ template<size_t otherCapacity>
+ Vector& operator=(const Vector<T, otherCapacity>&);
+
+ size_t size() const { return m_size; }
+ size_t capacity() const { return m_buffer.capacity(); }
+ bool isEmpty() const { return !size(); }
+
+ T& at(size_t i)
+ {
+ ASSERT(i < size());
+ return m_buffer.buffer()[i];
+ }
+ const T& at(size_t i) const
+ {
+ ASSERT(i < size());
+ return m_buffer.buffer()[i];
+ }
+
+ T& operator[](size_t i) { return at(i); }
+ const T& operator[](size_t i) const { return at(i); }
+
+ T* data() { return m_buffer.buffer(); }
+ const T* data() const { return m_buffer.buffer(); }
+ T** dataSlot() { return m_buffer.bufferSlot(); }
+
+ iterator begin() { return data(); }
+ iterator end() { return begin() + m_size; }
+ const_iterator begin() const { return data(); }
+ const_iterator end() const { return begin() + m_size; }
+
+ T& first() { return at(0); }
+ const T& first() const { return at(0); }
+ T& last() { return at(size() - 1); }
+ const T& last() const { return at(size() - 1); }
+
+ template<typename U> size_t find(const U&) const;
+
+ void shrink(size_t size);
+ void grow(size_t size);
+ void resize(size_t size);
+ void reserveCapacity(size_t newCapacity);
+ void reserveInitialCapacity(size_t initialCapacity);
+ void shrinkCapacity(size_t newCapacity);
+ void shrinkToFit() { shrinkCapacity(size()); }
+
+ void clear() { shrinkCapacity(0); }
+
+ template<typename U> void append(const U*, size_t);
+ template<typename U> void append(const U&);
+ template<typename U> void uncheckedAppend(const U& val);
+ template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
+
+ template<typename U> void insert(size_t position, const U*, size_t);
+ template<typename U> void insert(size_t position, const U&);
+ template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
+
+ template<typename U> void prepend(const U*, size_t);
+ template<typename U> void prepend(const U&);
+ template<typename U, size_t c> void prepend(const Vector<U, c>&);
+
+ void remove(size_t position);
+ void remove(size_t position, size_t length);
+
+ void removeLast()
+ {
+ ASSERT(!isEmpty());
+ shrink(size() - 1);
+ }
+
+ Vector(size_t size, const T& val)
+ : m_size(size)
+ , m_buffer(size)
+ {
+ if (begin())
+ TypeOperations::uninitializedFill(begin(), end(), val);
+ }
+
+ void fill(const T&, size_t);
+ void fill(const T& val) { fill(val, size()); }
+
+ template<typename Iterator> void appendRange(Iterator start, Iterator end);
+
+ T* releaseBuffer();
+
+ void swap(Vector<T, inlineCapacity>& other)
+ {
+ std::swap(m_size, other.m_size);
+ m_buffer.swap(other.m_buffer);
+ }
+
+ private:
+ void expandCapacity(size_t newMinCapacity);
+ const T* expandCapacity(size_t newMinCapacity, const T*);
+ template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
+
+ size_t m_size;
+ Buffer m_buffer;
+ };
+
+ template<typename T, size_t inlineCapacity>
+ Vector<T, inlineCapacity>::Vector(const Vector& other)
+ : m_size(other.size())
+ , m_buffer(other.capacity())
{
+ if (begin())
+ TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
-
- explicit Vector(size_t size)
- : m_size(size)
- , m_buffer(size)
+
+ template<typename T, size_t inlineCapacity>
+ template<size_t otherCapacity>
+ Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
+ : m_size(other.size())
+ , m_buffer(other.capacity())
{
if (begin())
- TypeOperations::initialize(begin(), end());
+ TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
-
- ~Vector()
+
+ template<typename T, size_t inlineCapacity>
+ Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
{
- if (m_size) shrink(0);
+ if (&other == this)
+ return *this;
+
+ if (size() > other.size())
+ shrink(other.size());
+ else if (other.size() > capacity()) {
+ clear();
+ reserveCapacity(other.size());
+ if (!begin())
+ return *this;
+ }
+
+ std::copy(other.begin(), other.begin() + size(), begin());
+ TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
+ m_size = other.size();
+
+ return *this;
}
-
- Vector(const Vector&);
- template<size_t otherCapacity>
- Vector(const Vector<T, otherCapacity>&);
-
- Vector& operator=(const Vector&);
+
+ template<typename T, size_t inlineCapacity>
template<size_t otherCapacity>
- Vector& operator=(const Vector<T, otherCapacity>&);
-
- size_t size() const { return m_size; }
- size_t capacity() const { return m_buffer.capacity(); }
- bool isEmpty() const { return !size(); }
-
- T& at(size_t i)
- {
- ASSERT(i < size());
- return m_buffer.buffer()[i];
- }
- const T& at(size_t i) const
+ Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
{
- ASSERT(i < size());
- return m_buffer.buffer()[i];
+ if (&other == this)
+ return *this;
+
+ if (size() > other.size())
+ shrink(other.size());
+ else if (other.size() > capacity()) {
+ clear();
+ reserveCapacity(other.size());
+ if (!begin())
+ return *this;
+ }
+
+ std::copy(other.begin(), other.begin() + size(), begin());
+ TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
+ m_size = other.size();
+
+ return *this;
}
-
- T& operator[](size_t i) { return at(i); }
- const T& operator[](size_t i) const { return at(i); }
-
- T* data() { return m_buffer.buffer(); }
- const T* data() const { return m_buffer.buffer(); }
- T** dataSlot() { return m_buffer.bufferSlot(); }
-
- iterator begin() { return data(); }
- iterator end() { return begin() + m_size; }
- const_iterator begin() const { return data(); }
- const_iterator end() const { return begin() + m_size; }
-
- T& first() { return at(0); }
- const T& first() const { return at(0); }
- T& last() { return at(size() - 1); }
- const T& last() const { return at(size() - 1); }
-
- template<typename U> size_t find(const U&) const;
-
- void shrink(size_t size);
- void grow(size_t size);
- void resize(size_t size);
- void reserveCapacity(size_t newCapacity);
- void shrinkCapacity(size_t newCapacity);
- void shrinkToFit() { shrinkCapacity(size()); }
-
- void clear() { shrinkCapacity(0); }
-
- template<typename U> void append(const U*, size_t);
- template<typename U> void append(const U&);
- template<typename U> void uncheckedAppend(const U& val);
- template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
-
- template<typename U> void insert(size_t position, const U*, size_t);
- template<typename U> void insert(size_t position, const U&);
- template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
-
- template<typename U> void prepend(const U*, size_t);
- template<typename U> void prepend(const U&);
- template<typename U, size_t c> void prepend(const Vector<U, c>&);
-
- void remove(size_t position);
- void remove(size_t position, size_t length);
-
- void removeLast()
+
+ template<typename T, size_t inlineCapacity>
+ template<typename U>
+ size_t Vector<T, inlineCapacity>::find(const U& value) const
{
- ASSERT(!isEmpty());
- shrink(size() - 1);
+ for (size_t i = 0; i < size(); ++i) {
+ if (at(i) == value)
+ return i;
+ }
+ return notFound;
}
-
- Vector(size_t size, const T& val)
- : m_size(size)
- , m_buffer(size)
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
{
- if (begin())
- TypeOperations::uninitializedFill(begin(), end(), val);
+ if (size() > newSize)
+ shrink(newSize);
+ else if (newSize > capacity()) {
+ clear();
+ reserveCapacity(newSize);
+ if (!begin())
+ return;
+ }
+
+ std::fill(begin(), end(), val);
+ TypeOperations::uninitializedFill(end(), begin() + newSize, val);
+ m_size = newSize;
}
-
- void fill(const T&, size_t);
- void fill(const T& val) { fill(val, size()); }
-
- template<typename Iterator> void appendRange(Iterator start, Iterator end);
-
- T* releaseBuffer();
-
- void swap(Vector<T, inlineCapacity>& other)
+
+ template<typename T, size_t inlineCapacity>
+ template<typename Iterator>
+ void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
{
- std::swap(m_size, other.m_size);
- m_buffer.swap(other.m_buffer);
+ for (Iterator it = start; it != end; ++it)
+ append(*it);
}
-
-private:
- void expandCapacity(size_t newMinCapacity);
- const T* expandCapacity(size_t newMinCapacity, const T*);
- template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
-
- size_t m_size;
- Buffer m_buffer;
-};
-
-template<typename T, size_t inlineCapacity>
-Vector<T, inlineCapacity>::Vector(const Vector& other)
-: m_size(other.size())
-, m_buffer(other.capacity())
-{
- if (begin())
- TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-}
-
-template<typename T, size_t inlineCapacity>
-template<size_t otherCapacity>
-Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
-: m_size(other.size())
-, m_buffer(other.capacity())
-{
- if (begin())
- TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-}
-
-template<typename T, size_t inlineCapacity>
-Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
-{
- if (&other == this)
- return *this;
-
- if (size() > other.size())
- shrink(other.size());
- else if (other.size() > capacity()) {
- clear();
- reserveCapacity(other.size());
- if (!begin())
- return *this;
- }
-
- std::copy(other.begin(), other.begin() + size(), begin());
- TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
- m_size = other.size();
-
- return *this;
-}
-
-template<typename T, size_t inlineCapacity>
-template<size_t otherCapacity>
-Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
-{
- if (&other == this)
- return *this;
-
- if (size() > other.size())
- shrink(other.size());
- else if (other.size() > capacity()) {
- clear();
- reserveCapacity(other.size());
- if (!begin())
- return *this;
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
+ {
+ reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
}
- std::copy(other.begin(), other.begin() + size(), begin());
- TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
- m_size = other.size();
-
- return *this;
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
-{
- if (size() > newSize)
- shrink(newSize);
- else if (newSize > capacity()) {
- clear();
- reserveCapacity(newSize);
- if (!begin())
- return;
+ template<typename T, size_t inlineCapacity>
+ const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
+ {
+ if (ptr < begin() || ptr >= end()) {
+ expandCapacity(newMinCapacity);
+ return ptr;
+ }
+ size_t index = ptr - begin();
+ expandCapacity(newMinCapacity);
+ return begin() + index;
}
-
- std::fill(begin(), end(), val);
- TypeOperations::uninitializedFill(end(), begin() + newSize, val);
- m_size = newSize;
-}
-
-template<typename T, size_t inlineCapacity>
-template<typename Iterator>
-void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
-{
- for (Iterator it = start; it != end; ++it)
- append(*it);
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
-{
- reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
-}
-
-template<typename T, size_t inlineCapacity>
-const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
-{
- if (ptr < begin() || ptr >= end()) {
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
+ {
expandCapacity(newMinCapacity);
return ptr;
}
- size_t index = ptr - begin();
- expandCapacity(newMinCapacity);
- return begin() + index;
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
-{
- expandCapacity(newMinCapacity);
- return ptr;
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::resize(size_t size)
-{
- if (size <= m_size)
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::resize(size_t size)
+ {
+ if (size <= m_size)
+ TypeOperations::destruct(begin() + size, end());
+ else {
+ if (size > capacity())
+ expandCapacity(size);
+ if (begin())
+ TypeOperations::initialize(end(), begin() + size);
+ }
+
+ m_size = size;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::shrink(size_t size)
+ {
+ ASSERT(size <= m_size);
TypeOperations::destruct(begin() + size, end());
- else {
+ m_size = size;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::grow(size_t size)
+ {
+ ASSERT(size >= m_size);
if (size > capacity())
expandCapacity(size);
if (begin())
TypeOperations::initialize(end(), begin() + size);
+ m_size = size;
}
-
- m_size = size;
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::shrink(size_t size)
-{
- ASSERT(size <= m_size);
- TypeOperations::destruct(begin() + size, end());
- m_size = size;
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::grow(size_t size)
-{
- ASSERT(size >= m_size);
- if (size > capacity())
- expandCapacity(size);
- if (begin())
- TypeOperations::initialize(end(), begin() + size);
- m_size = size;
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
-{
- if (newCapacity <= capacity())
- return;
- T* oldBuffer = begin();
- T* oldEnd = end();
- m_buffer.allocateBuffer(newCapacity);
- if (begin())
- TypeOperations::move(oldBuffer, oldEnd, begin());
- m_buffer.deallocateBuffer(oldBuffer);
-}
-
-template<typename T, size_t inlineCapacity>
-void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
-{
- if (newCapacity >= capacity())
- return;
-
- if (newCapacity < size())
- shrink(newCapacity);
-
- T* oldBuffer = begin();
- if (newCapacity > 0) {
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
+ {
+ if (newCapacity <= capacity())
+ return;
+ T* oldBuffer = begin();
T* oldEnd = end();
m_buffer.allocateBuffer(newCapacity);
- if (begin() != oldBuffer)
+ if (begin())
TypeOperations::move(oldBuffer, oldEnd, begin());
+ m_buffer.deallocateBuffer(oldBuffer);
}
- m_buffer.deallocateBuffer(oldBuffer);
- m_buffer.restoreInlineBufferIfNeeded();
-}
-
-// Templatizing these is better than just letting the conversion happen implicitly,
-// because for instance it allows a PassRefPtr to be appended to a RefPtr vector
-// without refcount thrash.
-
-template<typename T, size_t inlineCapacity> template<typename U>
-void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
-{
- size_t newSize = m_size + dataSize;
- if (newSize > capacity()) {
- data = expandCapacity(newSize, data);
- if (!begin())
- return;
+ template<typename T, size_t inlineCapacity>
+ inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
+ {
+ ASSERT(!m_size);
+ ASSERT(capacity() == inlineCapacity);
+ if (initialCapacity > inlineCapacity)
+ m_buffer.allocateBuffer(initialCapacity);
}
- T* dest = end();
- for (size_t i = 0; i < dataSize; ++i)
- new (&dest[i]) T(data[i]);
- m_size = newSize;
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-inline void Vector<T, inlineCapacity>::append(const U& val)
-{
- const U* ptr = &val;
- if (size() == capacity()) {
- ptr = expandCapacity(size() + 1, ptr);
- if (!begin())
+
+ template<typename T, size_t inlineCapacity>
+ void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
+ {
+ if (newCapacity >= capacity())
return;
+
+ if (newCapacity < size())
+ shrink(newCapacity);
+
+ T* oldBuffer = begin();
+ if (newCapacity > 0) {
+ T* oldEnd = end();
+ m_buffer.allocateBuffer(newCapacity);
+ if (begin() != oldBuffer)
+ TypeOperations::move(oldBuffer, oldEnd, begin());
+ }
+
+ m_buffer.deallocateBuffer(oldBuffer);
+ m_buffer.restoreInlineBufferIfNeeded();
}
-
+
+ // Templatizing these is better than just letting the conversion happen implicitly,
+ // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
+ // without refcount thrash.
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
+ {
+ size_t newSize = m_size + dataSize;
+ if (newSize > capacity()) {
+ data = expandCapacity(newSize, data);
+ if (!begin())
+ return;
+ }
+ if (newSize < m_size)
+ CRASH();
+ T* dest = end();
+ for (size_t i = 0; i < dataSize; ++i)
+ new (&dest[i]) T(data[i]);
+ m_size = newSize;
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ inline void Vector<T, inlineCapacity>::append(const U& val)
+ {
+ const U* ptr = &val;
+ if (size() == capacity()) {
+ ptr = expandCapacity(size() + 1, ptr);
+ if (!begin())
+ return;
+ }
+
#if COMPILER(MSVC7)
- // FIXME: MSVC7 generates compilation errors when trying to assign
- // a pointer to a Vector of its base class (i.e. can't downcast). So far
- // I've been unable to determine any logical reason for this, so I can
- // only assume it is a bug with the compiler. Casting is a bad solution,
- // however, because it subverts implicit conversions, so a better
- // one is needed.
- new (end()) T(static_cast<T>(*ptr));
+ // FIXME: MSVC7 generates compilation errors when trying to assign
+ // a pointer to a Vector of its base class (i.e. can't downcast). So far
+ // I've been unable to determine any logical reason for this, so I can
+ // only assume it is a bug with the compiler. Casting is a bad solution,
+ // however, because it subverts implicit conversions, so a better
+ // one is needed.
+ new (end()) T(static_cast<T>(*ptr));
#else
- new (end()) T(*ptr);
+ new (end()) T(*ptr);
#endif
- ++m_size;
-}
-
-// This version of append saves a branch in the case where you know that the
-// vector's capacity is large enough for the append to succeed.
-
-template<typename T, size_t inlineCapacity> template<typename U>
-inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
-{
- ASSERT(size() < capacity());
- const U* ptr = &val;
- new (end()) T(*ptr);
- ++m_size;
-}
-
-// This method should not be called append, a better name would be appendElements.
-// It could also be eliminated entirely, and call sites could just use
-// appendRange(val.begin(), val.end()).
-template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
-inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
-{
- append(val.begin(), val.size());
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
-{
- ASSERT(position <= size());
- size_t newSize = m_size + dataSize;
- if (newSize > capacity()) {
- data = expandCapacity(newSize, data);
- if (!begin())
- return;
+ ++m_size;
}
- T* spot = begin() + position;
- TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
- for (size_t i = 0; i < dataSize; ++i)
- new (&spot[i]) T(data[i]);
- m_size = newSize;
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
-{
- ASSERT(position <= size());
- const U* data = &val;
- if (size() == capacity()) {
- data = expandCapacity(size() + 1, data);
- if (!begin())
- return;
+
+ // This version of append saves a branch in the case where you know that the
+ // vector's capacity is large enough for the append to succeed.
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
+ {
+ ASSERT(size() < capacity());
+ const U* ptr = &val;
+ new (end()) T(*ptr);
+ ++m_size;
+ }
+
+ // This method should not be called append, a better name would be appendElements.
+ // It could also be eliminated entirely, and call sites could just use
+ // appendRange(val.begin(), val.end()).
+ template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
+ inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
+ {
+ append(val.begin(), val.size());
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
+ {
+ ASSERT(position <= size());
+ size_t newSize = m_size + dataSize;
+ if (newSize > capacity()) {
+ data = expandCapacity(newSize, data);
+ if (!begin())
+ return;
+ }
+ if (newSize < m_size)
+ CRASH();
+ T* spot = begin() + position;
+ TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
+ for (size_t i = 0; i < dataSize; ++i)
+ new (&spot[i]) T(data[i]);
+ m_size = newSize;
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
+ {
+ ASSERT(position <= size());
+ const U* data = &val;
+ if (size() == capacity()) {
+ data = expandCapacity(size() + 1, data);
+ if (!begin())
+ return;
+ }
+ T* spot = begin() + position;
+ TypeOperations::moveOverlapping(spot, end(), spot + 1);
+ new (spot) T(*data);
+ ++m_size;
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U, size_t c>
+ inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
+ {
+ insert(position, val.begin(), val.size());
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
+ {
+ insert(0, data, dataSize);
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U>
+ inline void Vector<T, inlineCapacity>::prepend(const U& val)
+ {
+ insert(0, val);
+ }
+
+ template<typename T, size_t inlineCapacity> template<typename U, size_t c>
+ inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
+ {
+ insert(0, val.begin(), val.size());
}
- T* spot = begin() + position;
- TypeOperations::moveOverlapping(spot, end(), spot + 1);
- new (spot) T(*data);
- ++m_size;
-}
-
-template<typename T, size_t inlineCapacity> template<typename U, size_t c>
-inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
-{
- insert(position, val.begin(), val.size());
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
-{
- insert(0, data, dataSize);
-}
-
-template<typename T, size_t inlineCapacity> template<typename U>
-inline void Vector<T, inlineCapacity>::prepend(const U& val)
-{
- insert(0, val);
-}
-
-template<typename T, size_t inlineCapacity> template<typename U, size_t c>
-inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
-{
- insert(0, val.begin(), val.size());
-}
-
-template<typename T, size_t inlineCapacity>
-inline void Vector<T, inlineCapacity>::remove(size_t position)
-{
- ASSERT(position < size());
- T* spot = begin() + position;
- spot->~T();
- TypeOperations::moveOverlapping(spot + 1, end(), spot);
- --m_size;
-}
-
-template<typename T, size_t inlineCapacity>
-inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
-{
- ASSERT(position < size());
- ASSERT(position + length < size());
- T* beginSpot = begin() + position;
- T* endSpot = beginSpot + length;
- TypeOperations::destruct(beginSpot, endSpot);
- TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
- m_size -= length;
-}
-
-template<typename T, size_t inlineCapacity>
-inline T* Vector<T, inlineCapacity>::releaseBuffer()
-{
- T* buffer = m_buffer.releaseBuffer();
- if (inlineCapacity && !buffer && m_size) {
- // If the vector had some data, but no buffer to release,
- // that means it was using the inline buffer. In that case,
- // we create a brand new buffer so the caller always gets one.
- size_t bytes = m_size * sizeof(T);
- buffer = static_cast<T*>(fastMalloc(bytes));
- memcpy(buffer, data(), bytes);
- }
- m_size = 0;
- return buffer;
-}
-
-template<typename T, size_t inlineCapacity>
-void deleteAllValues(const Vector<T, inlineCapacity>& collection)
-{
- typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
- iterator end = collection.end();
- for (iterator it = collection.begin(); it != end; ++it)
- delete *it;
-}
-
-template<typename T, size_t inlineCapacity>
-inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
-{
- a.swap(b);
-}
-
-template<typename T, size_t inlineCapacity>
-bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
-{
- if (a.size() != b.size())
- return false;
- return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
-}
-
-template<typename T, size_t inlineCapacity>
-inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
-{
- return !(a == b);
-}
+ template<typename T, size_t inlineCapacity>
+ inline void Vector<T, inlineCapacity>::remove(size_t position)
+ {
+ ASSERT(position < size());
+ T* spot = begin() + position;
+ spot->~T();
+ TypeOperations::moveOverlapping(spot + 1, end(), spot);
+ --m_size;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
+ {
+ ASSERT(position < size());
+ ASSERT(position + length < size());
+ T* beginSpot = begin() + position;
+ T* endSpot = beginSpot + length;
+ TypeOperations::destruct(beginSpot, endSpot);
+ TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
+ m_size -= length;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ inline T* Vector<T, inlineCapacity>::releaseBuffer()
+ {
+ T* buffer = m_buffer.releaseBuffer();
+ if (inlineCapacity && !buffer && m_size) {
+ // If the vector had some data, but no buffer to release,
+ // that means it was using the inline buffer. In that case,
+ // we create a brand new buffer so the caller always gets one.
+ size_t bytes = m_size * sizeof(T);
+ buffer = static_cast<T*>(fastMalloc(bytes));
+ memcpy(buffer, data(), bytes);
+ }
+ m_size = 0;
+ return buffer;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ void deleteAllValues(const Vector<T, inlineCapacity>& collection)
+ {
+ typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
+ iterator end = collection.end();
+ for (iterator it = collection.begin(); it != end; ++it)
+ delete *it;
+ }
+
+ template<typename T, size_t inlineCapacity>
+ inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
+ {
+ a.swap(b);
+ }
+
+ template<typename T, size_t inlineCapacity>
+ bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
+ {
+ if (a.size() != b.size())
+ return false;
+
+ return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
+ }
+
+ template<typename T, size_t inlineCapacity>
+ inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
+ {
+ return !(a == b);
+ }
} // namespace WTF
-// -*- mode: c++; c-basic-offset: 4 -*-
/*
- * This file is part of the KDE libraries
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
#include "RefPtr.h"
#include <utility>
+#include <memory>
using std::pair;
template<typename P>
struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { };
+ template<typename P>
+ struct VectorTraits<std::auto_ptr<P> > : SimpleClassVectorTraits { };
+
template<typename First, typename Second>
struct VectorTraits<pair<First, Second> >
{
--- /dev/null
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ * Copyright (C) 2002, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to
+ David M. Gay
+ Bell Laboratories, Room 2C-463
+ 600 Mountain Avenue
+ Murray Hill, NJ 07974-0636
+ U.S.A.
+ dmg@bell-labs.com
+ */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE.
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and Honor_FLT_ROUNDS is not #defined.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define USE_LONG_LONG on machines that have a "long long"
+ * integer type (of >= 64 bits), and performance testing shows that
+ * it is faster than 32-bit fallback (which is often not the case
+ * on 32-bit machines). On such machines, you can #define Just_16
+ * to store 16 bits per 32-bit int32_t when doing high-precision integer
+ * arithmetic. Whether this speeds things up or slows things down
+ * depends on the machine and the number being converted.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
+ * Infinity and NaN (case insensitively). On some systems (e.g.,
+ * some HP systems), it may be necessary to #define NAN_WORD0
+ * appropriately -- to the most significant word of a quiet NaN.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtod also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits and spaces;
+ * if there is only one string of hexadecimal digits, it is taken
+ * for the 52 fraction bits of the resulting NaN; if there are two
+ * or more strings of hex digits, the first is for the high 20 bits,
+ * the second and subsequent for the low 32 bits, with intervening
+ * white space ignored; but if this results in none of the 52
+ * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
+ * and NAN_WORD1 are used instead.
+ * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
+ * avoids underflows on inputs whose result does not underflow.
+ * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
+ * floating-point numbers and flushes underflows to zero rather
+ * than implementing gradual underflow, then you must also #define
+ * Sudden_Underflow.
+ * #define YES_ALIAS to permit aliasing certain double values with
+ * arrays of ULongs. This leads to slightly better code with
+ * some compilers and was always used prior to 19990916, but it
+ * is not strictly legal and can cause trouble with aggressively
+ * optimizing compilers (e.g., gcc 2.95.1 under -O2).
+ * #define SET_INEXACT if IEEE arithmetic is being used and extra
+ * computation should be done to set the inexact flag when the
+ * result is inexact and avoid setting inexact when the result
+ * is exact. In this case, dtoa.c must be compiled in
+ * an environment, perhaps provided by #include "dtoa.c" in a
+ * suitable wrapper, that defines two functions,
+ * int get_inexact(void);
+ * void clear_inexact(void);
+ * such that get_inexact() returns a nonzero value if the
+ * inexact bit is already set, and clear_inexact() sets the
+ * inexact bit to 0. When SET_INEXACT is #defined, strtod
+ * also does extra computations to set the underflow and overflow
+ * flags when appropriate (i.e., when the result is tiny and
+ * inexact or when it is a numeric value rounded to +-infinity).
+ * #define NO_ERRNO if strtod should not assign errno = ERANGE when
+ * the result overflows to +-Infinity or underflows to 0.
+ */
+
+#include "config.h"
+#include "dtoa.h"
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#else
+#define NO_ERRNO
+#endif
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Threading.h>
+
+#if COMPILER(MSVC)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4245)
+#pragma warning(disable: 4554)
+#endif
+
+#if PLATFORM(BIG_ENDIAN)
+#define IEEE_MC68k
+#elif PLATFORM(MIDDLE_ENDIAN)
+#define IEEE_ARM
+#else
+#define IEEE_8087
+#endif
+
+#define INFNAN_CHECK
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1
+Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined.
+#endif
+
+namespace WTF {
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+Mutex* s_dtoaP5Mutex;
+#endif
+
+typedef union { double d; uint32_t L[2]; } U;
+
+#ifdef YES_ALIAS
+#define dval(x) x
+#ifdef IEEE_8087
+#define word0(x) ((uint32_t*)&x)[1]
+#define word1(x) ((uint32_t*)&x)[0]
+#else
+#define word0(x) ((uint32_t*)&x)[0]
+#define word1(x) ((uint32_t*)&x)[1]
+#endif
+#else
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) || defined(IEEE_ARM)
+#define Storeinc(a,b,c) (((unsigned short*)a)[1] = (unsigned short)b, ((unsigned short*)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short*)a)[0] = (unsigned short)b, ((unsigned short*)a)[1] = (unsigned short)c, a++)
+#endif
+
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+
+#if !defined(NO_IEEE_Scale)
+#undef Avoid_Underflow
+#define Avoid_Underflow
+#endif
+
+#if !defined(Flt_Rounds)
+#if defined(FLT_ROUNDS)
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+
+#define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
+#define Big1 0xffffffff
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#if PLATFORM(PPC64) || PLATFORM(X86_64)
+// 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
+#define USE_LONG_LONG
+#endif
+
+#ifndef USE_LONG_LONG
+#ifdef Just_16
+#undef Pack_32
+/* When Pack_32 is not defined, we store 16 bits per 32-bit int32_t.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per int32_t.
+ */
+#endif
+#endif
+
+#define Kmax 15
+
+struct Bigint {
+ struct Bigint* next;
+ int k, maxwds, sign, wds;
+ uint32_t x[1];
+};
+
+static Bigint* Balloc(int k)
+{
+ int x = 1 << k;
+ Bigint* rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t));
+ rv->k = k;
+ rv->maxwds = x;
+ rv->next = 0;
+ rv->sign = rv->wds = 0;
+
+ return rv;
+}
+
+static void Bfree(Bigint* v)
+{
+ fastFree(v);
+}
+
+#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int))
+
+static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */
+{
+#ifdef USE_LONG_LONG
+ unsigned long long carry;
+#else
+ uint32_t carry;
+#endif
+
+ int wds = b->wds;
+ uint32_t* x = b->x;
+ int i = 0;
+ carry = a;
+ do {
+#ifdef USE_LONG_LONG
+ unsigned long long y = *x * (unsigned long long)m + carry;
+ carry = y >> 32;
+ *x++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ uint32_t xi = *x;
+ uint32_t y = (xi & 0xffff) * m + carry;
+ uint32_t z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ uint32_t y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ } while (++i < wds);
+
+ if (carry) {
+ if (wds >= b->maxwds) {
+ Bigint* b1 = Balloc(b->k + 1);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = (uint32_t)carry;
+ b->wds = wds;
+ }
+ return b;
+}
+
+static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9)
+{
+ int k;
+ int32_t y;
+ int32_t x = (nd + 8) / 9;
+
+ for (k = 0, y = 1; x > y; y <<= 1, k++) { }
+#ifdef Pack_32
+ Bigint* b = Balloc(k);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ Bigint* b = Balloc(k + 1);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ int i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do {
+ b = multadd(b, 10, *s++ - '0');
+ } while (++i < nd0);
+ s++;
+ } else
+ s += 10;
+ for (; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+}
+
+static int hi0bits(uint32_t x)
+{
+ int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+}
+
+static int lo0bits (uint32_t* y)
+{
+ int k;
+ uint32_t x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x & 1)
+ return 32;
+ }
+ *y = x;
+ return k;
+}
+
+static Bigint* i2b(int i)
+{
+ Bigint* b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+}
+
+static Bigint* mult(Bigint* a, Bigint* b)
+{
+ Bigint* c;
+ int k, wa, wb, wc;
+ uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ uint32_t y;
+#ifdef USE_LONG_LONG
+ unsigned long long carry, z;
+#else
+ uint32_t carry, z;
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ for (x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef USE_LONG_LONG
+ for (; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (unsigned long long)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = (uint32_t)z & 0xffffffffUL;
+ } while (x < xae);
+ *xc = (uint32_t)carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for (; xb < xbe; xb++, xc0++) {
+ if ((y = *xb & 0xffff)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ } while (x < xae);
+ *xc = carry;
+ }
+ if ((y = *xb >> 16)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ uint32_t z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ } while (x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ } while (x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
+ c->wds = wc;
+ return c;
+}
+
+static Bigint* p5s;
+static int p5s_count;
+
+static Bigint* pow5mult(Bigint* b, int k)
+{
+ static int p05[3] = { 5, 25, 125 };
+
+ if (int i = k & 3)
+ b = multadd(b, p05[i - 1], 0);
+
+ if (!(k >>= 2))
+ return b;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->lock();
+#endif
+ Bigint* p5 = p5s;
+ if (!p5) {
+ /* first time */
+ p5 = p5s = i2b(625);
+ p5s_count = 1;
+ }
+ int p5s_count_local = p5s_count;
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->unlock();
+#endif
+ int p5s_used = 0;
+
+ for (;;) {
+ if (k & 1) {
+ Bigint* b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+
+ if (++p5s_used == p5s_count_local) {
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->lock();
+#endif
+ if (p5s_used == p5s_count) {
+ ASSERT(!p5->next);
+ p5->next = mult(p5, p5);
+ ++p5s_count;
+ }
+
+ p5s_count_local = p5s_count;
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex->unlock();
+#endif
+ }
+ p5 = p5->next;
+ }
+
+ return b;
+}
+
+static Bigint* lshift(Bigint* b, int k)
+{
+ Bigint* result = b;
+
+#ifdef Pack_32
+ int n = k >> 5;
+#else
+ int n = k >> 4;
+#endif
+
+ int k1 = b->k;
+ int n1 = n + b->wds + 1;
+ for (int i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ if (b->k < k1)
+ result = Balloc(k1);
+
+ const uint32_t* srcStart = b->x;
+ uint32_t* dstStart = result->x;
+ const uint32_t* src = srcStart + b->wds - 1;
+ uint32_t* dst = dstStart + n1 - 1;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ uint32_t hiSubword = 0;
+ int s = 32 - k;
+ for (; src >= srcStart; --src) {
+ *dst-- = hiSubword | *src >> s;
+ hiSubword = *src << k;
+ }
+ *dst = hiSubword;
+ ASSERT(dst == dstStart + n);
+ result->wds = b->wds + n + (result->x[n1 - 1] != 0);
+ }
+#else
+ if (k &= 0xf) {
+ uint32_t hiSubword = 0;
+ int s = 16 - k;
+ for (; src >= srcStart; --src) {
+ *dst-- = hiSubword | *src >> s;
+ hiSubword = (*src << k) & 0xffff;
+ }
+ *dst = hiSubword;
+ ASSERT(dst == dstStart + n);
+ result->wds = b->wds + n + (result->x[n1 - 1] != 0);
+ }
+ #endif
+ else {
+ do {
+ *--dst = *src--;
+ } while (src >= srcStart);
+ result->wds = b->wds + n;
+ }
+ for (dst = dstStart + n; dst != dstStart; )
+ *--dst = 0;
+
+ if (result != b)
+ Bfree(b);
+ return result;
+}
+
+static int cmp(Bigint* a, Bigint* b)
+{
+ uint32_t *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+ ASSERT(i <= 1 || a->x[i - 1]);
+ ASSERT(j <= 1 || b->x[j - 1]);
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for (;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+}
+
+static Bigint* diff(Bigint* a, Bigint* b)
+{
+ Bigint* c;
+ int i, wa, wb;
+ uint32_t *xa, *xae, *xb, *xbe, *xc;
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ } else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+#ifdef USE_LONG_LONG
+ unsigned long long borrow = 0;
+ do {
+ unsigned long long y = (unsigned long long)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *xc++ = (uint32_t)y & 0xffffffffUL;
+ } while (xb < xbe);
+ while (xa < xae) {
+ unsigned long long y = *xa++ - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *xc++ = (uint32_t)y & 0xffffffffUL;
+ }
+#else
+ uint32_t borrow = 0;
+#ifdef Pack_32
+ do {
+ uint32_t y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ uint32_t z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ } while (xb < xbe);
+ while (xa < xae) {
+ uint32_t y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ uint32_t z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ uint32_t y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ } while (xb < xbe);
+ while (xa < xae) {
+ uint32_t y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while (!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+}
+
+static double ulp(double x)
+{
+ register int32_t L;
+ double a;
+
+ L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#endif
+ word0(a) = L;
+ word1(a) = 0;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ } else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(a) = 0x80000 >> L;
+ word1(a) = 0;
+ } else {
+ word0(a) = 0;
+ L -= Exp_shift;
+ word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ }
+ }
+#endif
+#endif
+ return dval(a);
+}
+
+static double b2d(Bigint* a, int* e)
+{
+ uint32_t* xa;
+ uint32_t* xa0;
+ uint32_t w;
+ uint32_t y;
+ uint32_t z;
+ int k;
+ double d;
+
+#define d0 word0(d)
+#define d1 word1(d)
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+ ASSERT(y);
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ d0 = Exp_1 | y >> Ebits - k;
+ w = xa > xa0 ? *--xa : 0;
+ d1 = y << (32 - Ebits) + k | w >> Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ d0 = Exp_1 | y << k | z >> 32 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> 32 - k;
+ } else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ret_d:
+#undef d0
+#undef d1
+ return dval(d);
+}
+
+static Bigint* d2b(double d, int* e, int* bits)
+{
+ Bigint* b;
+ int de, k;
+ uint32_t *x, y, z;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+#define d0 word0(d)
+#define d1 word1(d)
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#else
+ if ((de = (int)(d0 >> Exp_shift)))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ x[0] = y | z << 32 - k;
+ z >>= k;
+ } else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) ? 2 : 1;
+ } else {
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ } else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k + 16;
+ i = 3;
+ }
+ } else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ } else {
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ } else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ } while (!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+ *e = de - Bias - (P - 1) + k;
+ *bits = P - k;
+#ifndef Sudden_Underflow
+ } else {
+ *e = de - Bias - (P - 1) + 1 + k;
+#ifdef Pack_32
+ *bits = (32 * i) - hi0bits(x[i - 1]);
+#else
+ *bits = (i + 2) * 16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+}
+#undef d0
+#undef d1
+
+static double ratio(Bigint* a, Bigint* b)
+{
+ double da, db;
+ int k, ka, kb;
+
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32 * (a->wds - b->wds);
+#else
+ k = ka - kb + 16 * (a->wds - b->wds);
+#endif
+ if (k > 0)
+ word0(da) += k * Exp_msk1;
+ else {
+ k = -k;
+ word0(db) += k * Exp_msk1;
+ }
+ return dval(da) / dval(db);
+}
+
+static const double tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+};
+
+static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+#ifdef Avoid_Underflow
+ 9007199254740992. * 9007199254740992.e-256
+ /* = 2^106 * 1e-53 */
+#else
+ 1e-256
+#endif
+};
+
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+#define Scale_Bit 0x10
+#define n_bigtens 5
+
+#if defined(INFNAN_CHECK)
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+
+static int match(const char** sp, const char* t)
+{
+ int c, d;
+ const char* s = *sp;
+
+ while ((d = *t++)) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+}
+
+#ifndef No_Hex_NaN
+static void hexnan(double* rvp, const char** sp)
+{
+ uint32_t c, x[2];
+ const char* s;
+ int havedig, udx0, xshift;
+
+ x[0] = x[1] = 0;
+ havedig = xshift = 0;
+ udx0 = 1;
+ s = *sp;
+ while ((c = *(const unsigned char*)++s)) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c += 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ c += 10 - 'A';
+ else if (c <= ' ') {
+ if (udx0 && havedig) {
+ udx0 = 0;
+ xshift = 1;
+ }
+ continue;
+ } else if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ } else
+ return; /* invalid form: don't change *sp */
+ havedig = 1;
+ if (xshift) {
+ xshift = 0;
+ x[0] = x[1];
+ x[1] = 0;
+ }
+ if (udx0)
+ x[0] = (x[0] << 4) | (x[1] >> 28);
+ x[1] = (x[1] << 4) | c;
+ }
+ if ((x[0] &= 0xfffff) || x[1]) {
+ word0(*rvp) = Exp_mask | x[0];
+ word1(*rvp) = x[1];
+ }
+}
+#endif /*No_Hex_NaN*/
+#endif /* INFNAN_CHECK */
+
+double strtod(const char* s00, char** se)
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ const char *s, *s0, *s1;
+ double aadj, aadj1, adj, rv, rv0;
+ int32_t L;
+ uint32_t y, z;
+ Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+ sign = nz0 = nz = 0;
+ dval(rv) = 0.;
+ for (s = s00; ; s++)
+ switch (*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+break2:
+ if (*s == '0') {
+ nz0 = 1;
+ while (*++s == '0') { }
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = (10 * y) + c - '0';
+ else if (nd < 16)
+ z = (10 * z) + c - '0';
+ nd0 = nd;
+ if (c == '.') {
+ c = *++s;
+ if (!nd) {
+ for (; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for (; c >= '0' && c <= '9'; c = *++s) {
+have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for (i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = (10 * y) + c;
+ else if (nd <= DBL_DIG + 1)
+ z = (10 * z) + c;
+ nz = 0;
+ }
+ }
+ }
+dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch (c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while (c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while ((c = *++s) >= '0' && c <= '9')
+ L = (10 * L) + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ } else
+ e = 0;
+ } else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ word0(rv) = 0x7ff00000;
+ word1(rv) = 0;
+ goto ret;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+ word0(rv) = NAN_WORD0;
+ word1(rv) = NAN_WORD1;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ hexnan(&rv, &s);
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(rv) = y;
+ if (k > 9) {
+#ifdef SET_INEXACT
+ if (k > DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+ dval(rv) = tens[k - 9] * dval(rv) + z;
+ }
+ bd0 = 0;
+ if (nd <= DBL_DIG && Flt_Rounds == 1) {
+ if (!e)
+ goto ret;
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ goto ret;
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+ e -= i;
+ dval(rv) *= tens[i];
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+ /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ((i = e1 & 15))
+ dval(rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ovfl:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ /* Can't trust HUGE_VAL */
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ dval(rv0) = 1e300;
+ dval(rv0) *= dval(rv0);
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ e1 >>= 4;
+ for (j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0(rv) -= P * Exp_msk1;
+ dval(rv) *= bigtens[j];
+ if ((z = word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
+ goto ovfl;
+ if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ } else
+ word0(rv) += P * Exp_msk1;
+ }
+ } else if (e1 < 0) {
+ e1 = -e1;
+ if ((i = e1 & 15))
+ dval(rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ scale = 2 * P;
+ for (j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ if (scale && (j = (2 * P) + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(rv) = 0;
+ if (j >= 53)
+ word0(rv) = (P + 2) * Exp_msk1;
+ else
+ word0(rv) &= 0xffffffff << j - 32;
+ } else
+ word1(rv) &= 0xffffffff << j;
+ }
+#else
+ for (j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ /* The last multiplication could underflow. */
+ dval(rv0) = dval(rv);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
+ dval(rv) = 2. * dval(rv0);
+ dval(rv) *= tinytens[j];
+#endif
+ if (!dval(rv)) {
+undfl:
+ dval(rv) = 0.;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef Avoid_Underflow
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y);
+
+ for (;;) {
+ bd = Balloc(bd0->k);
+ Bcopy(bd, bd0);
+ bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bs = i2b(1);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ } else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Avoid_Underflow
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+ j = P + 1 - bbbits;
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(bb, bd);
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask
+#ifdef Avoid_Underflow
+ || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
+#else
+ || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+ && word1(rv) == (
+#ifdef Avoid_Underflow
+ (scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1)
+ ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) :
+#endif
+ 0xffffffff)) {
+ /*boundary case -- increment exponent*/
+ word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1;
+ word1(rv) = 0;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(rv) & Exp_mask;
+ if (L <= (2 * P + 1) * Exp_msk1) {
+ if (L > (P + 2) * Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(rv) = L | Bndry_mask1;
+ word1(rv) = 0xffffffff;
+ break;
+ }
+ if (!(word1(rv) & LSB))
+ break;
+ if (dsign)
+ dval(rv) += ulp(dval(rv));
+ else {
+ dval(rv) -= ulp(dval(rv));
+#ifndef Sudden_Underflow
+ if (!dval(rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = aadj1 = 1.;
+ else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(rv) == Tiny1 && !word0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ aadj1 = -1.;
+ } else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2. / FLT_RADIX)
+ aadj = 1. / FLT_RADIX;
+ else
+ aadj *= 0.5;
+ aadj1 = -aadj;
+ }
+ } else {
+ aadj *= 0.5;
+ aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch (Rounding) {
+ case 2: /* towards +infinity */
+ aadj1 -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ aadj1 += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ aadj1 += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ y = word0(rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) {
+ dval(rv0) = dval(rv);
+ word0(rv) -= P * Exp_msk1;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ if ((word0(rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) {
+ if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ goto ovfl;
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ goto cont;
+ } else
+ word0(rv) += P * Exp_msk1;
+ } else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2 * P * Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = (uint32_t)aadj) <= 0)
+ z = 1;
+ aadj = z;
+ aadj1 = dsign ? aadj : -aadj;
+ }
+ word0(aadj1) += (2 * P + 1) * Exp_msk1 - y;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P * Exp_msk1) {
+ dval(rv0) = dval(rv);
+ word0(rv) += P * Exp_msk1;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ if ((word0(rv) & Exp_mask) <= P * Exp_msk1)
+ {
+ if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
+ goto undfl;
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(rv) -= P * Exp_msk1;
+ } else {
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ }
+#else /*Sudden_Underflow*/
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P - 1) * Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P - 1) * Exp_msk1 && aadj > 1.) {
+ aadj1 = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ aadj1 = -aadj1;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (int32_t)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ } else if (aadj < .4999999 / FLT_RADIX)
+ break;
+ }
+#endif
+cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(rv0) = Exp_1 + (70 << Exp_shift);
+ word1(rv0) = 0;
+ dval(rv0) += 1.;
+ }
+ } else if (!oldinexact)
+ clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+ if (scale) {
+ word0(rv0) = Exp_1 - 2 * P * Exp_msk1;
+ word1(rv0) = 0;
+ dval(rv) *= dval(rv0);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+ if (word0(rv) == 0 && word1(rv) == 0)
+ errno = ERANGE;
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(rv0) = 1e-300;
+ dval(rv0) *= dval(rv0);
+ }
+#endif
+retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ret:
+ if (se)
+ *se = const_cast<char*>(s);
+ return sign ? -dval(rv) : dval(rv);
+}
+
+static int quorem(Bigint* b, Bigint* S)
+{
+ int n;
+ uint32_t *bx, *bxe, q, *sx, *sxe;
+#ifdef USE_LONG_LONG
+ unsigned long long borrow, carry, y, ys;
+#else
+ uint32_t borrow, carry, y, ys;
+#ifdef Pack_32
+ uint32_t si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+ ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem");
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+ ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem");
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef USE_LONG_LONG
+ ys = *sx++ * (unsigned long long)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *bx++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ } while (sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef USE_LONG_LONG
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & (uint32_t)1;
+ *bx++ = (uint32_t)y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ } while (sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+}
+
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+static char* dtoa_result;
+#endif
+
+static char* rv_alloc(int i)
+{
+ int k;
+
+ int j = sizeof(uint32_t);
+ for (k = 0;
+ sizeof(Bigint) - sizeof(uint32_t) - sizeof(int) + j <= (unsigned)i;
+ j <<= 1)
+ k++;
+ int* r = (int*)Balloc(k);
+ *r = k;
+ return
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+ dtoa_result =
+#endif
+ (char*)(r + 1);
+}
+
+static char* nrv_alloc(const char* s, char** rve, int n)
+{
+ char* rv = rv_alloc(n);
+ char* t = rv;
+
+ while ((*t = *s++))
+ t++;
+ if (rve)
+ *rve = t;
+ return rv;
+}
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined. It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+void freedtoa(char* s)
+{
+ Bigint* b = (Bigint*)((int*)s - 1);
+ b->maxwds = 1 << (b->k = *(int*)b);
+ Bfree(b);
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+ if (s == dtoa_result)
+ dtoa_result = 0;
+#endif
+}
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the int32_t
+ * calculation.
+ */
+
+char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve)
+{
+ /*
+ Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ int32_t L;
+#ifndef Sudden_Underflow
+ int denorm;
+ uint32_t x;
+#endif
+ Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
+ double d2, ds, eps;
+ char *s, *s0;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+
+ if (word0(d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(d) &= ~Sign_bit; /* clear sign bit */
+ } else
+ *sign = 0;
+
+ if ((word0(d) & Exp_mask) == Exp_mask)
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+ if (!word1(d) && !(word0(d) & 0xfffff))
+ return nrv_alloc("Infinity", rve, 8);
+ return nrv_alloc("NaN", rve, 3);
+ }
+ if (!dval(d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+
+ b = d2b(dval(d), &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
+#else
+ if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
+#endif
+ dval(d2) = dval(d);
+ word0(d2) &= Frac_mask1;
+ word0(d2) |= Exp_11;
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifndef Sudden_Underflow
+ denorm = 0;
+ } else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P - 1) - 1);
+ x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
+ : word1(d) << 32 - i;
+ dval(d2) = x;
+ word0(d2) -= 31 * Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P - 1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (dval(d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981);
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ } else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ } else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ leftright = 1;
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ s = s0 = rv_alloc(i);
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(d2) = dval(d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k & 0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(d) /= bigtens[n_bigtens - 1];
+ ieps++;
+ }
+ for (; j; j >>= 1, i++) {
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ }
+ dval(d) /= ds;
+ } else if ((j1 = -k)) {
+ dval(d) *= tens[j1 & 0xf];
+ for (j = j1 >> 4; j; j >>= 1, i++) {
+ if (j & 1) {
+ ieps++;
+ dval(d) *= bigtens[i];
+ }
+ }
+ }
+ if (k_check && dval(d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(d) *= 10.;
+ ieps++;
+ }
+ dval(eps) = (ieps * dval(d)) + 7.;
+ word0(eps) -= (P - 1) * Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
+ goto one_digit;
+ if (dval(d) < -dval(eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps);
+ for (i = 0;;) {
+ L = (long int)dval(d);
+ dval(d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(d) < dval(eps))
+ goto ret1;
+ if (1. - dval(d) < dval(eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(eps) *= 10.;
+ dval(d) *= 10.;
+ }
+ } else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(eps) *= tens[ilim - 1];
+ for (i = 1;; i++, dval(d) *= 10.) {
+ L = (int32_t)(dval(d));
+ if (!(dval(d) -= L))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(d) > 0.5 + dval(eps))
+ goto bump_up;
+ else if (dval(d) < 0.5 - dval(eps)) {
+ while (*--s == '0') { }
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+fast_failed:
+ s = s0;
+ dval(d) = dval(d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(d) <= 5 * ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for (i = 1;; i++, dval(d) *= 10.) {
+ L = (int32_t)(dval(d) / ds);
+ dval(d) -= L * ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(d) < 0) {
+ L--;
+ dval(d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+ dval(d) += dval(d);
+ if (dval(d) > ds || dval(d) == ds && L & 1) {
+bump_up:
+ while (*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P - 1) - 1 + 1) :
+#endif
+ 1 + P - bbits;
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if ((j = b5 - m5))
+ b = pow5mult(b, j);
+ } else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = pow5mult(S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f))
+ i = 32 - i;
+#else
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf))
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ } else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for (i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+ if (j1 == 0 && !(word1(d) & 1)) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+ if (j < 0 || j == 0 && !(word1(d) & 1)) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9')
+ goto round_9_up;
+ }
+accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+ if (dig == '9') { /* possible if i == 1 */
+round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd(mhi, 10, 0);
+ else {
+ mlo = multadd(mlo, 10, 0);
+ mhi = multadd(mhi, 10, 0);
+ }
+ }
+ } else
+ for (i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || j == 0 && dig & 1) {
+roundoff:
+ while (*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ } else {
+ while (*--s == '0') { }
+ s++;
+ }
+ goto ret;
+no_digits:
+ k = -1 - ndigits;
+ goto ret;
+one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ret1:
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(d) = Exp_1 + (70 << Exp_shift);
+ word1(d) = 0;
+ dval(d) += 1.;
+ }
+ } else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_dtoa_h
+#define WTF_dtoa_h
+
+namespace WTF {
+ class Mutex;
+}
+
+namespace WTF {
+
+ extern WTF::Mutex* s_dtoaP5Mutex;
+
+ double strtod(const char* s00, char** se);
+ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve);
+ void freedtoa(char* s);
+
+} // namespace WTF
+
+#endif // WTF_dtoa_h
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include <glib.h>
+
+namespace WTF {
+
+static gboolean timeoutFired(gpointer)
+{
+ dispatchFunctionsFromMainThread();
+ return FALSE;
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ g_timeout_add(0, timeoutFired, 0);
+}
+
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "MainThread.h"
+
+#import "Threading.h"
+#import <Foundation/NSThread.h>
+
+@interface WTFMainThreadCaller : NSObject {
+}
+- (void)call;
+@end
+
+@implementation WTFMainThreadCaller
+
+- (void)call
+{
+ WTF::dispatchFunctionsFromMainThread();
+}
+
+@end // implementation WTFMainThreadCaller
+
+namespace WTF {
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
+ [caller performSelector:@selector(call) onThread:mainNSThread() withObject:nil waitUntilDone:NO];
+ [caller release];
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "Threading.h"
+
+#import <Foundation/NSThread.h>
+
+namespace WTF {
+
+static NSThread *mainThread;
+
+NSThread *mainNSThread()
+{
+ return mainThread;
+}
+
+void initializeMainNSThread()
+{
+ mainThread = [[NSThread currentThread] retain];
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "MainThread.h"
+
+#import <Foundation/NSThread.h>
+
+@interface WTFMainThreadCaller : NSObject {
+}
+- (void)call;
+@end
+
+@implementation WTFMainThreadCaller
+
+- (void)call
+{
+ WTF::dispatchFunctionsFromMainThread();
+}
+
+@end // implementation WTFMainThreadCaller
+
+namespace WTF {
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
+ [caller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+ [caller release];
+}
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 2007 Staikos Computing Services Inc.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QCoreApplication>
+
+
+namespace WTF {
+
+class MainThreadInvoker : public QObject {
+ Q_OBJECT
+public:
+ MainThreadInvoker();
+
+private Q_SLOTS:
+ void dispatch();
+};
+
+MainThreadInvoker::MainThreadInvoker()
+{
+ moveToThread(QCoreApplication::instance()->thread());
+}
+
+void MainThreadInvoker::dispatch()
+{
+ dispatchFunctionsFromMainThread();
+}
+
+Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker)
+
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection);
+}
+
+}
+
+#include "MainThreadQt.moc"
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_Collator_h
+#define WTF_Collator_h
+
+#include <memory>
+#include <wtf/Noncopyable.h>
+#include <wtf/unicode/Unicode.h>
+
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+struct UCollator;
+#endif
+
+namespace WTF {
+
+ class Collator : Noncopyable {
+ public:
+ enum Result { Equal = 0, Greater = 1, Less = -1 };
+
+ Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too.
+ ~Collator();
+ void setOrderLowerFirst(bool);
+
+ static std::auto_ptr<Collator> userDefault();
+
+ Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const;
+
+ private:
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+ void createCollator() const;
+ void releaseCollator();
+ mutable UCollator* m_collator;
+#endif
+ char* m_locale;
+ bool m_lowerFirst;
+ };
+}
+
+using WTF::Collator;
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Collator.h"
+
+#if !USE(ICU_UNICODE) || UCONFIG_NO_COLLATION
+
+namespace WTF {
+
+Collator::Collator(const char*)
+{
+}
+
+Collator::~Collator()
+{
+}
+
+void Collator::setOrderLowerFirst(bool)
+{
+}
+
+std::auto_ptr<Collator> Collator::userDefault()
+{
+ return std::auto_ptr<Collator>(new Collator(0));
+}
+
+// A default implementation for platforms that lack Unicode-aware collation.
+Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
+{
+ int lmin = lhsLength < rhsLength ? lhsLength : rhsLength;
+ int l = 0;
+ while (l < lmin && *lhs == *rhs) {
+ lhs++;
+ rhs++;
+ l++;
+ }
+
+ if (l < lmin)
+ return (*lhs > *rhs) ? Greater : Less;
+
+ if (lhsLength == rhsLength)
+ return Equal;
+
+ return (lhsLength > rhsLength) ? Greater : Less;
+}
+
+}
+
+#endif
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006, 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 Library General Public
*
*/
-#ifndef KJS_UNICODE_H
-#define KJS_UNICODE_H
+#ifndef WTF_UNICODE_H
+#define WTF_UNICODE_H
-#include <wtf/Platform.h>
+#include <wtf/Assertions.h>
#if USE(QT4_UNICODE)
#include "qt4/UnicodeQt4.h"
#error "Unknown Unicode implementation"
#endif
-#endif
-// vim: ts=2 sw=2 et
+COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes);
+
+#endif // WTF_UNICODE_H
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Collator.h"
+
+#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
+
+#include "Assertions.h"
+#include "Threading.h"
+#include <unicode/ucol.h>
+#include <string.h>
+
+#if PLATFORM(DARWIN)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace WTF {
+
+static UCollator* cachedCollator;
+static Mutex& cachedCollatorMutex()
+{
+ AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+ return mutex;
+}
+
+Collator::Collator(const char* locale)
+ : m_collator(0)
+ , m_locale(locale ? strdup(locale) : 0)
+ , m_lowerFirst(false)
+{
+}
+
+std::auto_ptr<Collator> Collator::userDefault()
+{
+#if PLATFORM(DARWIN) && PLATFORM(CF)
+ // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
+ CFStringRef collationOrder = (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+ char buf[256];
+ if (collationOrder) {
+ CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
+ CFRelease(collationOrder);
+ return std::auto_ptr<Collator>(new Collator(buf));
+ } else
+ return std::auto_ptr<Collator>(new Collator(""));
+#else
+ return std::auto_ptr<Collator>(new Collator(0));
+#endif
+}
+
+Collator::~Collator()
+{
+ releaseCollator();
+ free(m_locale);
+}
+
+void Collator::setOrderLowerFirst(bool lowerFirst)
+{
+ m_lowerFirst = lowerFirst;
+}
+
+Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
+{
+ if (!m_collator)
+ createCollator();
+
+ return static_cast<Result>(ucol_strcoll(m_collator, lhs, lhsLength, rhs, rhsLength));
+}
+
+void Collator::createCollator() const
+{
+ ASSERT(!m_collator);
+ UErrorCode status = U_ZERO_ERROR;
+
+ {
+ Locker<Mutex> lock(cachedCollatorMutex());
+ if (cachedCollator) {
+ const char* cachedCollatorLocale = ucol_getLocaleByType(cachedCollator, ULOC_REQUESTED_LOCALE, &status);
+ ASSERT(U_SUCCESS(status));
+ ASSERT(cachedCollatorLocale);
+
+ UColAttributeValue cachedCollatorLowerFirst = ucol_getAttribute(cachedCollator, UCOL_CASE_FIRST, &status);
+ ASSERT(U_SUCCESS(status));
+
+ // FIXME: default locale is never matched, because ucol_getLocaleByType returns the actual one used, not 0.
+ if (m_locale && 0 == strcmp(cachedCollatorLocale, m_locale)
+ && ((UCOL_LOWER_FIRST == cachedCollatorLowerFirst && m_lowerFirst) || (UCOL_UPPER_FIRST == cachedCollatorLowerFirst && !m_lowerFirst))) {
+ m_collator = cachedCollator;
+ cachedCollator = 0;
+ return;
+ }
+ }
+ }
+
+ m_collator = ucol_open(m_locale, &status);
+ if (U_FAILURE(status)) {
+ status = U_ZERO_ERROR;
+ m_collator = ucol_open("", &status); // Fallback to Unicode Collation Algorithm.
+ }
+ ASSERT(U_SUCCESS(status));
+
+ ucol_setAttribute(m_collator, UCOL_CASE_FIRST, m_lowerFirst ? UCOL_LOWER_FIRST : UCOL_UPPER_FIRST, &status);
+ ASSERT(U_SUCCESS(status));
+}
+
+void Collator::releaseCollator()
+{
+ {
+ Locker<Mutex> lock(cachedCollatorMutex());
+ if (cachedCollator)
+ ucol_close(cachedCollator);
+ cachedCollator = m_collator;
+ m_collator = 0;
+ }
+}
+
+}
+
+#endif
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- * Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 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 Library General Public
*
*/
-#ifndef KJS_UNICODE_ICU_H
-#define KJS_UNICODE_ICU_H
+#ifndef WTF_UNICODE_ICU_H
+#define WTF_UNICODE_ICU_H
+#include <stdlib.h>
#include <unicode/uchar.h>
#include <unicode/ustring.h>
#include <unicode/utf16.h>
-#include <stdlib.h>
-
namespace WTF {
- namespace Unicode {
-
- enum Direction {
- LeftToRight = U_LEFT_TO_RIGHT,
- RightToLeft = U_RIGHT_TO_LEFT,
- EuropeanNumber = U_EUROPEAN_NUMBER,
- EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
- EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
- ArabicNumber = U_ARABIC_NUMBER,
- CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
- BlockSeparator = U_BLOCK_SEPARATOR,
- SegmentSeparator = U_SEGMENT_SEPARATOR,
- WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
- OtherNeutral = U_OTHER_NEUTRAL,
- LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
- LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
- RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
- RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
- RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
- PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
- NonSpacingMark = U_DIR_NON_SPACING_MARK,
- BoundaryNeutral = U_BOUNDARY_NEUTRAL
- };
-
- enum DecompositionType {
- DecompositionNone = U_DT_NONE,
- DecompositionCanonical = U_DT_CANONICAL,
- DecompositionCompat = U_DT_COMPAT,
- DecompositionCircle = U_DT_CIRCLE,
- DecompositionFinal = U_DT_FINAL,
- DecompositionFont = U_DT_FONT,
- DecompositionFraction = U_DT_FRACTION,
- DecompositionInitial = U_DT_INITIAL,
- DecompositionIsolated = U_DT_ISOLATED,
- DecompositionMedial = U_DT_MEDIAL,
- DecompositionNarrow = U_DT_NARROW,
- DecompositionNoBreak = U_DT_NOBREAK,
- DecompositionSmall = U_DT_SMALL,
- DecompositionSquare = U_DT_SQUARE,
- DecompositionSub = U_DT_SUB,
- DecompositionSuper = U_DT_SUPER,
- DecompositionVertical = U_DT_VERTICAL,
- DecompositionWide = U_DT_WIDE,
- };
-
- enum CharCategory {
- NoCategory = 0,
- Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
- Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
- Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
- Letter_Titlecase = U_MASK(U_TITLECASE_LETTER),
- Letter_Modifier = U_MASK(U_MODIFIER_LETTER),
- Letter_Other = U_MASK(U_OTHER_LETTER),
-
- Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
- Mark_Enclosing = U_MASK(U_ENCLOSING_MARK),
- Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
-
- Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
- Number_Letter = U_MASK(U_LETTER_NUMBER),
- Number_Other = U_MASK(U_OTHER_NUMBER),
-
- Separator_Space = U_MASK(U_SPACE_SEPARATOR),
- Separator_Line = U_MASK(U_LINE_SEPARATOR),
- Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
-
- Other_Control = U_MASK(U_CONTROL_CHAR),
- Other_Format = U_MASK(U_FORMAT_CHAR),
- Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
- Other_Surrogate = U_MASK(U_SURROGATE),
-
- Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
- Punctuation_Open = U_MASK(U_START_PUNCTUATION),
- Punctuation_Close = U_MASK(U_END_PUNCTUATION),
- Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
- Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
-
- Symbol_Math = U_MASK(U_MATH_SYMBOL),
- Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
- Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
- Symbol_Other = U_MASK(U_OTHER_SYMBOL),
-
- Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
- Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
- };
-
- inline UChar32 foldCase(UChar32 c)
- {
- return u_foldCase(c, U_FOLD_CASE_DEFAULT);
- }
-
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status);
- *error = !U_SUCCESS(status);
- return realLength;
- }
-
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status);
- *error = !!U_FAILURE(status);
- return realLength;
- }
-
- inline UChar32 toLower(UChar32 c)
- {
- return u_tolower(c);
- }
-
- inline UChar32 toUpper(UChar32 c)
- {
- return u_toupper(c);
- }
-
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- UErrorCode status = U_ZERO_ERROR;
- int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status);
- *error = !!U_FAILURE(status);
- return realLength;
- }
-
- inline UChar32 toTitleCase(UChar32 c)
- {
- return u_totitle(c);
- }
-
- inline bool isArabicChar(UChar32 c)
- {
- return ublock_getCode(c) == UBLOCK_ARABIC;
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return u_charType(c) == U_FORMAT_CHAR;
- }
-
- inline bool isSeparatorSpace(UChar32 c)
- {
- return u_charType(c) == U_SPACE_SEPARATOR;
- }
-
- inline bool isPrintableChar(UChar32 c)
- {
- return !!u_isprint(c);
- }
-
- inline bool isDigit(UChar32 c)
- {
- return !!u_isdigit(c);
- }
-
- inline bool isPunct(UChar32 c)
- {
- return !!u_ispunct(c);
- }
-
- inline UChar32 mirroredChar(UChar32 c)
- {
- return u_charMirror(c);
- }
-
- inline CharCategory category(UChar32 c)
- {
- return static_cast<CharCategory>(U_GET_GC_MASK(c));
- }
-
- inline Direction direction(UChar32 c)
- {
- return static_cast<Direction>(u_charDirection(c));
- }
-
- inline bool isLower(UChar32 c)
- {
- return !!u_islower(c);
- }
-
- inline int digitValue(UChar32 c)
- {
- return u_charDigitValue(c);
- }
-
- inline uint8_t combiningClass(UChar32 c)
- {
- return u_getCombiningClass(c);
- }
-
- inline DecompositionType decompositionType(UChar32 c)
- {
- return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
- }
-
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
- }
-
- }
-}
-
-#endif
-// vim: ts=2 sw=2 et
+namespace Unicode {
+
+enum Direction {
+ LeftToRight = U_LEFT_TO_RIGHT,
+ RightToLeft = U_RIGHT_TO_LEFT,
+ EuropeanNumber = U_EUROPEAN_NUMBER,
+ EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
+ EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
+ ArabicNumber = U_ARABIC_NUMBER,
+ CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
+ BlockSeparator = U_BLOCK_SEPARATOR,
+ SegmentSeparator = U_SEGMENT_SEPARATOR,
+ WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
+ OtherNeutral = U_OTHER_NEUTRAL,
+ LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
+ LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
+ RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
+ RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
+ RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
+ PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
+ NonSpacingMark = U_DIR_NON_SPACING_MARK,
+ BoundaryNeutral = U_BOUNDARY_NEUTRAL
+};
+
+enum DecompositionType {
+ DecompositionNone = U_DT_NONE,
+ DecompositionCanonical = U_DT_CANONICAL,
+ DecompositionCompat = U_DT_COMPAT,
+ DecompositionCircle = U_DT_CIRCLE,
+ DecompositionFinal = U_DT_FINAL,
+ DecompositionFont = U_DT_FONT,
+ DecompositionFraction = U_DT_FRACTION,
+ DecompositionInitial = U_DT_INITIAL,
+ DecompositionIsolated = U_DT_ISOLATED,
+ DecompositionMedial = U_DT_MEDIAL,
+ DecompositionNarrow = U_DT_NARROW,
+ DecompositionNoBreak = U_DT_NOBREAK,
+ DecompositionSmall = U_DT_SMALL,
+ DecompositionSquare = U_DT_SQUARE,
+ DecompositionSub = U_DT_SUB,
+ DecompositionSuper = U_DT_SUPER,
+ DecompositionVertical = U_DT_VERTICAL,
+ DecompositionWide = U_DT_WIDE,
+};
+
+enum CharCategory {
+ NoCategory = 0,
+ Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
+ Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
+ Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
+ Letter_Titlecase = U_MASK(U_TITLECASE_LETTER),
+ Letter_Modifier = U_MASK(U_MODIFIER_LETTER),
+ Letter_Other = U_MASK(U_OTHER_LETTER),
+
+ Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
+ Mark_Enclosing = U_MASK(U_ENCLOSING_MARK),
+ Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
+
+ Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
+ Number_Letter = U_MASK(U_LETTER_NUMBER),
+ Number_Other = U_MASK(U_OTHER_NUMBER),
+
+ Separator_Space = U_MASK(U_SPACE_SEPARATOR),
+ Separator_Line = U_MASK(U_LINE_SEPARATOR),
+ Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
+
+ Other_Control = U_MASK(U_CONTROL_CHAR),
+ Other_Format = U_MASK(U_FORMAT_CHAR),
+ Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
+ Other_Surrogate = U_MASK(U_SURROGATE),
+
+ Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
+ Punctuation_Open = U_MASK(U_START_PUNCTUATION),
+ Punctuation_Close = U_MASK(U_END_PUNCTUATION),
+ Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
+ Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
+
+ Symbol_Math = U_MASK(U_MATH_SYMBOL),
+ Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
+ Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
+ Symbol_Other = U_MASK(U_OTHER_SYMBOL),
+
+ Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
+ Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
+};
+
+inline UChar32 foldCase(UChar32 c)
+{
+ return u_foldCase(c, U_FOLD_CASE_DEFAULT);
+}
+
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status);
+ *error = !U_SUCCESS(status);
+ return realLength;
+}
+
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status);
+ *error = !!U_FAILURE(status);
+ return realLength;
+}
+
+inline UChar32 toLower(UChar32 c)
+{
+ return u_tolower(c);
+}
+
+inline UChar32 toUpper(UChar32 c)
+{
+ return u_toupper(c);
+}
+
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status);
+ *error = !!U_FAILURE(status);
+ return realLength;
+}
+
+inline UChar32 toTitleCase(UChar32 c)
+{
+ return u_totitle(c);
+}
+
+inline bool isArabicChar(UChar32 c)
+{
+ return ublock_getCode(c) == UBLOCK_ARABIC;
+}
+
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return u_charType(c) == U_SPACE_SEPARATOR;
+}
+
+inline bool isPrintableChar(UChar32 c)
+{
+ return !!u_isprint(c);
+}
+
+inline bool isPunct(UChar32 c)
+{
+ return !!u_ispunct(c);
+}
+
+inline bool hasLineBreakingPropertyComplexContext(UChar32 c)
+{
+ return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT;
+}
+
+inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c)
+{
+ int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
+ return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC;
+}
+
+inline UChar32 mirroredChar(UChar32 c)
+{
+ return u_charMirror(c);
+}
+
+inline CharCategory category(UChar32 c)
+{
+ return static_cast<CharCategory>(U_GET_GC_MASK(c));
+}
+
+inline Direction direction(UChar32 c)
+{
+ return static_cast<Direction>(u_charDirection(c));
+}
+
+inline bool isLower(UChar32 c)
+{
+ return !!u_islower(c);
+}
+
+inline uint8_t combiningClass(UChar32 c)
+{
+ return u_getCombiningClass(c);
+}
+
+inline DecompositionType decompositionType(UChar32 c)
+{
+ return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
+}
+
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
+}
+
+} }
+
+#endif // WTF_UNICODE_ICU_H
/*
- * This file is part of the KDE libraries
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ * Copyright (C) 2006, 2007, 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 Library General Public
*
*/
-#ifndef KJS_UNICODE_QT4_H
-#define KJS_UNICODE_QT4_H
+#ifndef WTF_UNICODE_QT4_H
+#define WTF_UNICODE_QT4_H
#include <QChar>
#include <QString>
#include <stdint.h>
#if QT_VERSION >= 0x040300
+QT_BEGIN_NAMESPACE
namespace QUnicodeTables {
struct Properties {
ushort category : 8;
Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
}
+QT_END_NAMESPACE
#endif
// ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
#define U_MASK(x) ((uint32_t)1<<(x))
namespace WTF {
- namespace Unicode {
-
- enum Direction {
- LeftToRight = QChar::DirL,
- RightToLeft = QChar::DirR,
- EuropeanNumber = QChar::DirEN,
- EuropeanNumberSeparator = QChar::DirES,
- EuropeanNumberTerminator = QChar::DirET,
- ArabicNumber = QChar::DirAN,
- CommonNumberSeparator = QChar::DirCS,
- BlockSeparator = QChar::DirB,
- SegmentSeparator = QChar::DirS,
- WhiteSpaceNeutral = QChar::DirWS,
- OtherNeutral = QChar::DirON,
- LeftToRightEmbedding = QChar::DirLRE,
- LeftToRightOverride = QChar::DirLRO,
- RightToLeftArabic = QChar::DirAL,
- RightToLeftEmbedding = QChar::DirRLE,
- RightToLeftOverride = QChar::DirRLO,
- PopDirectionalFormat = QChar::DirPDF,
- NonSpacingMark = QChar::DirNSM,
- BoundaryNeutral = QChar::DirBN
- };
-
- enum DecompositionType {
- DecompositionNone = QChar::NoDecomposition,
- DecompositionCanonical = QChar::Canonical,
- DecompositionCompat = QChar::Compat,
- DecompositionCircle = QChar::Circle,
- DecompositionFinal = QChar::Final,
- DecompositionFont = QChar::Font,
- DecompositionFraction = QChar::Fraction,
- DecompositionInitial = QChar::Initial,
- DecompositionIsolated = QChar::Isolated,
- DecompositionMedial = QChar::Medial,
- DecompositionNarrow = QChar::Narrow,
- DecompositionNoBreak = QChar::NoBreak,
- DecompositionSmall = QChar::Small,
- DecompositionSquare = QChar::Square,
- DecompositionSub = QChar::Sub,
- DecompositionSuper = QChar::Super,
- DecompositionVertical = QChar::Vertical,
- DecompositionWide = QChar::Wide
- };
-
- enum CharCategory {
- NoCategory = 0,
- Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
- Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
- Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
- Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
- Number_Letter = U_MASK(QChar::Number_Letter),
- Number_Other = U_MASK(QChar::Number_Other),
- Separator_Space = U_MASK(QChar::Separator_Space),
- Separator_Line = U_MASK(QChar::Separator_Line),
- Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
- Other_Control = U_MASK(QChar::Other_Control),
- Other_Format = U_MASK(QChar::Other_Format),
- Other_Surrogate = U_MASK(QChar::Other_Surrogate),
- Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
- Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
- Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
- Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
- Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
- Letter_Modifier = U_MASK(QChar::Letter_Modifier),
- Letter_Other = U_MASK(QChar::Letter_Other),
- Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
- Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
- Punctuation_Open = U_MASK(QChar::Punctuation_Open),
- Punctuation_Close = U_MASK(QChar::Punctuation_Close),
- Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
- Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
- Punctuation_Other = U_MASK(QChar::Punctuation_Other),
- Symbol_Math = U_MASK(QChar::Symbol_Math),
- Symbol_Currency = U_MASK(QChar::Symbol_Currency),
- Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
- Symbol_Other = U_MASK(QChar::Symbol_Other),
- };
+namespace Unicode {
+
+enum Direction {
+ LeftToRight = QChar::DirL,
+ RightToLeft = QChar::DirR,
+ EuropeanNumber = QChar::DirEN,
+ EuropeanNumberSeparator = QChar::DirES,
+ EuropeanNumberTerminator = QChar::DirET,
+ ArabicNumber = QChar::DirAN,
+ CommonNumberSeparator = QChar::DirCS,
+ BlockSeparator = QChar::DirB,
+ SegmentSeparator = QChar::DirS,
+ WhiteSpaceNeutral = QChar::DirWS,
+ OtherNeutral = QChar::DirON,
+ LeftToRightEmbedding = QChar::DirLRE,
+ LeftToRightOverride = QChar::DirLRO,
+ RightToLeftArabic = QChar::DirAL,
+ RightToLeftEmbedding = QChar::DirRLE,
+ RightToLeftOverride = QChar::DirRLO,
+ PopDirectionalFormat = QChar::DirPDF,
+ NonSpacingMark = QChar::DirNSM,
+ BoundaryNeutral = QChar::DirBN
+};
+
+enum DecompositionType {
+ DecompositionNone = QChar::NoDecomposition,
+ DecompositionCanonical = QChar::Canonical,
+ DecompositionCompat = QChar::Compat,
+ DecompositionCircle = QChar::Circle,
+ DecompositionFinal = QChar::Final,
+ DecompositionFont = QChar::Font,
+ DecompositionFraction = QChar::Fraction,
+ DecompositionInitial = QChar::Initial,
+ DecompositionIsolated = QChar::Isolated,
+ DecompositionMedial = QChar::Medial,
+ DecompositionNarrow = QChar::Narrow,
+ DecompositionNoBreak = QChar::NoBreak,
+ DecompositionSmall = QChar::Small,
+ DecompositionSquare = QChar::Square,
+ DecompositionSub = QChar::Sub,
+ DecompositionSuper = QChar::Super,
+ DecompositionVertical = QChar::Vertical,
+ DecompositionWide = QChar::Wide
+};
+
+enum CharCategory {
+ NoCategory = 0,
+ Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
+ Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
+ Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
+ Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
+ Number_Letter = U_MASK(QChar::Number_Letter),
+ Number_Other = U_MASK(QChar::Number_Other),
+ Separator_Space = U_MASK(QChar::Separator_Space),
+ Separator_Line = U_MASK(QChar::Separator_Line),
+ Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
+ Other_Control = U_MASK(QChar::Other_Control),
+ Other_Format = U_MASK(QChar::Other_Format),
+ Other_Surrogate = U_MASK(QChar::Other_Surrogate),
+ Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
+ Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
+ Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
+ Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
+ Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
+ Letter_Modifier = U_MASK(QChar::Letter_Modifier),
+ Letter_Other = U_MASK(QChar::Letter_Other),
+ Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
+ Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
+ Punctuation_Open = U_MASK(QChar::Punctuation_Open),
+ Punctuation_Close = U_MASK(QChar::Punctuation_Close),
+ Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
+ Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
+ Punctuation_Other = U_MASK(QChar::Punctuation_Other),
+ Symbol_Math = U_MASK(QChar::Symbol_Math),
+ Symbol_Currency = U_MASK(QChar::Symbol_Currency),
+ Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
+ Symbol_Other = U_MASK(QChar::Symbol_Other)
+};
#if QT_VERSION >= 0x040300
- // FIXME: handle surrogates correctly in all methods
- inline UChar32 toLower(UChar32 ch)
- {
- return QChar::toLower(ch);
- }
+// FIXME: handle surrogates correctly in all methods
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- const UChar *e = src + srcLength;
- const UChar *s = src;
- UChar *r = result;
- UChar *re = result + resultLength;
-
- // this avoids one out of bounds check in the loop
- if (QChar(*s).isLowSurrogate())
- *r++ = *s++;
-
- int needed = 0;
- while (s < e && r < re) {
- uint c = *s;
- if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
- c = QChar::surrogateToUcs4(*(s - 1), c);
- const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
- if (prop->lowerCaseSpecial) {
- QString qstring;
- if (c < 0x10000) {
- qstring += QChar(c);
- } else {
- qstring += QChar(*(s-1));
- qstring += QChar(*s);
- }
- qstring = qstring.toLower();
- for (int i = 0; i < qstring.length(); ++i) {
- if (r == re) {
- needed += qstring.length() - i;
- break;
- }
- *r = qstring.at(i).unicode();
- ++r;
- }
+inline UChar32 toLower(UChar32 ch)
+{
+ return QChar::toLower(ch);
+}
+
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ const UChar *e = src + srcLength;
+ const UChar *s = src;
+ UChar *r = result;
+ uint rindex = 0;
+
+ // this avoids one out of bounds check in the loop
+ if (s < e && QChar(*s).isLowSurrogate()) {
+ if (r)
+ r[rindex] = *s++;
+ ++rindex;
+ }
+
+ int needed = 0;
+ while (s < e && (rindex < uint(resultLength) || !r)) {
+ uint c = *s;
+ if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(s - 1), c);
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
+ if (prop->lowerCaseSpecial) {
+ QString qstring;
+ if (c < 0x10000) {
+ qstring += QChar(c);
} else {
- *r = *s + prop->lowerCaseDiff;
- ++r;
+ qstring += QChar(*(s-1));
+ qstring += QChar(*s);
}
- ++s;
+ qstring = qstring.toLower();
+ for (int i = 0; i < qstring.length(); ++i) {
+ if (rindex >= uint(resultLength)) {
+ needed += qstring.length() - i;
+ break;
+ }
+ if (r)
+ r[rindex] = qstring.at(i).unicode();
+ ++rindex;
+ }
+ } else {
+ if (r)
+ r[rindex] = *s + prop->lowerCaseDiff;
+ ++rindex;
}
- if (s < e)
- needed += e - s;
- *error = (needed != 0);
- if (r < re)
- *r = 0;
- return (r - result) + needed;
- }
+ ++s;
+ }
+ if (s < e)
+ needed += e - s;
+ *error = (needed != 0);
+ if (rindex < uint(resultLength))
+ r[rindex] = 0;
+ return rindex + needed;
+}
- inline UChar32 toUpper(UChar32 ch)
- {
- return QChar::toUpper(ch);
- }
+inline UChar32 toUpper(UChar32 ch)
+{
+ return QChar::toUpper(ch);
+}
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- const UChar *e = src + srcLength;
- const UChar *s = src;
- UChar *r = result;
- UChar *re = result + resultLength;
-
- // this avoids one out of bounds check in the loop
- if (QChar(*s).isLowSurrogate())
- *r++ = *s++;
-
- int needed = 0;
- while (s < e && r < re) {
- uint c = *s;
- if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
- c = QChar::surrogateToUcs4(*(s - 1), c);
- const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
- if (prop->upperCaseSpecial) {
- QString qstring;
- if (c < 0x10000) {
- qstring += QChar(c);
- } else {
- qstring += QChar(*(s-1));
- qstring += QChar(*s);
- }
- qstring = qstring.toUpper();
- for (int i = 0; i < qstring.length(); ++i) {
- if (r == re) {
- needed += qstring.length() - i;
- break;
- }
- *r = qstring.at(i).unicode();
- ++r;
- }
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ const UChar *e = src + srcLength;
+ const UChar *s = src;
+ UChar *r = result;
+ int rindex = 0;
+
+ // this avoids one out of bounds check in the loop
+ if (s < e && QChar(*s).isLowSurrogate()) {
+ if (r)
+ r[rindex] = *s++;
+ ++rindex;
+ }
+
+ int needed = 0;
+ while (s < e && (rindex < resultLength || !r)) {
+ uint c = *s;
+ if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
+ c = QChar::surrogateToUcs4(*(s - 1), c);
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
+ if (prop->upperCaseSpecial) {
+ QString qstring;
+ if (c < 0x10000) {
+ qstring += QChar(c);
} else {
- *r = *s + prop->upperCaseDiff;
- ++r;
+ qstring += QChar(*(s-1));
+ qstring += QChar(*s);
+ }
+ qstring = qstring.toUpper();
+ for (int i = 0; i < qstring.length(); ++i) {
+ if (rindex >= resultLength) {
+ needed += qstring.length() - i;
+ break;
+ }
+ if (r)
+ r[rindex] = qstring.at(i).unicode();
+ ++rindex;
}
- ++s;
+ } else {
+ if (r)
+ r[rindex] = *s + prop->upperCaseDiff;
+ ++rindex;
}
- if (s < e)
- needed += e - s;
- *error = (needed != 0);
- if (r < re)
- *r = 0;
- return (r - result) + needed;
- }
+ ++s;
+ }
+ if (s < e)
+ needed += e - s;
+ *error = (needed != 0);
+ if (rindex < resultLength)
+ r[rindex] = 0;
+ return rindex + needed;
+}
- inline int toTitleCase(UChar32 c)
- {
- return QChar::toTitleCase(c);
- }
+inline int toTitleCase(UChar32 c)
+{
+ return QChar::toTitleCase(c);
+}
- inline UChar32 foldCase(UChar32 c)
- {
- return QChar::toCaseFolded(c);
- }
+inline UChar32 foldCase(UChar32 c)
+{
+ return QChar::toCaseFolded(c);
+}
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- // FIXME: handle special casing. Easiest with some low level API in Qt
- *error = false;
- if (resultLength < srcLength) {
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ // FIXME: handle special casing. Easiest with some low level API in Qt
+ *error = false;
+ if (resultLength < srcLength) {
*error = true;
return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar::toCaseFolded(src[i]);
- return srcLength;
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return QChar::category(c) == QChar::Other_Format;
- }
-
- inline bool isArabicChar(UChar32 c)
- {
- return c >= 0x0600 && c <= 0x06FF;
}
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar::toCaseFolded(ushort(src[i]));
+ return srcLength;
+}
- inline bool isPrintableChar(UChar32 c)
- {
- const uint test = U_MASK(QChar::Other_Control) |
- U_MASK(QChar::Other_NotAssigned);
- return !(U_MASK(QChar::category(c)) & test);
- }
+inline bool isArabicChar(UChar32 c)
+{
+ return c >= 0x0600 && c <= 0x06FF;
+}
- inline bool isSeparatorSpace(UChar32 c)
- {
- return QChar::category(c) == QChar::Separator_Space;
- }
+inline bool isPrintableChar(UChar32 c)
+{
+ const uint test = U_MASK(QChar::Other_Control) |
+ U_MASK(QChar::Other_NotAssigned);
+ return !(U_MASK(QChar::category(c)) & test);
+}
- inline bool isPunct(UChar32 c)
- {
- const uint test = U_MASK(QChar::Punctuation_Connector) |
- U_MASK(QChar::Punctuation_Dash) |
- U_MASK(QChar::Punctuation_Open) |
- U_MASK(QChar::Punctuation_Close) |
- U_MASK(QChar::Punctuation_InitialQuote) |
- U_MASK(QChar::Punctuation_FinalQuote) |
- U_MASK(QChar::Punctuation_Other);
- return U_MASK(QChar::category(c)) & test;
- }
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return QChar::category(c) == QChar::Separator_Space;
+}
- inline bool isDigit(UChar32 c)
- {
- return QChar::category(c) == QChar::Number_DecimalDigit;
- }
+inline bool isPunct(UChar32 c)
+{
+ const uint test = U_MASK(QChar::Punctuation_Connector) |
+ U_MASK(QChar::Punctuation_Dash) |
+ U_MASK(QChar::Punctuation_Open) |
+ U_MASK(QChar::Punctuation_Close) |
+ U_MASK(QChar::Punctuation_InitialQuote) |
+ U_MASK(QChar::Punctuation_FinalQuote) |
+ U_MASK(QChar::Punctuation_Other);
+ return U_MASK(QChar::category(c)) & test;
+}
- inline bool isLower(UChar32 c)
- {
- return QChar::category(c) == QChar::Letter_Lowercase;
- }
+inline bool isLower(UChar32 c)
+{
+ return QChar::category(c) == QChar::Letter_Lowercase;
+}
- inline int digitValue(UChar32 c)
- {
- return QChar::digitValue(c);
- }
+inline bool hasLineBreakingPropertyComplexContext(UChar32)
+{
+ // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context).
+ return false;
+}
- inline UChar32 mirroredChar(UChar32 c)
- {
- return QChar::mirroredChar(c);
- }
+inline UChar32 mirroredChar(UChar32 c)
+{
+ return QChar::mirroredChar(c);
+}
- inline uint8_t combiningClass(UChar32 c)
- {
- return QChar::combiningClass(c);
- }
+inline uint8_t combiningClass(UChar32 c)
+{
+ return QChar::combiningClass(c);
+}
- inline DecompositionType decompositionType(UChar32 c)
- {
- return (DecompositionType)QChar::decompositionTag(c);
- }
+inline DecompositionType decompositionType(UChar32 c)
+{
+ return (DecompositionType)QChar::decompositionTag(c);
+}
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- // handle surrogates correctly
- for (int i = 0; i < len; ++i) {
- uint c1 = QChar::toCaseFolded(a[i]);
- uint c2 = QChar::toCaseFolded(b[i]);
- if (c1 != c2)
- return c1 - c2;
- }
- return 0;
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ // handle surrogates correctly
+ for (int i = 0; i < len; ++i) {
+ uint c1 = QChar::toCaseFolded(ushort(a[i]));
+ uint c2 = QChar::toCaseFolded(ushort(b[i]));
+ if (c1 != c2)
+ return c1 - c2;
}
+ return 0;
+}
- inline Direction direction(UChar32 c)
- {
- return (Direction)QChar::direction(c);
- }
+inline Direction direction(UChar32 c)
+{
+ return (Direction)QChar::direction(c);
+}
- inline CharCategory category(UChar32 c)
- {
- return (CharCategory) U_MASK(QChar::category(c));
- }
+inline CharCategory category(UChar32 c)
+{
+ return (CharCategory) U_MASK(QChar::category(c));
+}
#else
- inline UChar32 toLower(UChar32 ch)
- {
- if (ch > 0xffff)
+inline UChar32 toLower(UChar32 ch)
+{
+ if (ch > 0xffff)
return ch;
- return QChar((unsigned short)ch).toLower().unicode();
- }
+ return QChar((unsigned short)ch).toLower().unicode();
+}
- inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- *error = false;
- if (resultLength < srcLength) {
- *error = true;
- return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar(src[i]).toLower().unicode();
- return srcLength;
- }
+inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ if (resultLength < srcLength) {
+ *error = true;
+ return srcLength;
+ }
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar(src[i]).toLower().unicode();
+ return srcLength;
+}
- inline UChar32 toUpper(UChar32 ch)
- {
- if (ch > 0xffff)
+inline UChar32 toUpper(UChar32 ch)
+{
+ if (ch > 0xffff)
return ch;
- return QChar((unsigned short)ch).toUpper().unicode();
- }
+ return QChar((unsigned short)ch).toUpper().unicode();
+}
- inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- *error = false;
- if (resultLength < srcLength) {
+inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ if (resultLength < srcLength) {
*error = true;
return srcLength;
- }
- for (int i = 0; i < srcLength; ++i)
- result[i] = QChar(src[i]).toUpper().unicode();
- return srcLength;
}
+ for (int i = 0; i < srcLength; ++i)
+ result[i] = QChar(src[i]).toUpper().unicode();
+ return srcLength;
+}
- inline int toTitleCase(UChar32 c)
- {
- if (c > 0xffff)
+inline int toTitleCase(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar((unsigned short)c).toUpper().unicode();
- }
+ return QChar((unsigned short)c).toUpper().unicode();
+}
- inline UChar32 foldCase(UChar32 c)
- {
- if (c > 0xffff)
+inline UChar32 foldCase(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar((unsigned short)c).toLower().unicode();
- }
-
- inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
- {
- return toLower(result, resultLength, src, srcLength, error);
- }
-
- inline bool isFormatChar(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Other_Format;
- }
-
- inline bool isPrintableChar(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
- }
+ return QChar((unsigned short)c).toLower().unicode();
+}
- inline bool isArabicChar(UChar32 c)
- {
- return c >= 0x0600 && c <= 0x06FF;
- }
+inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ return toLower(result, resultLength, src, srcLength, error);
+}
- inline bool isSeparatorSpace(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
- }
+inline bool isPrintableChar(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
+}
- inline bool isPunct(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
- }
+inline bool isArabicChar(UChar32 c)
+{
+ return c >= 0x0600 && c <= 0x06FF;
+}
- inline bool isDigit(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isDigit();
- }
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
+}
- inline bool isLower(UChar32 c)
- {
- return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
- }
+inline bool isPunct(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
+}
- inline int digitValue(UChar32 c)
- {
- if (c > 0xffff)
- return 0;
- return QChar(c).digitValue();
- }
+inline bool isLower(UChar32 c)
+{
+ return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
+}
- inline UChar32 mirroredChar(UChar32 c)
- {
- if (c > 0xffff)
+inline UChar32 mirroredChar(UChar32 c)
+{
+ if (c > 0xffff)
return c;
- return QChar(c).mirroredChar().unicode();
- }
+ return QChar(c).mirroredChar().unicode();
+}
- inline uint8_t combiningClass(UChar32 c)
- {
- if (c > 0xffff)
+inline uint8_t combiningClass(UChar32 c)
+{
+ if (c > 0xffff)
return 0;
- return QChar((unsigned short)c).combiningClass();
- }
+ return QChar((unsigned short)c).combiningClass();
+}
- inline DecompositionType decompositionType(UChar32 c)
- {
- if (c > 0xffff)
+inline DecompositionType decompositionType(UChar32 c)
+{
+ if (c > 0xffff)
return DecompositionNone;
- return (DecompositionType)QChar(c).decompositionTag();
- }
+ return (DecompositionType)QChar(c).decompositionTag();
+}
- inline int umemcasecmp(const UChar* a, const UChar* b, int len)
- {
- for (int i = 0; i < len; ++i) {
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ for (int i = 0; i < len; ++i) {
QChar c1 = QChar(a[i]).toLower();
QChar c2 = QChar(b[i]).toLower();
if (c1 != c2)
- return c1.unicode() - c2.unicode();
- }
- return 0;
+ return c1.unicode() - c2.unicode();
}
+ return 0;
+}
- inline Direction direction(UChar32 c)
- {
- if (c > 0xffff)
+inline Direction direction(UChar32 c)
+{
+ if (c > 0xffff)
return LeftToRight;
- return (Direction)QChar(c).direction();
- }
+ return (Direction)QChar(c).direction();
+}
- inline CharCategory category(UChar32 c)
- {
- if (c > 0xffff)
+inline CharCategory category(UChar32 c)
+{
+ if (c > 0xffff)
return NoCategory;
- return (CharCategory) U_MASK(QChar(c).category());
- }
+ return (CharCategory) U_MASK(QChar(c).category());
+}
#endif
- }
-}
+} }
-#endif
-// vim: ts=2 sw=2 et
+#endif // WTF_UNICODE_QT4_H
--- /dev/null
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "Assertions.h"
+#include "Threading.h"
+#if !PLATFORM(WIN_CE)
+#include <windows.h>
+#endif
+
+namespace WTF {
+
+static HWND threadingWindowHandle;
+static UINT threadingFiredMessage;
+const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass";
+
+LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == threadingFiredMessage)
+ dispatchFunctionsFromMainThread();
+ else
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ return 0;
+}
+
+void initializeMainThread()
+{
+ if (threadingWindowHandle)
+ return;
+
+ mainThreadFunctionQueueMutex();
+
+ WNDCLASSEX wcex;
+ memset(&wcex, 0, sizeof(WNDCLASSEX));
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.lpfnWndProc = ThreadingWindowWndProc;
+ wcex.lpszClassName = kThreadingWindowClassName;
+ RegisterClassEx(&wcex);
+
+ threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, 0);
+ threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ ASSERT(threadingWindowHandle);
+ PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
+}
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2007 Kevin Ollivier
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+namespace WTF {
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+}
+
+}