#ifndef APICast_h
#define APICast_h
+#include "JSAPIValueWrapper.h"
#include "JSValue.h"
+#include <wtf/Platform.h>
+#include <wtf/UnusedParam.h>
namespace JSC {
class ExecState;
class PropertyNameArray;
class JSGlobalData;
class JSObject;
- class JSValuePtr;
+ class JSValue;
}
typedef const struct OpaqueJSContextGroup* JSContextGroupRef;
return reinterpret_cast<JSC::ExecState*>(c);
}
-inline JSC::JSValuePtr toJS(JSValueRef v)
+inline JSC::JSValue toJS(JSC::ExecState*, JSValueRef v)
{
- return JSC::JSValuePtr::decode(reinterpret_cast<JSC::JSValueEncodedAsPointer*>(const_cast<OpaqueJSValue*>(v)));
+#if USE(JSVALUE32_64)
+ JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
+ if (!jsCell)
+ return JSC::JSValue();
+ if (jsCell->isAPIValueWrapper())
+ return static_cast<JSC::JSAPIValueWrapper*>(jsCell)->value();
+ return jsCell;
+#else
+ return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v)));
+#endif
}
inline JSC::JSObject* toJS(JSObjectRef o)
return reinterpret_cast<JSC::JSGlobalData*>(const_cast<OpaqueJSContextGroup*>(g));
}
-inline JSValueRef toRef(JSC::JSValuePtr v)
+inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v)
{
- return reinterpret_cast<JSValueRef>(JSC::JSValuePtr::encode(v));
-}
-
-inline JSValueRef* toRef(JSC::JSValuePtr* v)
-{
- return reinterpret_cast<JSValueRef*>(v);
+#if USE(JSVALUE32_64)
+ if (!v)
+ return 0;
+ if (!v.isCell())
+ return reinterpret_cast<JSValueRef>(asCell(JSC::jsAPIValueWrapper(exec, v)));
+ return reinterpret_cast<JSValueRef>(asCell(v));
+#else
+ UNUSED_PARAM(exec);
+ return reinterpret_cast<JSValueRef>(JSC::JSValue::encode(v));
+#endif
}
inline JSObjectRef toRef(JSC::JSObject* o)
if (completion.complType() == Throw) {
if (exception)
- *exception = toRef(completion.value());
+ *exception = toRef(exec, completion.value());
return 0;
}
-
+
if (completion.value())
- return toRef(completion.value());
+ return toRef(exec, completion.value());
// happens, for example, when the only statement is an empty (';') statement
- return toRef(jsUndefined());
+ return toRef(exec, jsUndefined());
}
bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
if (completion.complType() == Throw) {
if (exception)
- *exception = toRef(completion.value());
+ *exception = toRef(exec, completion.value());
return false;
}
/* JavaScript symbol exports */
#undef JS_EXPORT
-#if defined(__GNUC__)
+#if defined(BUILDING_WX__)
+ #define JS_EXPORT
+#elif defined(__GNUC__)
#define JS_EXPORT __attribute__((visibility("default")))
+#elif defined(_WIN32_WCE)
+ #if defined(JS_BUILDING_JS)
+ #define JS_EXPORT __declspec(dllexport)
+ #elif defined(JS_IMPORT_JS)
+ #define JS_EXPORT __declspec(dllimport)
+ #else
+ #define JS_EXPORT
+ #endif
#elif defined(WIN32) || defined(_WIN32)
/*
* TODO: Export symbols with JS_EXPORT when using MSVC.
* See http://bugs.webkit.org/show_bug.cgi?id=16227
*/
- #define JS_EXPORT
+ #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
+ #define JS_EXPORT __declspec(dllexport)
+ #else
+ #define JS_EXPORT __declspec(dllimport)
+ #endif
#else
#define JS_EXPORT
#endif
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;
+JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) AVAILABLE_IN_WEBKIT_VERSION_4_0;
#ifdef __cplusplus
}
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args.at(exec, i));
-
- JSLock::DropAllLocks dropAllLocks(exec);
- return toJS(callback(ctx, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ arguments[i] = toRef(exec, args.at(i));
+
+ JSValueRef exception = 0;
+ JSObjectRef result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception);
+ }
+ if (exception)
+ exec->setException(toJS(exec, exception));
+ return toJS(result);
}
return toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0));
JSObjectCallAsConstructorCallback callback() const { return m_callback; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
}
{
}
-JSValuePtr JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args)
+JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args)
{
JSContextRef execRef = toRef(exec);
JSObjectRef functionRef = toRef(functionObject);
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args.at(exec, i));
+ arguments[i] = toRef(exec, args.at(i));
- JSLock::DropAllLocks dropAllLocks(exec);
- return toJS(static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ JSValueRef exception = 0;
+ JSValueRef result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
+ }
+ if (exception)
+ exec->setException(toJS(exec, exception));
+
+ return toJS(exec, result);
}
CallType JSCallbackFunction::getCallData(CallData& callData)
// InternalFunction mish-mashes constructor and function behavior -- we should
// refactor the code so this override isn't necessary
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
}
virtual CallType getCallData(CallData&);
virtual const ClassInfo* classInfo() const { return &info; }
- static JSValuePtr call(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ static JSValue JSC_HOST_CALL call(ExecState*, JSObject*, JSValue, const ArgList&);
JSObjectCallAsFunctionCallback m_callback;
};
JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
bool inherits(JSClassRef) const;
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance));
}
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier&);
virtual bool deleteProperty(ExecState*, unsigned);
- virtual bool hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto);
+ virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
void init(ExecState*);
- static JSCallbackObject* asCallbackObject(JSValuePtr);
+ static JSCallbackObject* asCallbackObject(JSValue);
- static JSValuePtr call(ExecState*, JSObject* functionObject, JSValuePtr thisValue, const ArgList&);
+ static JSValue JSC_HOST_CALL call(ExecState*, JSObject* functionObject, JSValue 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&);
+ static JSValue staticValueGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue callbackGetter(ExecState*, const Identifier&, const PropertySlot&);
struct JSCallbackObjectData {
JSCallbackObjectData(void* privateData, JSClassRef jsClass)
namespace JSC {
template <class Base>
-inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValuePtr value)
+inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue value)
{
ASSERT(asObject(value)->inherits(&info));
return static_cast<JSCallbackObject*>(asObject(value));
UString JSCallbackObject<Base>::className() const
{
UString thisClassName = classRef()->className();
- if (!thisClassName.isNull())
+ if (!thisClassName.isEmpty())
return thisClassName;
return Base::className();
} else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
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));
+ JSValueRef exception = 0;
+ JSValueRef value;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (value) {
+ slot.setValue(toJS(exec, value));
+ return true;
+ }
+ if (exception) {
+ slot.setValue(jsUndefined());
return true;
}
}
}
template <class Base>
-void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
JSContextRef ctx = toRef(exec);
JSObjectRef thisRef = toRef(this);
RefPtr<OpaqueJSString> propertyNameRef;
- JSValueRef valueRef = toRef(value);
+ JSValueRef valueRef = toRef(exec, value);
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
- JSLock::DropAllLocks dropAllLocks(exec);
- if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
+ JSValueRef exception = 0;
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (result || exception)
return;
}
if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
- JSLock::DropAllLocks dropAllLocks(exec);
- if (setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, toRef(exec->exceptionSlot())))
+ JSValueRef exception = 0;
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (result || exception)
return;
} else
throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
- JSLock::DropAllLocks dropAllLocks(exec);
- if (deleteProperty(ctx, thisRef, propertyNameRef.get(), toRef(exec->exceptionSlot())))
+ JSValueRef exception = 0;
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (result || exception)
return true;
}
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args.at(exec, i));
- JSLock::DropAllLocks dropAllLocks(exec);
- return toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ arguments[i] = toRef(exec, args.at(i));
+ JSValueRef exception = 0;
+ JSObject* result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception));
+ }
+ exec->setException(toJS(exec, exception));
+ return result;
}
}
}
template <class Base>
-bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr)
+bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue)
{
JSContextRef execRef = toRef(exec);
JSObjectRef thisRef = toRef(this);
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
- JSLock::DropAllLocks dropAllLocks(exec);
- return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
+ JSValueRef valueRef = toRef(exec, value);
+ JSValueRef exception = 0;
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = hasInstance(execRef, thisRef, valueRef, &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ return result;
}
}
return false;
}
template <class Base>
-JSValuePtr JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args)
+JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args)
{
JSContextRef execRef = toRef(exec);
JSObjectRef functionRef = toRef(functionObject);
int argumentCount = static_cast<int>(args.size());
Vector<JSValueRef, 16> arguments(argumentCount);
for (int i = 0; i < argumentCount; i++)
- arguments[i] = toRef(args.at(exec, i));
- JSLock::DropAllLocks dropAllLocks(exec);
- return toJS(callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
+ arguments[i] = toRef(exec, args.at(i));
+ JSValueRef exception = 0;
+ JSValue result;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception));
+ }
+ exec->setException(toJS(exec, exception));
+ return result;
}
}
ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
- return noValue();
+ return JSValue();
}
template <class Base>
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
- JSLock::DropAllLocks dropAllLocks(exec);
- if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot()))) {
- double dValue;
- return toJS(value).getNumber(dValue) ? dValue : NaN;
+ JSValueRef exception = 0;
+ JSValueRef value;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
}
+ if (exception) {
+ exec->setException(toJS(exec, exception));
+ return 0;
+ }
+
+ double dValue;
+ return toJS(exec, value).getNumber(dValue) ? dValue : NaN;
}
return Base::toNumber(exec);
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
+ JSValueRef exception = 0;
JSValueRef value;
{
JSLock::DropAllLocks dropAllLocks(exec);
- value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot()));
+ value = convertToType(ctx, thisRef, kJSTypeString, &exception);
}
- if (value)
- return toJS(value).getString();
+ if (exception) {
+ exec->setException(toJS(exec, exception));
+ return "";
+ }
+ return toJS(exec, value).getString();
}
return Base::toString(exec);
}
template <class Base>
-JSValuePtr JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
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);
+ JSValueRef exception = 0;
+ JSValueRef value;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (value)
+ return toJS(exec, value);
+ if (exception)
+ return jsUndefined();
}
return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
}
template <class Base>
-JSValuePtr JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
}
template <class Base>
-JSValuePtr JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
+JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
JSCallbackObject* thisObj = asCallbackObject(slot.slotBase());
if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
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);
+ JSValueRef exception = 0;
+ JSValueRef value;
+ {
+ JSLock::DropAllLocks dropAllLocks(exec);
+ value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
+ }
+ exec->setException(toJS(exec, exception));
+ if (value)
+ return toJS(exec, value);
+ if (exception)
+ return jsUndefined();
}
return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass);
ExecState* exec = globalObject->globalExec();
- JSValuePtr prototype = globalObjectClass->prototype(exec);
+ JSValue prototype = globalObjectClass->prototype(exec);
if (!prototype)
prototype = jsNull();
globalObject->resetPrototype(prototype);
synchronization is required.
@result The created JSContextGroup.
*/
-JS_EXPORT JSContextGroupRef JSContextGroupCreate() AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+JS_EXPORT JSContextGroupRef JSContextGroupCreate() AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@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;
+JS_EXPORT void JSContextGroupRelease(JSContextGroupRef group) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSContextGroupRef JSContextGetGroup(JSContextRef ctx) AVAILABLE_IN_WEBKIT_VERSION_4_0;
#ifdef __cplusplus
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsPrototype = jsClass
- ? jsClass->prototype(exec)
- : exec->lexicalGlobalObject()->objectPrototype();
-
+ JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
+ if (!jsPrototype)
+ jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
+
JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
return toRef(constructor);
Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
- ArgList args;
+ MarkedArgumentBuffer args;
for (unsigned i = 0; i < parameterCount; i++)
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());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
JSObject* result;
if (argumentCount) {
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
result = constructArray(exec, argList);
} else
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
JSObject* result = constructDate(exec, argList);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
JSObject* result = constructError(exec, argList);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
JSObject* result = constructRegExp(exec, argList);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
return toRef(result);
}
-JSValueRef JSObjectGetPrototype(JSContextRef, JSObjectRef object)
+JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- return toRef(jsObject->prototype());
+ return toRef(exec, jsObject->prototype());
}
-void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value)
+void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
{
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
JSObject* jsObject = toJS(object);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull());
}
JSObject* jsObject = toJS(object);
- JSValuePtr jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
+ JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
- return toRef(jsValue);
+ return toRef(exec, jsValue);
}
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
JSObject* jsObject = toJS(object);
Identifier name(propertyName->identifier(&exec->globalData()));
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
if (attributes && !jsObject->hasProperty(exec, name))
jsObject->putWithAttributes(exec, name, jsValue, attributes);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
}
JSObject* jsObject = toJS(object);
- JSValuePtr jsValue = jsObject->get(exec, propertyIndex);
+ JSValue jsValue = jsObject->get(exec, propertyIndex);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
- return toRef(jsValue);
+ return toRef(exec, jsValue);
}
JSLock lock(exec);
JSObject* jsObject = toJS(object);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
jsObject->put(exec, propertyIndex, jsValue);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
}
bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
return result;
if (!jsThisObject)
jsThisObject = exec->globalThisValue();
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; i++)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
CallData callData;
CallType callType = jsObject->getCallData(callData);
if (callType == CallTypeNone)
return 0;
- JSValueRef result = toRef(call(exec, jsObject, callType, callData, jsThisObject, argList));
+ JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
if (constructType == ConstructTypeNone)
return 0;
- ArgList argList;
+ MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; i++)
- argList.append(toJS(arguments[i]));
+ argList.append(toJS(exec, arguments[i]));
JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
result = 0;
}
@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;
+JS_EXPORT JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
@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;
+JS_EXPORT JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0;
/*!
@function
#include <algorithm> // for std::min
-JSType JSValueGetType(JSContextRef, JSValueRef value)
+JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
{
- JSC::JSValuePtr jsValue = toJS(value);
+ JSC::ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSC::JSLock lock(exec);
+
+ JSC::JSValue jsValue = toJS(exec, value);
+
if (jsValue.isUndefined())
return kJSTypeUndefined;
if (jsValue.isNull())
using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above.
-bool JSValueIsUndefined(JSContextRef, JSValueRef value)
+bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isUndefined();
}
-bool JSValueIsNull(JSContextRef, JSValueRef value)
+bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isNull();
}
-bool JSValueIsBoolean(JSContextRef, JSValueRef value)
+bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isBoolean();
}
-bool JSValueIsNumber(JSContextRef, JSValueRef value)
+bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isNumber();
}
-bool JSValueIsString(JSContextRef, JSValueRef value)
+bool JSValueIsString(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isString();
}
-bool JSValueIsObject(JSContextRef, JSValueRef value)
+bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.isObject();
}
-bool JSValueIsObjectOfClass(JSContextRef, JSValueRef value, JSClassRef jsClass)
+bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
{
- JSValuePtr jsValue = toJS(value);
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
if (JSObject* o = jsValue.getObject()) {
if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsA = toJS(a);
- JSValuePtr jsB = toJS(b);
+ JSValue jsA = toJS(exec, a);
+ JSValue jsB = toJS(exec, b);
- bool result = JSValuePtr::equal(exec, jsA, jsB); // false if an exception is thrown
+ bool result = JSValue::equal(exec, jsA, jsB); // false if an exception is thrown
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
return result;
}
-bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b)
+bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
{
- JSValuePtr jsA = toJS(a);
- JSValuePtr jsB = toJS(b);
-
- bool result = JSValuePtr::strictEqual(jsA, jsB);
- return result;
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsA = toJS(exec, a);
+ JSValue jsB = toJS(exec, b);
+
+ return JSValue::strictEqual(jsA, jsB);
}
bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
+
JSObject* jsConstructor = toJS(constructor);
if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
return false;
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());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
}
return result;
}
-JSValueRef JSValueMakeUndefined(JSContextRef)
+JSValueRef JSValueMakeUndefined(JSContextRef ctx)
{
- return toRef(jsUndefined());
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ return toRef(exec, jsUndefined());
}
-JSValueRef JSValueMakeNull(JSContextRef)
+JSValueRef JSValueMakeNull(JSContextRef ctx)
{
- return toRef(jsNull());
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ return toRef(exec, jsNull());
}
-JSValueRef JSValueMakeBoolean(JSContextRef, bool value)
+JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
{
- return toRef(jsBoolean(value));
+ ExecState* exec = toJS(ctx);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ return toRef(exec, jsBoolean(value));
}
JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
exec->globalData().heap.registerThread();
JSLock lock(exec);
- return toRef(jsNumber(exec, value));
+ return toRef(exec, jsNumber(exec, value));
}
JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
exec->globalData().heap.registerThread();
JSLock lock(exec);
- return toRef(jsString(exec, string->ustring()));
+ return toRef(exec, jsString(exec, string->ustring()));
}
bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
{
ExecState* exec = toJS(ctx);
- JSValuePtr jsValue = toJS(value);
+ exec->globalData().heap.registerThread();
+ JSLock lock(exec);
+
+ JSValue jsValue = toJS(exec, value);
return jsValue.toBoolean(exec);
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
double number = jsValue.toNumber(exec);
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
number = NaN;
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
stringRef.clear();
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
JSObjectRef objectRef = toRef(jsValue.toObject(exec));
if (exec->hadException()) {
if (exception)
- *exception = toRef(exec->exception());
+ *exception = toRef(exec, exec->exception());
exec->clearException();
objectRef = 0;
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
gcProtect(jsValue);
}
exec->globalData().heap.registerThread();
JSLock lock(exec);
- JSValuePtr jsValue = toJS(value);
+ JSValue jsValue = toJS(exec, value);
gcUnprotect(jsValue);
}
#define WEBKIT_VERSION_2_0 0x0200
#define WEBKIT_VERSION_3_0 0x0300
#define WEBKIT_VERSION_3_1 0x0310
+#define WEBKIT_VERSION_4_0 0x0400
#define WEBKIT_VERSION_LATEST 0x9999
#ifdef __APPLE__
/*
- * AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_IN_WEBKIT_VERSION_4_0
*
- * Used on declarations introduced after WebKit 3.1
+ * Used on declarations introduced in WebKit 4.0
*/
#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST
- #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1 UNAVAILABLE_ATTRIBUTE
+ #define AVAILABLE_IN_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE
#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST
- #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1 WEAK_IMPORT_ATTRIBUTE
+ #define AVAILABLE_IN_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE
#else
- #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+ #define AVAILABLE_IN_WEBKIT_VERSION_4_0
#endif
/*
- * AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED
+ * AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED
*
- * Used on declarations introduced after WebKit 3.1,
- * and deprecated after WebKit 3.1
+ * Used on declarations introduced in WebKit 4.0,
+ * and deprecated in WebKit 4.0
*/
#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
- #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
+ #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE
#else
- #define AVAILABLE_AFTER_WEBKIT_VERSION_3_1_BUT_DEPRECATED AVAILABLE_AFTER_WEBKIT_VERSION_3_1
+ #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_IN_WEBKIT_VERSION_4_0
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 1.0,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 1.1,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 1.2,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 1.3,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 2.0,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 3.0,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER
#endif
/*
- * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0
*
* Used on declarations introduced in WebKit 3.1,
- * but later deprecated after WebKit 3.1
+ * but later deprecated in WebKit 4.0
*/
#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
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 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
+ #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER
#endif
/*
- * DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ * DEPRECATED_IN_WEBKIT_VERSION_4_0
*
- * Used on types deprecated after WebKit 3.1
+ * Used on types deprecated in WebKit 4.0
*/
#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST
- #define DEPRECATED_AFTER_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE
+ #define DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE
#else
- #define DEPRECATED_AFTER_WEBKIT_VERSION_3_1
+ #define DEPRECATED_IN_WEBKIT_VERSION_4_0
#endif
#include "JavaScriptCore.h"
#include "JSBasePrivate.h"
#include <math.h>
+#define ASSERT_DISABLED 0
#include <wtf/Assertions.h>
#include <wtf/UnusedParam.h>
#endif
static JSGlobalContextRef context = 0;
-
+static int failed = 0;
static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
{
- if (JSValueToBoolean(context, value) != expectedValue)
+ if (JSValueToBoolean(context, value) != expectedValue) {
fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
+ failed = 1;
+ }
}
static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
// 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)))
+ if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue))) {
fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
+ failed = 1;
+ }
}
static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
unsigned i;
- for (i = 0; jsBuffer[i]; i++)
- if (jsBuffer[i] != expectedValue[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)
+ failed = 1;
+ }
+ }
+
+ if (jsSize < strlen(jsBuffer) + 1) {
fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
+ failed = 1;
+ }
free(jsBuffer);
JSStringRelease(valueAsString);
CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
CFRelease(expectedValueAsCFString);
- if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0)
+ if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0) {
fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
+ failed = 1;
+ }
- if (jsLength != (size_t)cfLength)
+ if (jsLength != (size_t)cfLength) {
fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, cfLength);
-
+ failed = 1;
+ }
+
free(cfBuffer);
JSStringRelease(valueAsString);
}
+static bool timeZoneIsPST()
+{
+ char timeZoneName[70];
+ struct tm gtm;
+ memset(>m, 0, sizeof(gtm));
+ strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m);
+
+ return 0 == strcmp("PST", timeZoneName);
+}
+
static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
/* MyObject pseudo-class */
if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
|| JSStringIsEqualToUTF8CString(propertyName, "cantFind")
+ || JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")
|| JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
|| JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
|| JSStringIsEqualToUTF8CString(propertyName, "0")) {
if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
return JSValueMakeUndefined(context);
}
-
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
+ return JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ }
+
if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
*exception = JSValueMakeNumber(context, 1);
return JSValueMakeNumber(context, 1);
if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
return true; // pretend we set the property in order to swallow it
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnSet")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ }
+
return false;
}
return true;
if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
- *exception = JSValueMakeNumber(context, 2);
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
return false;
}
UNUSED_PARAM(thisObject);
UNUSED_PARAM(exception);
+ if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnCall")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return JSValueMakeUndefined(context);
+ }
+
if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
return JSValueMakeNumber(context, 1);
UNUSED_PARAM(context);
UNUSED_PARAM(object);
+ if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnConstruct")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return object;
+ }
+
if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
UNUSED_PARAM(context);
UNUSED_PARAM(constructor);
+ if (JSValueIsString(context, possibleValue) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, possibleValue, 0), "throwOnHasInstance")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return false;
+ }
+
JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
JSStringRelease(numberString);
return jsClass;
}
+static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructor);
+
+ JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
+ JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
+ JSStringRelease(hasInstanceName);
+ if (!hasInstance)
+ return false;
+ JSObjectRef function = JSValueToObject(context, hasInstance, exception);
+ JSValueRef result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
+ return result && JSValueToBoolean(context, result);
+}
+
+static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(exception);
+ JSStringRef funcName;
+ switch (type) {
+ case kJSTypeNumber:
+ funcName = JSStringCreateWithUTF8CString("toNumber");
+ break;
+ case kJSTypeString:
+ funcName = JSStringCreateWithUTF8CString("toStringExplicit");
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
+ JSStringRelease(funcName);
+ JSObjectRef function = JSValueToObject(context, func, exception);
+ if (!function)
+ return NULL;
+ JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
+ if (!value) {
+ JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed");
+ JSValueRef errorStringRef = JSValueMakeString(context, errorString);
+ JSStringRelease(errorString);
+ return errorStringRef;
+ }
+ return value;
+}
+
+JSClassDefinition EvilExceptionObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "EvilExceptionObject",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ EvilExceptionObject_hasInstance,
+ EvilExceptionObject_convertToType,
+};
+
+static JSClassRef EvilExceptionObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&EvilExceptionObject_definition);
+
+ return jsClass;
+}
+
+JSClassDefinition EmptyObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static JSClassRef EmptyObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&EmptyObject_definition);
+
+ return jsClass;
+}
+
+
static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
UNUSED_PARAM(object);
return JSValueMakeNumber(ctx, 3);
}
+static JSValueRef functionGC(JSContextRef context, 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);
+ JSGarbageCollect(context);
+ return JSValueMakeUndefined(context);
+}
+
static JSStaticValue globalObject_staticValues[] = {
{ "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
{ 0, 0, 0, 0 }
static JSStaticFunction globalObject_staticFunctions[] = {
{ "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
+ { "gc", functionGC, kJSPropertyAttributeNone },
{ 0, 0, 0 }
};
JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
JSStringRelease(myObjectIString);
+ JSObjectRef EvilExceptionObject = JSObjectMake(context, EvilExceptionObject_class(context), NULL);
+ JSStringRef EvilExceptionObjectIString = JSStringCreateWithUTF8CString("EvilExceptionObject");
+ JSObjectSetProperty(context, globalObject, EvilExceptionObjectIString, EvilExceptionObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(EvilExceptionObjectIString);
+
+ JSObjectRef EmptyObject = JSObjectMake(context, EmptyObject_class(context), NULL);
+ JSStringRef EmptyObjectIString = JSStringCreateWithUTF8CString("EmptyObject");
+ JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(EmptyObjectIString);
+
JSValueRef exception;
// Conversions that throw exceptions
JSStringRelease(functionBody);
string = JSValueToStringCopy(context, function, NULL);
- assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {return foo;}");
+ assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) { return foo;\n}");
JSStringRelease(string);
JSStringRef print = JSStringCreateWithUTF8CString("print");
JSValueRef argumentsDateValues[] = { JSValueMakeNumber(context, 0) };
o = JSObjectMakeDate(context, 1, argumentsDateValues, NULL);
- assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
+ if (timeZoneIsPST())
+ assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
string = JSStringCreateWithUTF8CString("an error message");
JSValueRef argumentsErrorValues[] = { JSValueMakeString(context, string) };
ASSERT(JSValueIsEqual(context, v, o, NULL));
JSStringRelease(script);
+ // Verify that creating a constructor for a class with no static functions does not trigger
+ // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
+ nullDefinition = kJSClassDefinitionEmpty;
+ nullClass = JSClassCreate(&nullDefinition);
+ myConstructor = JSObjectMakeConstructor(context, nullClass, 0);
+ JSClassRelease(nullClass);
+
char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
- if (!scriptUTF8)
+ if (!scriptUTF8) {
printf("FAIL: Test script could not be loaded.\n");
- else {
+ failed = 1;
+ } else {
script = JSStringCreateWithUTF8CString(scriptUTF8);
result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
if (JSValueIsUndefined(context, result))
CFShow(exceptionCF);
CFRelease(exceptionCF);
JSStringRelease(exceptionIString);
+ failed = 1;
}
JSStringRelease(script);
free(scriptUTF8);
v = NULL;
o = NULL;
globalObject = NULL;
+ myConstructor = NULL;
JSStringRelease(jsEmptyIString);
JSStringRelease(jsOneIString);
JSGlobalContextRelease(context);
JSClassRelease(globalObjectClass);
+ // Test for an infinite prototype chain that used to be created. This test
+ // passes if the call to JSObjectHasProperty() does not hang.
+
+ JSClassDefinition prototypeLoopClassDefinition = kJSClassDefinitionEmpty;
+ prototypeLoopClassDefinition.staticFunctions = globalObject_staticFunctions;
+ JSClassRef prototypeLoopClass = JSClassCreate(&prototypeLoopClassDefinition);
+ JSGlobalContextRef prototypeLoopContext = JSGlobalContextCreateInGroup(NULL, prototypeLoopClass);
+
+ JSStringRef nameProperty = JSStringCreateWithUTF8CString("name");
+ JSObjectHasProperty(prototypeLoopContext, JSContextGetGlobalObject(prototypeLoopContext), nameProperty);
+
+ JSGlobalContextRelease(prototypeLoopContext);
+ JSClassRelease(prototypeLoopClass);
+
+ printf("PASS: Infinite prototype chain does not occur.\n");
+
+ if (failed) {
+ printf("FAIL: Some tests failed.\n");
+ return 1;
+ }
+
printf("PASS: Program exited normally.\n");
return 0;
}
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+function bludgeonArguments() { if (0) arguments; return function g() {} }
+h = bludgeonArguments();
+gc();
+
+var failed = false;
+function pass(msg)
+{
+ print("PASS: " + msg, "green");
+}
+
+function fail(msg)
+{
+ print("FAIL: " + msg, "red");
+ failed = true;
+}
+
function shouldBe(a, b)
{
var evalA;
}
if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
- print("PASS: " + a + " should be " + b + " and is.", "green");
+ pass(a + " should be " + b + " and is.");
else
- print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
+ fail(a + " should be " + b + " but instead is " + evalA + ".");
}
function shouldThrow(a)
{
- var result = "__FAIL__: " + a + " did not throw an exception.";
-
var evalA;
try {
eval(a);
} catch(e) {
- result = "PASS: " + a + " threw: " + e;
+ pass(a + " threw: " + e);
+ return;
}
-
- print(result);
+
+ fail(a + " did not throw an exception.");
}
function globalStaticFunction()
MyObject.cantDelete = 1;
delete MyObject.cantDelete;
shouldBe("MyObject.cantDelete", 1);
-shouldBe("delete MyObject.throwOnDelete", 2); // deleteProperty -- should throw 2
+shouldBe("delete MyObject.throwOnDelete", "an exception");
MyObject.cantSet = 1;
shouldBe("MyObject.cantSet", undefined);
+shouldBe("MyObject.throwOnGet", "an exception");
+shouldBe("MyObject.throwOnSet = 5", "an exception");
+shouldBe("MyObject('throwOnCall')", "an exception");
+shouldBe("new MyObject('throwOnConstruct')", "an exception");
+shouldBe("'throwOnHasInstance' instanceof MyObject", "an exception");
var foundMyPropertyName = false;
var foundRegularType = false;
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");
+
+if (foundMyPropertyName)
+ pass("MyObject.myPropertyName was enumerated");
+else
+ fail("MyObject.myPropertyName was not enumerated");
+
+if (foundRegularType)
+ pass("MyObject.regularType was enumerated");
+else
+ fail("MyObject.regularType was not enumerated");
myObject = new MyObject();
shouldBe("+MyObject", 1); // toNumber
shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
shouldBe("String(MyObject)", "MyObjectAsString"); // type conversion to string
-shouldBe("MyObject - 0", NaN); // toPrimitive
+shouldBe("MyObject - 0", 1); // toNumber
shouldBe("typeof MyConstructor", "object");
constructedObject = new MyConstructor(1);
shouldBe("derived.baseOnly = 0", 1);
shouldBe("derived.derivedOnly = 0", 2)
shouldBe("derived.protoDup = 0", 2);
+
+shouldBe("undefined instanceof MyObject", false);
+EvilExceptionObject.hasInstance = function f() { return f(); };
+EvilExceptionObject.__proto__ = undefined;
+shouldThrow("undefined instanceof EvilExceptionObject");
+EvilExceptionObject.hasInstance = function () { return true; };
+shouldBe("undefined instanceof EvilExceptionObject", true);
+
+EvilExceptionObject.toNumber = function f() { return f(); }
+shouldThrow("EvilExceptionObject*5");
+EvilExceptionObject.toStringExplicit = function f() { return f(); }
+shouldThrow("String(EvilExceptionObject)");
+
+shouldBe("EmptyObject", "[object CallbackObject]");
+
+if (failed)
+ throw "Some tests failed";
+
#include "runtime/JSStaticScopeObject.cpp"
#include "runtime/JSFunction.cpp"
#include "runtime/Arguments.cpp"
+#include "runtime/JSAPIValueWrapper.cpp"
#include "runtime/JSGlobalObjectFunctions.cpp"
#include "runtime/PrototypeFunction.cpp"
#include "runtime/GlobalEvalFunction.cpp"
#include "runtime/Collector.cpp"
#include "runtime/CommonIdentifiers.cpp"
#include "runtime/DateConstructor.cpp"
-#include "runtime/DateMath.cpp"
+#include "runtime/DateConversion.cpp"
#include "runtime/DatePrototype.cpp"
#include "runtime/DateInstance.cpp"
#include "wtf/dtoa.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 ==
chartables.c \
DatePrototype.lut.h \
Grammar.cpp \
+ JSONObject.lut.h \
Lexer.lut.h \
MathObject.lut.h \
NumberConstructor.lut.h \
javascriptcore_cppflags += \
+ -I$(srcdir)/JavaScriptCore \
-I$(srcdir)/JavaScriptCore/API \
-I$(srcdir)/JavaScriptCore/ForwardingHeaders \
-I$(srcdir)/JavaScriptCore/interpreter \
-I$(srcdir)/JavaScriptCore/jit \
-I$(srcdir)/JavaScriptCore/assembler \
-I$(srcdir)/JavaScriptCore/wtf/unicode \
+ -I$(srcdir)/JavaScriptCore/yarr \
-I$(top_builddir)/JavaScriptCore/pcre \
-I$(top_builddir)/JavaScriptCore/parser \
-I$(top_builddir)/JavaScriptCore/runtime
DerivedSources/Lexer.lut.h \
JavaScriptCore/runtime/ArrayPrototype.lut.h \
JavaScriptCore/runtime/DatePrototype.lut.h \
+ JavaScriptCore/runtime/JSONObject.lut.h \
JavaScriptCore/runtime/MathObject.lut.h \
JavaScriptCore/runtime/NumberConstructor.lut.h \
JavaScriptCore/runtime/RegExpConstructor.lut.h \
JavaScriptCore/JavaScriptCorePrefix.h \
JavaScriptCore/jit/ExecutableAllocator.h \
JavaScriptCore/jit/JIT.cpp \
+ JavaScriptCore/jit/JITOpcodes.cpp \
JavaScriptCore/jit/JITCall.cpp \
+ JavaScriptCore/jit/JITCode.h \
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/jit/JITStubs.cpp \
+ JavaScriptCore/jit/JITStubs.h \
+ JavaScriptCore/jit/JITStubCall.h \
JavaScriptCore/bytecode/StructureStubInfo.cpp \
JavaScriptCore/bytecode/StructureStubInfo.h \
JavaScriptCore/bytecode/CodeBlock.cpp \
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/icu/unicode/utypes.h \
JavaScriptCore/icu/unicode/uversion.h \
JavaScriptCore/assembler/X86Assembler.h \
+ JavaScriptCore/assembler/AbstractMacroAssembler.h \
JavaScriptCore/assembler/AssemblerBuffer.h \
JavaScriptCore/assembler/MacroAssembler.h \
+ JavaScriptCore/assembler/MacroAssemblerCodeRef.h \
+ JavaScriptCore/assembler/MacroAssemblerX86.h \
+ JavaScriptCore/assembler/MacroAssemblerX86_64.h \
+ JavaScriptCore/assembler/MacroAssemblerX86Common.h \
JavaScriptCore/os-win32/stdbool.h \
JavaScriptCore/os-win32/stdint.h \
JavaScriptCore/pcre/pcre.h \
JavaScriptCore/profiler/Profiler.h \
JavaScriptCore/profiler/TreeProfile.cpp \
JavaScriptCore/profiler/TreeProfile.h \
+ JavaScriptCore/interpreter/CachedCall.h \
JavaScriptCore/interpreter/CallFrame.cpp \
JavaScriptCore/interpreter/CallFrame.h \
+ JavaScriptCore/interpreter/CallFrameClosure.h \
+ JavaScriptCore/runtime/TimeoutChecker.cpp \
+ JavaScriptCore/runtime/TimeoutChecker.h \
JavaScriptCore/runtime/InitializeThreading.cpp \
JavaScriptCore/runtime/InitializeThreading.h \
JavaScriptCore/runtime/JSActivation.cpp \
JavaScriptCore/runtime/JSGlobalData.h \
JavaScriptCore/runtime/JSNotAnObject.cpp \
JavaScriptCore/runtime/JSNotAnObject.h \
+ JavaScriptCore/runtime/JSONObject.cpp \
+ JavaScriptCore/runtime/JSONObject.h \
JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
JavaScriptCore/runtime/JSPropertyNameIterator.h \
+ JavaScriptCore/runtime/LiteralParser.cpp \
+ JavaScriptCore/runtime/LiteralParser.h \
JavaScriptCore/runtime/SmallStrings.cpp \
JavaScriptCore/runtime/SmallStrings.h \
JavaScriptCore/runtime/Structure.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/Assertions.h \
JavaScriptCore/wtf/ByteArray.cpp \
JavaScriptCore/wtf/ByteArray.h \
+ JavaScriptCore/wtf/CrossThreadRefCounted.h \
+ JavaScriptCore/wtf/OwnFastMallocPtr.h \
JavaScriptCore/wtf/CurrentTime.cpp \
JavaScriptCore/wtf/CurrentTime.h \
+ JavaScriptCore/wtf/DateMath.cpp \
+ JavaScriptCore/wtf/DateMath.h \
JavaScriptCore/wtf/Deque.h \
JavaScriptCore/wtf/DisallowCType.h \
JavaScriptCore/wtf/Forward.h \
JavaScriptCore/wtf/NotFound.h \
JavaScriptCore/wtf/OwnArrayPtr.h \
JavaScriptCore/wtf/OwnPtr.h \
+ JavaScriptCore/wtf/OwnPtrCommon.h \
+ JavaScriptCore/wtf/PassOwnPtr.h \
JavaScriptCore/wtf/PassRefPtr.h \
JavaScriptCore/wtf/Platform.h \
JavaScriptCore/wtf/PtrAndFlags.h \
JavaScriptCore/wtf/RefPtr.h \
JavaScriptCore/wtf/RefPtrHashMap.h \
JavaScriptCore/wtf/RetainPtr.h \
+ JavaScriptCore/wtf/SegmentedVector.h \
JavaScriptCore/wtf/StdLibExtras.h \
JavaScriptCore/wtf/StringExtras.h \
JavaScriptCore/wtf/TCPackedCache.h \
JavaScriptCore/wtf/ThreadSpecific.h \
JavaScriptCore/wtf/Threading.h \
JavaScriptCore/wtf/Threading.cpp \
- JavaScriptCore/wtf/ThreadingGtk.cpp \
JavaScriptCore/wtf/ThreadingPthreads.cpp \
+ JavaScriptCore/wtf/TypeTraits.cpp \
+ JavaScriptCore/wtf/TypeTraits.h \
JavaScriptCore/wtf/UnusedParam.h \
JavaScriptCore/wtf/Vector.h \
JavaScriptCore/wtf/VectorTraits.h \
JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
+ JavaScriptCore/wtf/gtk/ThreadingGtk.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/Unicode.h
+
+if TARGET_WIN32
+javascriptcore_sources += \
+ JavaScriptCore/wtf/ThreadSpecificWin.cpp \
+ JavaScriptCore/jit/ExecutableAllocatorWin.cpp
+else
+javascriptcore_sources += \
+ JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
+endif
+
+# ----
+# icu unicode backend
+# ----
+if USE_ICU_UNICODE
+javascriptcore_sources += \
JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \
JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
+endif # USE_ICU_UNICODE
+
+# ----
+# glib unicode backend
+# ----
+if USE_GLIB_UNICODE
+javascriptcore_sources += \
+ JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h \
+ JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp \
+ JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h
+endif
+
+javascriptcore_sources += \
+ JavaScriptCore/wtf/VMTags.h \
+ JavaScriptCore/yarr/RegexCompiler.cpp \
+ JavaScriptCore/yarr/RegexCompiler.h \
+ JavaScriptCore/yarr/RegexInterpreter.cpp \
+ JavaScriptCore/yarr/RegexInterpreter.h \
+ JavaScriptCore/yarr/RegexJIT.cpp \
+ JavaScriptCore/yarr/RegexJIT.h \
+ JavaScriptCore/yarr/RegexParser.h \
+ JavaScriptCore/yarr/RegexPattern.h
# Debug build
if ENABLE_DEBUG
JavaScriptCore/debugger/Debugger.h \
JavaScriptCore/parser/Lexer.cpp \
JavaScriptCore/parser/Lexer.h \
+ JavaScriptCore/parser/NodeConstructors.h \
JavaScriptCore/parser/NodeInfo.h \
JavaScriptCore/parser/Nodes.cpp \
JavaScriptCore/parser/Nodes.h \
JavaScriptCore/parser/Parser.cpp \
JavaScriptCore/parser/Parser.h \
+ JavaScriptCore/parser/ParserArena.cpp \
+ JavaScriptCore/parser/ParserArena.h \
JavaScriptCore/parser/ResultType.h \
JavaScriptCore/parser/SourceCode.h \
JavaScriptCore/parser/SourceProvider.h \
JavaScriptCore/runtime/ConstructData.h \
JavaScriptCore/runtime/DateConstructor.cpp \
JavaScriptCore/runtime/DateConstructor.h \
+ JavaScriptCore/runtime/DateConversion.cpp \
+ JavaScriptCore/runtime/DateConversion.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/NativeErrorConstructor.h \
JavaScriptCore/runtime/NativeErrorPrototype.cpp \
JavaScriptCore/runtime/NativeErrorPrototype.h \
+ JavaScriptCore/runtime/NativeFunctionWrapper.h \
JavaScriptCore/runtime/NumberConstructor.cpp \
JavaScriptCore/runtime/NumberConstructor.h \
JavaScriptCore/runtime/NumberObject.cpp \
JavaScriptCore/runtime/Tracing.h \
JavaScriptCore/runtime/UString.cpp \
JavaScriptCore/runtime/UString.h \
+ JavaScriptCore/wtf/FastAllocBase.h \
JavaScriptCore/wtf/FastMalloc.cpp \
JavaScriptCore/wtf/FastMalloc.h \
JavaScriptCore/wtf/MallocZoneSupport.h \
DerivedSources/Grammar.h
javascriptcore_sources += \
- JavaScriptCore/AllInOneFile.cpp
+ JavaScriptCore/AllInOneFile.cpp \
+ JavaScriptCore/parser/ParserArena.cpp \
+ JavaScriptCore/parser/ParserArena.h
endif # END ENABLE_DEBUG
DerivedSources/Grammar.h: DerivedSources/Grammar.cpp;
Programs_minidom_CFLAGS = \
-ansi \
-fno-strict-aliasing \
- -O2 \
$(global_cflags) \
$(GLOBALDEPS_CFLAGS)
-lm \
-lstdc++
+Programs_minidom_LDFLAGS = \
+ -no-install \
+ -no-fast-install
+
# jsc
Programs_jsc_SOURCES = \
JavaScriptCore/jsc.cpp
Programs_jsc_CXXFLAGS = \
-fno-strict-aliasing \
- -O2 \
$(global_cxxflags) \
$(global_cflags) \
$(GLOBALDEPS_CFLAGS) \
CLEANFILES += \
JavaScriptCore/runtime/ArrayPrototype.lut.h \
JavaScriptCore/runtime/DatePrototype.lut.h \
+ JavaScriptCore/runtime/JSONObject.lut.h \
JavaScriptCore/runtime/MathObject.lut.h \
JavaScriptCore/runtime/NumberConstructor.lut.h \
JavaScriptCore/runtime/RegExpConstructor.lut.h \
__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
__ZN3JSC10JSFunction4infoE
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
-__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
-__ZN3JSC11JSImmediate12nonInlineNaNEv
-__ZN3JSC11JSImmediate8toObjectENS_10JSValuePtrEPNS_9ExecStateE
-__ZN3JSC11JSImmediate8toStringENS_10JSValuePtrE
-__ZN3JSC11JSImmediate9prototypeENS_10JSValuePtrEPNS_9ExecStateE
-__ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E
+__ZN3JSC11ParserArena5resetEv
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
__ZN3JSC12DateInstance4infoE
__ZN3JSC12JSGlobalData10ClientDataD2Ev
__ZN3JSC12JSGlobalData12createLeakedEv
__ZN3JSC12JSGlobalData14sharedInstanceEv
-__ZN3JSC12JSGlobalData6createEv
+__ZN3JSC12JSGlobalData6createEb
__ZN3JSC12JSGlobalDataD1Ev
-__ZN3JSC12SamplingTool13notifyOfScopeEPNS_9ScopeNodeE
__ZN3JSC12SamplingTool4dumpEPNS_9ExecStateE
-__ZN3JSC12SamplingTool4stopEv
-__ZN3JSC12SamplingTool5startEj
+__ZN3JSC12SamplingTool5setupEv
__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC12StringObject4infoE
__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE
__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSC12nonInlineNaNEv
+__ZN3JSC13SamplingFlags4stopEv
+__ZN3JSC13SamplingFlags5startEv
+__ZN3JSC13SamplingFlags7s_flagsE
__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
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
__ZN3JSC14JSGlobalObject4markEv
__ZN3JSC14JSGlobalObjectD2Ev
__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14SamplingThread4stopEv
+__ZN3JSC14SamplingThread5startEj
+__ZN3JSC14TimeoutChecker5resetEv
__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
__ZN3JSC15JSWrapperObject4markEv
__ZN3JSC15toInt32SlowCaseEdRb
__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
__ZN3JSC16FunctionBodyNode14copyParametersEv
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IPNS_12FuncDeclNodeELm0EEERKNS_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
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
__ZN3JSC19initializeThreadingEv
+__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC23AbstractSamplingCounter4dumpEv
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_10JSValuePtrEPNS_14JSGlobalObjectE
+__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
__ZN3JSC4Heap11objectCountEv
-__ZN3JSC4Heap14allocateNumberEm
__ZN3JSC4Heap14primaryHeapEndEv
__ZN3JSC4Heap15recordExtraCostEm
__ZN3JSC4Heap16primaryHeapBeginEv
__ZN3JSC4Heap24setGCProtectNeedsLockingEv
__ZN3JSC4Heap25protectedObjectTypeCountsEv
__ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZN3JSC4Heap4heapENS_10JSValuePtrE
+__ZN3JSC4Heap4heapENS_7JSValueE
__ZN3JSC4Heap6isBusyEv
__ZN3JSC4Heap7collectEv
__ZN3JSC4Heap7destroyEv
-__ZN3JSC4Heap7protectENS_10JSValuePtrE
+__ZN3JSC4Heap7protectENS_7JSValueE
__ZN3JSC4Heap8allocateEm
-__ZN3JSC4Heap9unprotectENS_10JSValuePtrE
-__ZN3JSC4callEPNS_9ExecStateENS_10JSValuePtrENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC4Heap9unprotectENS_7JSValueE
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
__ZN3JSC5equalEPKNS_7UString3RepES3_
__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
__ZN3JSC6JSCell11getJSNumberEv
__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
-__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE
__ZN3JSC6JSCell9getObjectEv
__ZN3JSC6JSCellnwEmPNS_9ExecStateE
__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
__ZN3JSC6JSLock9lockCountEv
__ZN3JSC6JSLockC1EPNS_9ExecStateE
__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
-__ZN3JSC7ArgList10slowAppendENS_10JSValuePtrE
__ZN3JSC7CStringD1Ev
__ZN3JSC7CStringaSERKS0_
__ZN3JSC7JSArray4infoE
__ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
__ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
+__ZN3JSC7UString3Rep11computeHashEPKci
__ZN3JSC7UString3Rep11computeHashEPKti
+__ZN3JSC7UString3Rep12sharedBufferEv
+__ZN3JSC7UString3Rep14createFromUTF8EPKc
__ZN3JSC7UString3Rep14nullBaseStringE
+__ZN3JSC7UString3Rep6createEPtiN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrItEEEEEE
__ZN3JSC7UString3Rep7destroyEv
+__ZN3JSC7UString4fromEd
__ZN3JSC7UString4fromEi
__ZN3JSC7UString4fromEj
+__ZN3JSC7UString4fromEl
__ZN3JSC7UString6appendEPKc
__ZN3JSC7UString6appendERKS0_
__ZN3JSC7UStringC1EPKc
__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
__ZN3JSC8DebuggerC2Ev
__ZN3JSC8DebuggerD2Ev
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_10JSValuePtrES3_
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3JSC8JSObject17createInheritorIDEv
__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_10JSValuePtrEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_10JSValuePtrE
-__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_10JSValuePtrE
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE
__ZN3JSC8JSObject23allocatePropertyStorageEmm
-__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
__ZN3JSC8JSObject4markEv
__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC8Profiler8profilerEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
__ZN3JSC9CodeBlockD1Ev
__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC9Structure13hasTransitionEPNS_7UString3RepEj
__ZN3JSC9Structure17stopIgnoringLeaksEv
__ZN3JSC9Structure18startIgnoringLeaksEv
-__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
__ZN3JSC9Structure22materializePropertyMapEv
-__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE
-__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj
-__ZN3JSC9Structure3getERKNS_10IdentifierERj
-__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm
-__ZN3JSC9StructureC1ENS_10JSValuePtrERKNS_8TypeInfoE
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
+__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
+__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
+__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC9Structure3getEPKNS_7UString3RepERjRPNS_6JSCellE
+__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
+__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoE
__ZN3JSC9StructureD1Ev
-__ZN3JSC9constructEPNS_9ExecStateENS_10JSValuePtrENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
__ZN3JSCeqERKNS_7UStringEPKc
-__ZN3JSCeqERKNS_7UStringES2_
__ZN3JSCgtERKNS_7UStringES2_
__ZN3JSCltERKNS_7UStringES2_
__ZN3WTF10fastCallocEmm
__ZN3WTF15ThreadCondition4waitERNS_5MutexE
__ZN3WTF15ThreadCondition6signalEv
__ZN3WTF15ThreadCondition9broadcastEv
+__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
__ZN3WTF15ThreadConditionC1Ev
__ZN3WTF15ThreadConditionD1Ev
__ZN3WTF16callOnMainThreadEPFvPvES0_
__ZN3WTF27releaseFastMallocFreeMemoryEv
__ZN3WTF28setMainThreadCallbacksPausedEb
__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
__ZN3WTF5Mutex4lockEv
__ZN3WTF5Mutex6unlockEv
__ZN3WTF8CollatorD1Ev
__ZN3WTF8fastFreeEPv
__ZN3WTF9ByteArray6createEm
-__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE
__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
__ZNK3JSC12DateInstance7getTimeERdRi
__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZNK3JSC16FunctionBodyNode14isHostFunctionEv
__ZNK3JSC16InternalFunction9classInfoEv
__ZNK3JSC16JSVariableObject16isVariableObjectEv
__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
__ZNK3JSC17DebuggerCallFrame10thisObjectEv
__ZNK3JSC17DebuggerCallFrame12functionNameEv
+__ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
__ZNK3JSC17DebuggerCallFrame4typeEv
-__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_10JSValuePtrE
+__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
__ZNK3JSC4Heap10statisticsEv
__ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
__ZNK3JSC6JSCell14isGetterSetterEv
-__ZNK3JSC6JSCell17getTruncatedInt32ERi
-__ZNK3JSC6JSCell18getTruncatedUInt32ERj
__ZNK3JSC6JSCell9classInfoEv
__ZNK3JSC6JSCell9getStringERNS_7UStringE
__ZNK3JSC6JSCell9getStringEv
__ZNK3JSC6JSCell9getUInt32ERj
__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
+__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
+__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
+__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
__ZNK3JSC7UString10UTF8StringEb
__ZNK3JSC7UString14toStrictUInt32EPb
__ZNK3JSC7UString5asciiEv
__ZTVN3JSC15JSWrapperObjectE
__ZTVN3JSC16InternalFunctionE
__ZTVN3JSC16JSVariableObjectE
+__ZTVN3JSC17JSAPIValueWrapperE
__ZTVN3JSC8JSObjectE
__ZTVN3JSC8JSStringE
_jscore_fastmalloc_introspection
--- /dev/null
+{
+ 'variables': {
+ 'javascriptcore_files': [
+ 'AllInOneFile.cpp',
+ 'API/APICast.h',
+ 'API/JavaScript.h',
+ 'API/JavaScriptCore.h',
+ 'API/JSBase.cpp',
+ 'API/JSBase.h',
+ 'API/JSBasePrivate.h',
+ 'API/JSCallbackConstructor.cpp',
+ 'API/JSCallbackConstructor.h',
+ 'API/JSCallbackFunction.cpp',
+ 'API/JSCallbackFunction.h',
+ 'API/JSCallbackObject.cpp',
+ 'API/JSCallbackObject.h',
+ 'API/JSCallbackObjectFunctions.h',
+ 'API/JSClassRef.cpp',
+ 'API/JSClassRef.h',
+ 'API/JSContextRef.cpp',
+ 'API/JSContextRef.h',
+ 'API/JSObjectRef.cpp',
+ 'API/JSObjectRef.h',
+ 'API/JSProfilerPrivate.cpp',
+ 'API/JSProfilerPrivate.h',
+ 'API/JSRetainPtr.h',
+ 'API/JSStringRef.cpp',
+ 'API/JSStringRef.h',
+ 'API/JSStringRefBSTR.cpp',
+ 'API/JSStringRefBSTR.h',
+ 'API/JSStringRefCF.cpp',
+ 'API/JSStringRefCF.h',
+ 'API/JSValueRef.cpp',
+ 'API/JSValueRef.h',
+ 'API/OpaqueJSString.cpp',
+ 'API/OpaqueJSString.h',
+ 'API/tests/JSNode.h',
+ 'API/tests/JSNodeList.h',
+ 'API/tests/Node.h',
+ 'API/tests/NodeList.h',
+ 'API/WebKitAvailability.h',
+ 'assembler/AbstractMacroAssembler.h',
+ 'assembler/ARMv7Assembler.h',
+ 'assembler/AssemblerBuffer.h',
+ 'assembler/CodeLocation.h',
+ 'assembler/MacroAssembler.h',
+ 'assembler/MacroAssemblerARMv7.h',
+ 'assembler/MacroAssemblerCodeRef.h',
+ 'assembler/MacroAssemblerX86.h',
+ 'assembler/MacroAssemblerX86_64.h',
+ 'assembler/MacroAssemblerX86Common.h',
+ 'assembler/X86Assembler.h',
+ 'bytecode/CodeBlock.cpp',
+ 'bytecode/CodeBlock.h',
+ 'bytecode/EvalCodeCache.h',
+ 'bytecode/Instruction.h',
+ 'bytecode/JumpTable.cpp',
+ 'bytecode/JumpTable.h',
+ 'bytecode/Opcode.cpp',
+ 'bytecode/Opcode.h',
+ 'bytecode/SamplingTool.cpp',
+ 'bytecode/SamplingTool.h',
+ 'bytecode/StructureStubInfo.cpp',
+ 'bytecode/StructureStubInfo.h',
+ 'bytecompiler/BytecodeGenerator.cpp',
+ 'bytecompiler/BytecodeGenerator.h',
+ 'bytecompiler/Label.h',
+ 'bytecompiler/LabelScope.h',
+ 'bytecompiler/RegisterID.h',
+ 'config.h',
+ 'debugger/Debugger.cpp',
+ 'debugger/Debugger.h',
+ 'debugger/DebuggerActivation.cpp',
+ 'debugger/DebuggerActivation.h',
+ 'debugger/DebuggerCallFrame.cpp',
+ 'debugger/DebuggerCallFrame.h',
+ 'icu/unicode/parseerr.h',
+ 'icu/unicode/platform.h',
+ 'icu/unicode/putil.h',
+ 'icu/unicode/uchar.h',
+ 'icu/unicode/ucnv.h',
+ 'icu/unicode/ucnv_err.h',
+ 'icu/unicode/ucol.h',
+ 'icu/unicode/uconfig.h',
+ 'icu/unicode/uenum.h',
+ 'icu/unicode/uiter.h',
+ 'icu/unicode/uloc.h',
+ 'icu/unicode/umachine.h',
+ 'icu/unicode/unorm.h',
+ 'icu/unicode/urename.h',
+ 'icu/unicode/uset.h',
+ 'icu/unicode/ustring.h',
+ 'icu/unicode/utf.h',
+ 'icu/unicode/utf16.h',
+ 'icu/unicode/utf8.h',
+ 'icu/unicode/utf_old.h',
+ 'icu/unicode/utypes.h',
+ 'icu/unicode/uversion.h',
+ 'interpreter/CachedCall.h',
+ 'interpreter/CallFrame.cpp',
+ 'interpreter/CallFrame.h',
+ 'interpreter/CallFrameClosure.h',
+ 'interpreter/Interpreter.cpp',
+ 'interpreter/Interpreter.h',
+ 'interpreter/Register.h',
+ 'interpreter/RegisterFile.cpp',
+ 'interpreter/RegisterFile.h',
+ 'JavaScriptCorePrefix.h',
+ 'jit/ExecutableAllocator.cpp',
+ 'jit/ExecutableAllocator.h',
+ 'jit/ExecutableAllocatorFixedVMPool.cpp',
+ 'jit/ExecutableAllocatorPosix.cpp',
+ 'jit/ExecutableAllocatorWin.cpp',
+ 'jit/JIT.cpp',
+ 'jit/JIT.h',
+ 'jit/JITArithmetic.cpp',
+ 'jit/JITCall.cpp',
+ 'jit/JITCode.h',
+ 'jit/JITInlineMethods.h',
+ 'jit/JITOpcodes.cpp',
+ 'jit/JITPropertyAccess.cpp',
+ 'jit/JITStubCall.h',
+ 'jit/JITStubs.cpp',
+ 'jit/JITStubs.h',
+ 'jsc.cpp',
+ 'os-win32/stdbool.h',
+ 'os-win32/stdint.h',
+ 'parser/Lexer.cpp',
+ 'parser/Lexer.h',
+ 'parser/NodeConstructors.h',
+ 'parser/NodeInfo.h',
+ 'parser/Nodes.cpp',
+ 'parser/Nodes.h',
+ 'parser/Parser.cpp',
+ 'parser/Parser.h',
+ 'parser/ParserArena.cpp',
+ 'parser/ParserArena.h',
+ 'parser/ResultType.h',
+ 'parser/SourceCode.h',
+ 'parser/SourceProvider.h',
+ 'pcre/pcre.h',
+ 'pcre/pcre_compile.cpp',
+ 'pcre/pcre_exec.cpp',
+ 'pcre/pcre_internal.h',
+ 'pcre/pcre_tables.cpp',
+ 'pcre/pcre_ucp_searchfuncs.cpp',
+ 'pcre/pcre_xclass.cpp',
+ 'pcre/ucpinternal.h',
+ 'pcre/ucptable.cpp',
+ 'profiler/CallIdentifier.h',
+ 'profiler/HeavyProfile.cpp',
+ 'profiler/HeavyProfile.h',
+ 'profiler/Profile.cpp',
+ 'profiler/Profile.h',
+ 'profiler/ProfileGenerator.cpp',
+ 'profiler/ProfileGenerator.h',
+ 'profiler/ProfileNode.cpp',
+ 'profiler/ProfileNode.h',
+ 'profiler/Profiler.cpp',
+ 'profiler/Profiler.h',
+ 'profiler/ProfilerServer.h',
+ 'profiler/TreeProfile.cpp',
+ 'profiler/TreeProfile.h',
+ 'runtime/ArgList.cpp',
+ 'runtime/ArgList.h',
+ 'runtime/Arguments.cpp',
+ 'runtime/Arguments.h',
+ 'runtime/ArrayConstructor.cpp',
+ 'runtime/ArrayConstructor.h',
+ 'runtime/ArrayPrototype.cpp',
+ 'runtime/ArrayPrototype.h',
+ 'runtime/BatchedTransitionOptimizer.h',
+ 'runtime/BooleanConstructor.cpp',
+ 'runtime/BooleanConstructor.h',
+ 'runtime/BooleanObject.cpp',
+ 'runtime/BooleanObject.h',
+ 'runtime/BooleanPrototype.cpp',
+ 'runtime/BooleanPrototype.h',
+ 'runtime/CallData.cpp',
+ 'runtime/CallData.h',
+ 'runtime/ClassInfo.h',
+ 'runtime/Collector.cpp',
+ 'runtime/Collector.h',
+ 'runtime/CollectorHeapIterator.h',
+ 'runtime/CommonIdentifiers.cpp',
+ 'runtime/CommonIdentifiers.h',
+ 'runtime/Completion.cpp',
+ 'runtime/Completion.h',
+ 'runtime/ConstructData.cpp',
+ 'runtime/ConstructData.h',
+ 'runtime/DateConstructor.cpp',
+ 'runtime/DateConstructor.h',
+ 'runtime/DateConversion.cpp',
+ 'runtime/DateConversion.h',
+ 'runtime/DateInstance.cpp',
+ 'runtime/DateInstance.h',
+ 'runtime/DatePrototype.cpp',
+ 'runtime/DatePrototype.h',
+ 'runtime/Error.cpp',
+ 'runtime/Error.h',
+ 'runtime/ErrorConstructor.cpp',
+ 'runtime/ErrorConstructor.h',
+ 'runtime/ErrorInstance.cpp',
+ 'runtime/ErrorInstance.h',
+ 'runtime/ErrorPrototype.cpp',
+ 'runtime/ErrorPrototype.h',
+ 'runtime/ExceptionHelpers.cpp',
+ 'runtime/ExceptionHelpers.h',
+ 'runtime/FunctionConstructor.cpp',
+ 'runtime/FunctionConstructor.h',
+ 'runtime/FunctionPrototype.cpp',
+ 'runtime/FunctionPrototype.h',
+ 'runtime/GetterSetter.cpp',
+ 'runtime/GetterSetter.h',
+ 'runtime/GlobalEvalFunction.cpp',
+ 'runtime/GlobalEvalFunction.h',
+ 'runtime/Identifier.cpp',
+ 'runtime/Identifier.h',
+ 'runtime/InitializeThreading.cpp',
+ 'runtime/InitializeThreading.h',
+ 'runtime/InternalFunction.cpp',
+ 'runtime/InternalFunction.h',
+ 'runtime/JSActivation.cpp',
+ 'runtime/JSActivation.h',
+ 'runtime/JSArray.cpp',
+ 'runtime/JSArray.h',
+ 'runtime/JSByteArray.cpp',
+ 'runtime/JSByteArray.h',
+ 'runtime/JSCell.cpp',
+ 'runtime/JSCell.h',
+ 'runtime/JSFunction.cpp',
+ 'runtime/JSFunction.h',
+ 'runtime/JSGlobalData.cpp',
+ 'runtime/JSGlobalData.h',
+ 'runtime/JSGlobalObject.cpp',
+ 'runtime/JSGlobalObject.h',
+ 'runtime/JSGlobalObjectFunctions.cpp',
+ 'runtime/JSGlobalObjectFunctions.h',
+ 'runtime/JSImmediate.cpp',
+ 'runtime/JSImmediate.h',
+ 'runtime/JSLock.cpp',
+ 'runtime/JSLock.h',
+ 'runtime/JSNotAnObject.cpp',
+ 'runtime/JSNotAnObject.h',
+ 'runtime/JSNumberCell.cpp',
+ 'runtime/JSNumberCell.h',
+ 'runtime/JSObject.cpp',
+ 'runtime/JSObject.h',
+ 'runtime/JSONObject.cpp',
+ 'runtime/JSONObject.h',
+ 'runtime/JSPropertyNameIterator.cpp',
+ 'runtime/JSPropertyNameIterator.h',
+ 'runtime/JSStaticScopeObject.cpp',
+ 'runtime/JSStaticScopeObject.h',
+ 'runtime/JSString.cpp',
+ 'runtime/JSString.h',
+ 'runtime/JSType.h',
+ 'runtime/JSValue.cpp',
+ 'runtime/JSValue.h',
+ 'runtime/JSVariableObject.cpp',
+ 'runtime/JSVariableObject.h',
+ 'runtime/JSWrapperObject.cpp',
+ 'runtime/JSWrapperObject.h',
+ 'runtime/LiteralParser.cpp',
+ 'runtime/LiteralParser.h',
+ 'runtime/Lookup.cpp',
+ 'runtime/Lookup.h',
+ 'runtime/MathObject.cpp',
+ 'runtime/MathObject.h',
+ 'runtime/NativeErrorConstructor.cpp',
+ 'runtime/NativeErrorConstructor.h',
+ 'runtime/NativeErrorPrototype.cpp',
+ 'runtime/NativeErrorPrototype.h',
+ 'runtime/NativeFunctionWrapper.h',
+ 'runtime/NumberConstructor.cpp',
+ 'runtime/NumberConstructor.h',
+ 'runtime/NumberObject.cpp',
+ 'runtime/NumberObject.h',
+ 'runtime/NumberPrototype.cpp',
+ 'runtime/NumberPrototype.h',
+ 'runtime/ObjectConstructor.cpp',
+ 'runtime/ObjectConstructor.h',
+ 'runtime/ObjectPrototype.cpp',
+ 'runtime/ObjectPrototype.h',
+ 'runtime/Operations.cpp',
+ 'runtime/Operations.h',
+ 'runtime/PropertyMapHashTable.h',
+ 'runtime/PropertyNameArray.cpp',
+ 'runtime/PropertyNameArray.h',
+ 'runtime/PropertySlot.cpp',
+ 'runtime/PropertySlot.h',
+ 'runtime/Protect.h',
+ 'runtime/PrototypeFunction.cpp',
+ 'runtime/PrototypeFunction.h',
+ 'runtime/PutPropertySlot.h',
+ 'runtime/RegExp.cpp',
+ 'runtime/RegExp.h',
+ 'runtime/RegExpConstructor.cpp',
+ 'runtime/RegExpConstructor.h',
+ 'runtime/RegExpMatchesArray.h',
+ 'runtime/RegExpObject.cpp',
+ 'runtime/RegExpObject.h',
+ 'runtime/RegExpPrototype.cpp',
+ 'runtime/RegExpPrototype.h',
+ 'runtime/ScopeChain.cpp',
+ 'runtime/ScopeChain.h',
+ 'runtime/ScopeChainMark.h',
+ 'runtime/SmallStrings.cpp',
+ 'runtime/SmallStrings.h',
+ 'runtime/StringConstructor.cpp',
+ 'runtime/StringConstructor.h',
+ 'runtime/StringObject.cpp',
+ 'runtime/StringObject.h',
+ 'runtime/StringObjectThatMasqueradesAsUndefined.h',
+ 'runtime/StringPrototype.cpp',
+ 'runtime/StringPrototype.h',
+ 'runtime/Structure.cpp',
+ 'runtime/Structure.h',
+ 'runtime/StructureChain.cpp',
+ 'runtime/StructureChain.h',
+ 'runtime/StructureTransitionTable.h',
+ 'runtime/SymbolTable.h',
+ 'runtime/TimeoutChecker.cpp',
+ 'runtime/TimeoutChecker.h',
+ 'runtime/Tracing.h',
+ 'runtime/TypeInfo.h',
+ 'runtime/UString.cpp',
+ 'runtime/UString.h',
+ 'wrec/CharacterClass.cpp',
+ 'wrec/CharacterClass.h',
+ 'wrec/CharacterClassConstructor.cpp',
+ 'wrec/CharacterClassConstructor.h',
+ 'wrec/Escapes.h',
+ 'wrec/Quantifier.h',
+ 'wrec/WREC.cpp',
+ 'wrec/WREC.h',
+ 'wrec/WRECFunctors.cpp',
+ 'wrec/WRECFunctors.h',
+ 'wrec/WRECGenerator.cpp',
+ 'wrec/WRECGenerator.h',
+ 'wrec/WRECParser.cpp',
+ 'wrec/WRECParser.h',
+ 'wtf/AlwaysInline.h',
+ 'wtf/ASCIICType.h',
+ 'wtf/Assertions.cpp',
+ 'wtf/Assertions.h',
+ 'wtf/AVLTree.h',
+ 'wtf/ByteArray.cpp',
+ 'wtf/ByteArray.h',
+ 'wtf/chromium/ChromiumThreading.h',
+ 'wtf/chromium/MainThreadChromium.cpp',
+ 'wtf/CrossThreadRefCounted.h',
+ 'wtf/CurrentTime.cpp',
+ 'wtf/CurrentTime.h',
+ 'wtf/DateMath.cpp',
+ 'wtf/DateMath.h',
+ 'wtf/Deque.h',
+ 'wtf/DisallowCType.h',
+ 'wtf/dtoa.cpp',
+ 'wtf/dtoa.h',
+ 'wtf/FastAllocBase.h',
+ 'wtf/FastMalloc.cpp',
+ 'wtf/FastMalloc.h',
+ 'wtf/Forward.h',
+ 'wtf/GetPtr.h',
+ 'wtf/GOwnPtr.cpp',
+ 'wtf/GOwnPtr.h',
+ 'wtf/gtk/MainThreadGtk.cpp',
+ 'wtf/gtk/ThreadingGtk.cpp',
+ 'wtf/HashCountedSet.h',
+ 'wtf/HashFunctions.h',
+ 'wtf/HashIterators.h',
+ 'wtf/HashMap.h',
+ 'wtf/HashSet.h',
+ 'wtf/HashTable.cpp',
+ 'wtf/HashTable.h',
+ 'wtf/HashTraits.h',
+ 'wtf/ListHashSet.h',
+ 'wtf/ListRefPtr.h',
+ 'wtf/Locker.h',
+ 'wtf/MainThread.cpp',
+ 'wtf/MainThread.h',
+ 'wtf/MallocZoneSupport.h',
+ 'wtf/MathExtras.h',
+ 'wtf/MessageQueue.h',
+ 'wtf/Noncopyable.h',
+ 'wtf/NotFound.h',
+ 'wtf/OwnArrayPtr.h',
+ 'wtf/OwnFastMallocPtr.h',
+ 'wtf/OwnPtr.h',
+ 'wtf/OwnPtrCommon.h',
+ 'wtf/OwnPtrWin.cpp',
+ 'wtf/PassOwnPtr.h',
+ 'wtf/PassRefPtr.h',
+ 'wtf/Platform.h',
+ 'wtf/PtrAndFlags.h',
+ 'wtf/qt/MainThreadQt.cpp',
+ 'wtf/qt/ThreadingQt.cpp',
+ 'wtf/RandomNumber.cpp',
+ 'wtf/RandomNumber.h',
+ 'wtf/RandomNumberSeed.h',
+ 'wtf/RefCounted.h',
+ 'wtf/RefCountedLeakCounter.cpp',
+ 'wtf/RefCountedLeakCounter.h',
+ 'wtf/RefPtr.h',
+ 'wtf/RefPtrHashMap.h',
+ 'wtf/RetainPtr.h',
+ 'wtf/SegmentedVector.h',
+ 'wtf/StdLibExtras.h',
+ 'wtf/StringExtras.h',
+ 'wtf/TCPackedCache.h',
+ 'wtf/TCPageMap.h',
+ 'wtf/TCSpinLock.h',
+ 'wtf/TCSystemAlloc.cpp',
+ 'wtf/TCSystemAlloc.h',
+ 'wtf/Threading.cpp',
+ 'wtf/Threading.h',
+ 'wtf/ThreadingNone.cpp',
+ 'wtf/ThreadingPthreads.cpp',
+ 'wtf/ThreadingWin.cpp',
+ 'wtf/ThreadSpecific.h',
+ 'wtf/ThreadSpecificWin.cpp',
+ 'wtf/TypeTraits.cpp',
+ 'wtf/TypeTraits.h',
+ 'wtf/unicode/Collator.h',
+ 'wtf/unicode/CollatorDefault.cpp',
+ 'wtf/unicode/glib/UnicodeGLib.cpp',
+ 'wtf/unicode/glib/UnicodeGLib.h',
+ 'wtf/unicode/glib/UnicodeMacrosFromICU.h',
+ 'wtf/unicode/icu/CollatorICU.cpp',
+ 'wtf/unicode/icu/UnicodeIcu.h',
+ 'wtf/unicode/qt4/UnicodeQt4.h',
+ 'wtf/unicode/Unicode.h',
+ 'wtf/unicode/UTF8.cpp',
+ 'wtf/unicode/UTF8.h',
+ 'wtf/UnusedParam.h',
+ 'wtf/Vector.h',
+ 'wtf/VectorTraits.h',
+ 'wtf/VMTags.h',
+ 'wtf/win/MainThreadWin.cpp',
+ 'wtf/wx/MainThreadWx.cpp',
+ 'yarr/RegexCompiler.cpp',
+ 'yarr/RegexCompiler.h',
+ 'yarr/RegexInterpreter.cpp',
+ 'yarr/RegexInterpreter.h',
+ 'yarr/RegexJIT.cpp',
+ 'yarr/RegexJIT.h',
+ 'yarr/RegexParser.h',
+ 'yarr/RegexPattern.h',
+ ]
+ }
+}
-__ZN3JSC19initializeThreadingEv
-dyld_stub_binding_helper
-__ZN3JSCL23initializeThreadingOnceEv
-__ZN3WTF19initializeThreadingEv
+// JavaScriptCore order file generated on Fri Feb 19 17:16:12 -0800 2010 by Andrew Turley (aturley@apple.com)
+// Scenario included SpringBoard launch/unlock with passcode, launching all apps, MobileSafari page loads,
+// keyboard usage and general app interaction.
__ZN3WTF10fastMallocEm
__ZN3WTF10fastMallocILb1EEEPvm
__ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
+ stub helpers
__ZN3WTFL15InitSizeClassesEv
__Z20TCMalloc_SystemAllocmPmm
__ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
__ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
__ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
__ZN3WTFL13MetaDataAllocEm
-__Z22TCMalloc_SystemReleasePvm
+__ZN3WTF17TCMalloc_PageHeap6DeleteEPNS_4SpanE
+__ZN3WTF16fastZeroedMallocEm
+__ZN3WTF8fastFreeEPv
+__ZN3WTF12isMainThreadEv
__ZN3WTFL25identifierByPthreadHandleERKP17_opaque_pthread_t
__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t
__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
-__ZN3WTF16fastZeroedMallocEm
-__ZN3WTF8fastFreeEPv
-__ZN3WTF22initializeMainNSThreadEv
+__ZN3JSC19initializeThreadingEv
+__ZN3JSCL23initializeThreadingOnceEv
+__ZN3WTF19initializeThreadingEv
__ZN3WTF20initializeMainThreadEv
__ZN3WTF5MutexC1Ev
+__ZN3WTF28initializeMainThreadPlatformEv
__ZN3JSC17initializeUStringEv
-__ZN3JSC12initDateMathEv
+__ZN3WTF15initializeDatesEv
__ZN3WTF11currentTimeEv
__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
-__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
-__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
-__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
__ZN3JSC8DebuggerC2Ev
__ZN3JSC6JSLock12DropAllLocksC1Eb
__ZN3JSCL17createJSLockCountEv
__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
+__ZN3WTF5MutexD1Ev
__ZN3WTF15ThreadConditionC1Ev
__ZN3WTF12createThreadEPFPvS0_ES0_PKc
__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
-__ZN3WTF15ThreadCondition4waitERNS_5MutexE
__ZN3WTFL16threadEntryPointEPv
-__ZN3WTF5MutexD1Ev
+__ZN3WTF21setThreadNameInternalEPKc
__ZN3WTF13currentThreadEv
__ZN3WTF15ThreadCondition9broadcastEv
__ZN3WTF15ThreadCondition6signalEv
__ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF6VectorINS_19FunctionWithContextELm0EE14expandCapacityEm
+__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
-__ZN3WTF12mainNSThreadEv
-[WTFMainThreadCaller call]
__ZN3WTF31dispatchFunctionsFromMainThreadEv
__ZN3WTF11fastReallocEPvm
__ZN3WTF11fastReallocILb1EEEPvS1_m
+__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
+__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
+__ZL11checkEscapePPKtS0_P9ErrorCodeib
+__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
+__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZL5matchPKtPKhiR9MatchData
__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
+__ZN3JSC9Structure18startIgnoringLeaksEv
+__ZN3JSC7VPtrSetC2Ev
+__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoE
__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE
__ZN3JSC7JSArrayD1Ev
__ZN3JSC7JSArrayD2Ev
__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
__ZN3JSC9StructureD1Ev
__ZN3JSC9StructureD2Ev
-__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
__ZN3JSC11JSByteArrayD1Ev
__ZN3JSC8JSStringD1Ev
-__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev
__ZN3JSC10JSFunctionD1Ev
-__ZN3JSC8JSObjectD2Ev
+__ZN3JSC12JSGlobalDataC2EbRKNS_7VPtrSetE
__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
+__ZN3JSC11InterpreterC1Ev
+__ZN3JSC11InterpreterC2Ev
+__ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_7JSValueE
+__ZN3WTF9HashTableIPKvSt4pairIS2_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN3JSC14TimeoutCheckerC1Ev
__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
__ZN3JSC27startProfilerServerIfNeededEv
+[ProfilerServer sharedProfileServer]
-[ProfilerServer init]
-__ZN3JSC11Interpreter10initializeEPNS_12JSGlobalDataE
+__ZN3JSC9Structure17stopIgnoringLeaksEv
__ZN3JSC4Heap8allocateEm
__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv
+__ZN3JSC4Heap4heapENS_7JSValueE
+__ZN3JSC4Heap7protectENS_7JSValueE
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject5resetENS_10JSValuePtrE
+__ZN3JSC14JSGlobalObject5resetENS_7JSValueE
__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
+__ZN3JSC8JSObject17putDirectInternalERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotEPNS_6JSCellE
+__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
+__ZN3JSC9Structure3getEPKNS_7UString3RepERjRPNS_6JSCellE
+__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
+__ZN3JSC9Structure3putERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureEPPNS_17PrototypeFunctionES7_
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_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
__ZNK3JSC13ErrorInstance9classInfoEv
__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
__ZN3JSC12SmallStrings24singleCharacterStringRepEh
+__ZN3JSC7JSValueC1EPNS_9ExecStateEd
__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEE3addEPS4_RKS6_
__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E6expandEv
-__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_10JSValuePtrE
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
__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
+__ZN3JSC4Heap9unprotectENS_7JSValueE
__ZN3JSC6JSCellnwEmPNS_9ExecStateE
__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
-__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
-__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
-__ZN3JSC11Interpreter17resetTimeoutCheckEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC7UString3Rep12sharedBufferEv
+__ZN3JSC14TimeoutChecker5resetEv
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
__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
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
+__ZN3JSC5Lexer10sourceCodeEiii
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
+__ZN3JSC20ParserArenaDeletablenwEmPNS_12JSGlobalDataE
+__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE14expandCapacityEm
+__ZN3WTF6VectorIPN3JSC12FuncDeclNodeELm0EE14expandCapacityEm
+__ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
__ZNK3JSC13StatementNode16isEmptyStatementEv
-__Z21mergeDeclarationListsIPN3JSC20ParserRefCountedDataIN3WTF6VectorINS2_6RefPtrINS0_12FuncDeclNodeEEELm0EEEEEET_SA_SA_
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3JSC5Lexer10scanRegExpEv
+__ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
+__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE
__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
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14shrinkCapacityEm
+__ZN3JSC5Lexer7record8Ei
+__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii
+__ZN3JSC7UString3Rep7destroyEv
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZL26appendToVarDeclarationListPvRPN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEm
+__ZNK3JSC14ExpressionNode10isLocationEv
__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
+__ZN3JSC10Identifier6removeEPNS_7UString3RepE
+__ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS9_IPNS_12FuncDeclNodeELm0EEEji
+__ZN3JSC11ParserArena10removeLastEv
+__ZN3JSC11ParserArena5resetEv
__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
-__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_10JSValuePtrE
+__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_7JSValueE
__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_
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm
+__ZN3JSC9Structure31toCacheableDictionaryTransitionEPS0_
+__ZN3JSC9Structure22toDictionaryTransitionEPS0_NS0_14DictionaryKindE
+__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
+__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
+__ZN3JSC9Structure6removeERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE14expandCapacityEm
+__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
+__ZNK3JSC7UString14toStrictUInt32EPb
+__ZN3JSC9Structure26flattenDictionaryStructureEPNS_8JSObjectE
+__ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
__ZN3JSC17BytecodeGenerator8generateEv
__ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
-__ZN3JSC17BytecodeGenerator11addConstantENS_10JSValuePtrE
-__ZN3WTF7HashMapIPN3JSC23JSValueEncodedAsPointerEjNS_7PtrHashIS3_EENS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEE3addERKS3_RKj
-__ZN3WTF9HashTableIPN3JSC23JSValueEncodedAsPointerESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEEESC_E6rehashEi
+__ZN3JSC17BytecodeGenerator12newTemporaryEv
+__ZN3JSC17BytecodeGenerator11newRegisterEv
+__ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
+__ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEESA_E6expandEv
__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
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8newLabelEv
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
__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
+__ZN3WTF6VectorIjLm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESD_E6rehashEi
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3WTF6VectorIN3JSC11InstructionELm0EE6appendIiEEvRKT_
__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
+__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
+__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE
+__ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE
+__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS7_EEEESE_E6expandEv
__ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
__ZNK3JSC21UStringSourceProvider6lengthEv
__ZNK3JSC21UStringSourceProvider4dataEv
-__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
__ZN3JSC19extractFunctionBodyEPNS_11ProgramNodeE
__ZNK3JSC17ExprStatementNode15isExprStatementEv
__ZNK3JSC12FuncExprNode14isFuncExprNodeEv
__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
+__ZN3JSC11ParserArenaD1Ev
+__ZN3JSC11ResolveNodeD0Ev
__ZN3JSC7SubNodeD0Ev
-__ZN3JSC12BinaryOpNodeD2Ev
-__ZN3JSC17BytecodeGeneratorD2Ev
+__ZN3JSC14ExpressionNodeD2Ev
+__ZN3JSC10ReturnNodeD0Ev
+__ZN3JSC14SourceElementsD0Ev
+__ZN3JSC9BlockNodeD0Ev
__ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
+__ZThn12_N3JSC11ProgramNodeD0Ev
__ZN3JSC11ProgramNodeD0Ev
-__ZN3JSC9ScopeNodeD2Ev
-__ZN3JSC9ScopeNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC13ParameterNodeD0Ev
__ZN3JSC17ExprStatementNodeD0Ev
+__ZThn12_N3JSC12FuncExprNodeD0Ev
__ZN3JSC12FuncExprNodeD0Ev
-__ZN3JSC12FuncExprNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC12NodeReleaser21adoptFunctionBodyNodeERN3WTF6RefPtrINS_16FunctionBodyNodeEEE
-__ZN3JSC13ParameterNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC13ParameterNodeD0Ev
+__ZThn12_N3JSC16FunctionBodyNodeD0Ev
__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
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC6RegExpEEELm0EE14shrinkCapacityEm
__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_12FuncDeclNodeELm0EEEED0Ev
+__ZN3JSC15DotAccessorNodeD0Ev
+__ZN3JSC12NotEqualNodeD0Ev
+__ZN3JSC10RegExpNodeD0Ev
+__ZN3JSC16ArgumentListNodeD0Ev
+__ZN3JSC13ArgumentsNodeD0Ev
+__ZN3JSC19FunctionCallDotNodeD0Ev
+__ZN3JSC14LogicalNotNodeD0Ev
+__ZN3JSC13LogicalOpNodeD0Ev
+__ZN3JSC6IfNodeD0Ev
__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
+__ZN3JSC17AssignResolveNodeD0Ev
+__ZN3JSC17ObjectLiteralNodeD0Ev
+__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED0Ev
__ZN3JSC16VarStatementNodeD0Ev
-__ZN3JSC16VarStatementNode12releaseNodesERNS_12NodeReleaserE
-__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b
-__ZNK3JSC10NumberNode8isNumberEv
-__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC21FunctionCallValueNodeD0Ev
+__ZN3JSC10StringNodeD0Ev
+__ZN3WTF14deleteOwnedPtrIN3JSC17BytecodeGeneratorEEEvPT_
+__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
+__ZN3JSC12FuncDeclNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC11Interpreter15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
+__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC9Structure13hasTransitionEPNS_7UString3RepEj
+__ZN3JSC11Interpreter15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_15PutPropertySlotE
+__ZN3JSC11Interpreter13resolveGlobalEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZL17combineCommaNodesPvPN3JSC14ExpressionNodeES2_
+__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
__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
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
+__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
+__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC10NumberNodeD0Ev
-__ZN3JSC11NewExprNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC11NewExprNodeD0Ev
-__ZN3JSC7AddNodeD0Ev
-__ZN3JSC8MultNodeD0Ev
-__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC19BracketAccessorNodeD0Ev
+__ZN3JSC18PostfixResolveNodeD0Ev
+__ZN3JSC15ConditionalNodeD0Ev
+__ZN3JSC9BreakNodeD0Ev
+__ZN3JSC18EmptyStatementNodeD0Ev
+__ZN3JSC7ForNodeD0Ev
+__ZN3JSC12PropertyNodeD0Ev
+__ZN3JSC16PropertyListNodeD0Ev
+__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
+__ZNK3JSC8JSString8toStringEPNS_9ExecStateE
+__ZN3JSC7UString4fromEj
+__ZN3JSC7UString3Rep6createEPtiN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrItEEEEEE
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
+__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
+__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZNK3JSC6JSCell8isObjectEPKNS_9ClassInfoE
-__ZNK3JSC12DateInstance9classInfoEv
-__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZNK3JSC12JSNumberCell8toNumberEPNS_9ExecStateE
+__ZNK3JSC12RegExpObject9classInfoEv
+__ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
+__ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
+__ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
+__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
+__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
+__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IPNS3_9StructureES9_ENS3_28StructureTransitionTableHashENS3_34StructureTransitionTableHashTraitsENS_10HashTraitsISA_EEE3addERKS7_RKSA_
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_S1_IPNS3_9StructureES9_EENS_18PairFirstExtractorISB_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsISA_EEEESG_E6rehashEi
+__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EESA_E6rehashEi
__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC13StatementNode12isReturnNodeEv
__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
+__ZN3JSC10IfElseNodeD0Ev
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivationC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZNK3JSC6JSCell9classInfoEv
+__Z12jsRegExpFreeP8JSRegExp
+__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
__ZNK3JSC19BracketAccessorNode10isLocationEv
__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
-__ZNK3JSC7ForNode6isLoopEv
-__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
+__ZNK3JSC14ExpressionNode5isAddEv
+__ZNK3JSC12JSActivation14isDynamicScopeEv
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC7AddNode5isAddEv
+__ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
+__ZNK3JSC10StringNode8isStringEv
+__ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
-__ZN3JSC7ForNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC7ForNodeD0Ev
-__ZN3JSC18PostfixResolveNodeD0Ev
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
+__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ThrowNodeD0Ev
+__ZN3JSC9EqualNodeD0Ev
+__ZN3JSC7AddNodeD0Ev
+__ZN3JSC15StrictEqualNodeD0Ev
+__ZN3JSC23FunctionCallResolveNodeD0Ev
__ZN3JSC17AssignBracketNodeD0Ev
-__ZN3JSC17AssignBracketNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC8ThisNodeD0Ev
-__ZN3JSC8JSObject17createInheritorIDEv
-__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3JSC17TypeOfResolveNodeD0Ev
+__ZN3JSC9ArrayNodeD0Ev
+__ZN3JSC13PrefixDotNodeD0Ev
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString4findERKS0_i
+__ZN3JSC11concatenateEPNS_7UString3RepES2_
__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_10JSValuePtrE
-__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
-__ZN3JSC21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
-__ZN3JSCL12getDSTOffsetEdd
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
+__ZNK3JSC7UString8toUInt32EPbb
+__ZNK3JSC7UString8toDoubleEbb
__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
+__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC7UString3Rep15reserveCapacityEi
+__ZN3WTF11fastReallocILb0EEEPvS1_m
+__ZN3JSC7UString6appendERKS0_
+__ZN3JSC16jsIsFunctionTypeENS_7JSValueE
+__ZNK3JSC9CodeBlock13refStructuresEPNS_11InstructionE
+__ZN3JSC14StructureChainC1EPNS_9StructureE
+__ZN3JSC14StructureChainC2EPNS_9StructureE
+__ZNK3JSC14StructureChain11isCacheableEv
+__ZNK3JSC9CodeBlock15derefStructuresEPNS_11InstructionE
+__ZN3JSC6RegExpD1Ev
+__ZThn12_N3JSC12FuncDeclNodeD0Ev
+__ZN3JSC12FuncDeclNodeD0Ev
+__ZNK3JSC10NumberNode8isNumberEv
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC13GreaterEqNode8opcodeIDEv
-__ZN3JSC13GreaterEqNodeD0Ev
-__ZN3JSC9ArgumentsD1Ev
-__ZN3JSC9ArgumentsD2Ev
__ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
-__ZNK3JSC11GreaterNode8opcodeIDEv
-__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC14LogicalNotNode8opcodeIDEv
-__ZN3JSC8WithNodeD0Ev
-__ZN3JSC8WithNode12releaseNodesERNS_12NodeReleaserE
+__ZL17bracketIsAnchoredPKh
+__ZL32branchFindFirstAssertedCharacterPKhb
+__ZL20branchNeedsLineStartPKhjj
+__ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
__ZN3JSC11GreaterNodeD0Ev
-__ZN3JSC11UnaryOpNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC14LogicalNotNodeD0Ev
-__ZN3JSC14ExpressionNodeD2Ev
-__ZN3JSC10JSValuePtr13equalSlowCaseEPNS_9ExecStateES0_S0_
-__ZN3JSC11Interpreter7resolveEPNS_9ExecStateEPNS_11InstructionERNS_10JSValuePtrE
-__ZNK3JSC8NullNode6isNullEv
-__ZN3JSC8NullNodeD0Ev
-__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataERKNS_10IdentifierEPNS_14ExpressionNodeES7_PNS_13StatementNodeEiii
-__ZNK3JSC9ForInNode6isLoopEv
+__ZN3JSC18NotStrictEqualNodeD0Ev
+__ZN3JSC8WithNodeD0Ev
+__ZN3JSC11ElementNodeD0Ev
+__ZN3JSC23CallFunctionCallDotNodeD0Ev
+__ZN3JSC6InNodeD0Ev
+__ZN3JSC11NewExprNodeD0Ev
+__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj
+__ZNK3JSC7UString10getCStringERN3WTF6VectorIcLm32EEE
__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
+__ZN3JSC9Structure22materializePropertyMapEv
+__ZNK3JSC14ExpressionNode11isCommaNodeEv
+__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8ThisNodeD0Ev
+__ZN3JSC9CommaNodeD0Ev
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9WhileNodeD0Ev
__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
+__ZNK3JSC7JSValue8toUInt32EPNS_9ExecStateE
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8NullNodeD0Ev
+__ZN3JSC8LessNodeD0Ev
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEERKNS_7ArgListE
__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
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
+__ZN3JSC11Interpreter7resolveEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSC11Interpreter14uncacheGetByIDEPNS_9CodeBlockEPNS_11InstructionE
+__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
__ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
-__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_10JSValuePtrE
-__ZN3WTF11fastReallocILb0EEEPvS1_m
-__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
-__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
+__ZN3JSC7TryNodeD0Ev
+__ZNK3JSC9CommaNode11isCommaNodeEv
+__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
__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
+__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE\r
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC7JSArray9setLengthEj
+__ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
+__ZN3JSC8JSObject17createInheritorIDEv
+__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC10JSFunction9classInfoEv
+__ZN3JSCplERKNS_7UStringES2_
+__ZN3JSC7UString6appendEPKc
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
+__ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode13isSimpleArrayEv
+__ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
+__ZN3JSC24ApplyFunctionCallDotNodeD0Ev
+__ZNK3JSC7JSArray9classInfoEv
+__ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
__ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
-__ZL5matchPKtPKhiR9MatchData
-__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9ThrowNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC9ThrowNodeD0Ev
-__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17DeleteBracketNodeD0Ev
-__ZN3JSC17DeleteBracketNode12releaseNodesERNS_12NodeReleaserE
-__ZNK3JSC6JSCell9getUInt32ERj
+__ZN3JSC7UString17expandPreCapacityEi
+__ZN3JSCL19isInvalidParamForInEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC7UString4fromEd
+__ZN3WTF4dtoaEPcdiPiS1_PS0_
+__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
+__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC12ContinueNodeD0Ev
+__ZN3JSC13DeleteDotNodeD0Ev
+__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
-__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZN3JSC7UString4fromEi
+__ZN3WTF6VectorItLm256EE6appendItEEvPKT_m
+__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12nonInlineNaNEv
+__ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
+__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrItEEE5derefEv
+__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15TypeOfValueNodeD0Ev
+__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
+__ZN3JSC13UnaryPlusNodeD0Ev
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7UString6appendEt
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC4Heap7collectEv
+__ZN3JSC4Heap30markStackObjectsConservativelyEv
+__ZN3JSC4Heap31markCurrentThreadConservativelyEv
+__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv
+__ZN3JSC4Heap18markConservativelyEPvS1_
+__ZN3JSC14JSGlobalObject4markEv
+__ZN3JSC8JSObject4markEv
+__ZN3JSC6JSCell4markEv
+__ZN3JSC10JSFunction4markEv
+__ZN3JSC16FunctionBodyNode4markEv
+__ZN3JSC9CodeBlock4markEv
+__ZN3JSC12JSActivation4markEv
+__ZN3JSC9Arguments4markEv
+__ZN3JSC7JSArray4markEv
+__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC18GlobalEvalFunction4markEv
+__ZN3JSC19JSStaticScopeObject4markEv
+__ZN3JSC4Heap20markProtectedObjectsEv
+__ZN3JSC12SmallStrings4markEv
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv
+__ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC12JSActivationD2Ev
+__ZN3JSC9ArgumentsD1Ev
+__ZN3JSC9ArgumentsD2Ev
+__ZN3JSC18RegExpMatchesArrayD1Ev
+__ZN3JSC8JSObjectD1Ev
+__ZN3JSC22JSPropertyNameIteratorD1Ev
+__ZN3JSC12StringObjectD1Ev
+__ZN3JSC8JSObjectD2Ev
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv
+__ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv
+__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17ReadModifyDotNodeD0Ev
+__ZN3JSC7UString10BaseString20slowIsBufferReadOnlyEv
+__ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorItLm256EE14expandCapacityEm
+__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
+__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
+__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
+__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE15reserveCapacityEm
+__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
+__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
+__ZN3WTF6VectorIiLm8EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
+__ZN3JSC14CaseClauseNodeD0Ev
+__ZN3JSC14ClauseListNodeD0Ev
+__ZN3JSC13CaseBlockNodeD0Ev
+__ZN3JSC10SwitchNodeD0Ev
+__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
-__ZN3JSC7UString6appendEPKc
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_10JSValuePtrE
-__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZNK3JSC7UString10UTF8StringEb
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7UStringC2EPtib
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
+__ZN3JSC7UString13appendNumericEi
+__ZN3JSC11concatenateEPNS_7UString3RepEi
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC13GreaterEqNodeD0Ev
+__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC8MultNodeD0Ev
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF16weakRandomNumberEv
+__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7UString3Rep11computeHashEPKti
+__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
+__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC20EvalFunctionCallNodeD0Ev
+__ZN3JSC11Interpreter22resolveBaseAndPropertyEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_7JSValueE
+__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
+__ZN3JSC13LiteralParser5parseENS0_11ParserStateE
+__ZNK3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3getEPS4_
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS1_INS2_8EvalNodeEEEENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6expandEv
+__ZN3JSC9ExecState9thisValueEv
+__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC8EvalNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
+__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11Interpreter11resolveBaseEPNS_9ExecStateEPNS_11InstructionE
+__ZN3JSC10LessEqNodeD0Ev
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZThn12_N3JSC8EvalNodeD0Ev
+__ZN3JSC8EvalNodeD0Ev
+__ZN3JSC22JSPropertyNameIterator4markEv
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyResolveNodeD0Ev
+__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
+__ZNK3JSC12JSNumberCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC7UString13appendNumericEd
+__ZN3JSC11concatenateEPNS_7UString3RepEd
+__ZN3JSC14jsIsObjectTypeENS_7JSValueE
+__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
+__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC7DivNodeD0Ev
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
+__ZN3WTF17getCurrentUTCTimeEv
+__ZN3WTF8timeClipEd
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12DateInstance9classInfoEv
+__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRN3WTF17GregorianDateTimeE
+__ZN3WTF21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3WTF12getUTCOffsetEv
+__ZN3WTFL12getDSTOffsetEdd
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF13tryFastMallocEm
+__ZN3JSC10BitAndNodeD0Ev
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL8parseIntERKNS_7UStringEi
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
+__ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEjb
+__ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
+__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
+__ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
+__ZNK3JSC10ScopeChain10localDepthEv
+__ZNK3JSC12JSActivation9classInfoEv
__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IPNS_12FuncDeclNodeELm0EEERKNS_10SourceCodeEji
__ZN3JSC13StatementNode6setLocEii
__ZN3JSC16FunctionBodyNode14copyParametersEv
__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
__ZN3JSC9CodeBlock43hasGlobalResolveInstructionAtBytecodeOffsetEj
-__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
+__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_7JSValueENS_7UStringE
+__ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
+__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
+__ZN3JSC11Interpreter20createExceptionScopeEPNS_9ExecStateEPKNS_11InstructionE
+__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC23FunctionCallBracketNodeD0Ev
+__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIjLm16EE6resizeEm
+__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10formatTimeERKN3WTF17GregorianDateTimeEb
+__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC12JSNumberCell8toObjectEPNS_9ExecStateE
+__ZN3JSC15constructNumberEPNS_9ExecStateENS_7JSValueE
+__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE
+__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC14PostfixDotNodeD0Ev
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
+__ZN3JSC14InstanceOfNodeD0Ev
+__ZN3JSCL27isInvalidParamForInstanceOfEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString12replaceRangeEiiRKS0_
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
+__ZNK3JSC12StringObject9classInfoEv
+__ZN3WTFL15dateToDayInYearEiii
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC19JSStaticScopeObjectD1Ev
+__ZN3JSC19JSStaticScopeObjectD2Ev
+__ZN3JSC13ErrorInstanceD1Ev
+__ZN3JSC13JSNotAnObjectD1Ev
+__ZN3JSC22JSNotAnObjectErrorStubD1Ev
+__ZN3JSC12NumberObjectD1Ev
+__ZN3JSC12DateInstanceD1Ev
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17PrefixResolveNodeD0Ev
+__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC7ModNodeD0Ev
+__ZN3JSC21ReadModifyBracketNodeD0Ev
+__ZN3JSC10BitXOrNodeD0Ev
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZL17makeLeftShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZL18makeRightShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC13LeftShiftNodeD0Ev
+__ZN3JSC14RightShiftNodeD0Ev
+__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZN3JSC10NegateNodeD0Ev
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11DoWhileNodeD0Ev
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17PrefixBracketNodeD0Ev
+__ZN3JSC10JSONObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22JSONProtoFuncStringifyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11StringifierC2EPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSC11Stringifier9stringifyENS_7JSValueE
+__ZN3JSC11Stringifier22appendStringifiedValueERNS_7UStringENS_7JSValueEPNS_8JSObjectERKNS_27PropertyNameForFunctionCallE
+__ZNK3JSC6JSCell9getStringERNS_7UStringE
+__ZN3JSC11Stringifier6Holder18appendNextPropertyERS0_RNS_7UStringE
+__ZNK3JSC7UString6substrEii
+__ZNK3JSC7UStringixEi
+__ZN3JSC11Stringifier18appendQuotedStringERNS_7UStringERKS1_
+__ZN3JSC7UString6appendEPKti
+__ZN3JSC11StringifierD2Ev
+__ZN3JSCL18JSONProtoFuncParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE0EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
+__ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZNK3JSC8JSObject22isNotAnObjectErrorStubEv
+__ZNK3JSC8JSObject19isWatchdogExceptionEv
+__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
+__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
+__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7PtrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
+__ZN3JSC17PrototypeFunctionD1Ev
+__ZN3JSC15ObjectPrototypeD1Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3JSC18GlobalEvalFunctionD1Ev
+__ZN3JSC10JSONObjectD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC22NativeErrorConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
+__ZN3JSC17RegExpConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC14ErrorPrototypeD1Ev
+__ZN3JSC15RegExpPrototypeD1Ev
+__ZN3JSC13DatePrototypeD1Ev
+__ZN3JSC12DateInstanceD2Ev
+__ZN3JSC15NumberPrototypeD1Ev
+__ZN3JSC16BooleanPrototypeD1Ev
+__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC14ArrayPrototypeD1Ev
+__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC17DeleteBracketNodeD0Ev
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject9classNameEv
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
+__ZN3JSC4Heap15recordExtraCostEm
+__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
+__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
+__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter11resolveSkipEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
+__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17DeleteResolveNodeD0Ev
+__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter14uncachePutByIDEPNS_9CodeBlockEPNS_11InstructionE
__ZNK3JSC9Arguments9classInfoEv
-__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_7ArgListE
-__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
-__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
-__ZN3JSC7TryNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC7TryNodeD0Ev
-__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZNK3JSC10JSValuePtr9toIntegerEPNS_9ExecStateE
+__ZN3JSC9Arguments15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
+__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState11stringTableEPS0_
+__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTFL7multaddERNS_6BigIntEii
+__ZN3WTF6VectorIjLm16EEaSERKS1_
+__ZN3WTFL4multERNS_6BigIntERKS0_
+__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18PostfixBracketNodeD0Ev
+__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__Z15jsc_pcre_xclassiPKh
+__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8VoidNodeD0Ev
+__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZNK3JSC9ArrayNode13isSimpleArrayEv
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateE
+__ZN3JSC7JSArray17compactForSortingEv
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEm
+__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray3popEv
+__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE
+__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_7JSValueE
+__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
+__ZNK3JSC7UString5rfindERKS0_i
+__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
+__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSC13BooleanObjectD1Ev
+__ZN3WTF17TCMalloc_PageHeap3NewEm
+__ZNK3JSC21UStringSourceProvider8getRangeEii
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
+__ZN3JSCL27compareByStringPairForQSortEPKvS1_
+__ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC12NumberObject9classInfoEv
+__ZN3JSCL19isNonASCIIIdentPartEi
+__ZN3JSC8EvalNode4markEv
+__ZN3WTF7Unicode18UTF8SequenceLengthEc
+__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
+__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
+__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE
+__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE1EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE15reserveCapacityEm
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16integerPartNoExpEd
+__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF13tryFastCallocEmm
+__ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3JSCL22compareNumbersForQSortEPKvS1_
+__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
+__ZN3JSC7JSArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState10arrayTableEPS0_
+__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC12JSNumberCell12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12NumberObject11getJSNumberEv
+__ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
+__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC9BitOrNodeD0Ev
+__ZN3JSC12JSGlobalData6createEb
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC7CStringD1Ev
+__ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC14BitwiseNotNodeD0Ev
+__ZN3JSC22UnsignedRightShiftNodeD0Ev
+__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
+__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
+__ZN3JSC15SimpleJumpTable14offsetForValueEii
+__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
+__ZN3WTF7HashSetIPN3JSC20MarkedArgumentBufferENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
__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
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
+__ZN3JSC4Heap7destroyEv
+__ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12JSGlobalDataD2Ev
+__ZN3JSC12RegisterFileD1Ev
+__ZNK3JSC9HashTable11deleteTableEv
+__ZN3JSC5LexerD1Ev
+__ZN3JSC5LexerD2Ev
+__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_EENS8_IS2_EEEEEEvRT0_
+__ZN3JSC17CommonIdentifiersD2Ev
+__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC4HeapD1Ev
+__ZN3JSC12SmallStringsD1Ev
-__ZN3WTF19initializeThreadingEv
__ZN3WTF10fastMallocEm
__ZN3WTF10fastMallocILb1EEEPvm
__ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
__ZN3WTFL15InitSizeClassesEv
__Z20TCMalloc_SystemAllocmPmm
+__ZN3WTFL13MetaDataAllocEm
__ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
__ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi
__ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
__ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
__ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
-__ZN3WTFL13MetaDataAllocEm
+__ZN3WTF19initializeThreadingEv
__ZN3WTF20initializeMainThreadEv
__ZN3WTF5MutexC1Ev
+__ZN3WTF28initializeMainThreadPlatformEv
__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF8fastFreeEPv
__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
__ZN3JSC19initializeThreadingEv
__ZN3JSCL23initializeThreadingOnceEv
__ZN3WTF15ThreadConditionC1Ev
__ZN3WTF5Mutex4lockEv
__ZN3WTF5Mutex6unlockEv
-__ZN3WTF8fastFreeEPv
__ZN3WTF12createThreadEPFPvS0_ES0_PKc
__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTrai
__ZN3WTFL16threadEntryPointEPv
-__ZN3WTF7HashMapIjP17_opaque_pthread_tNS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3addERKjRKS2_
-__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
__ZN3WTF16fastZeroedMallocEm
+__ZN3WTF21setThreadNameInternalEPKc
__ZN3WTF5MutexD1Ev
__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
+__ZN3WTF12isMainThreadEv
__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
__ZN3WTF13currentThreadEv
__ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF6VectorINS_19FunctionWithContextELm0EE14expandCapacityEm
+__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
__ZN3WTF15ThreadCondition4waitERNS_5MutexE
__ZN3JSC8DebuggerC2Ev
__ZN3WTF6strtodEPKcPPc
__ZN3WTF15ThreadCondition6signalEv
+__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
__ZN3WTF15ThreadCondition9broadcastEv
+-[WTFMainThreadCaller call]
+__ZN3WTF31dispatchFunctionsFromMainThreadEv
+__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
+__ZN3WTF11fastReallocEPvm
+__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC7UStringC1EPKti
+__ZN3JSC7UStringC2EPKti
__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
+__ZN3JSC9Structure18startIgnoringLeaksEv
+__ZN3JSC7VPtrSetC2Ev
+__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoE
__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE
-__ZN3JSC7JSArrayD0Ev
+__ZN3JSC7JSArrayD1Ev
+__ZN3JSC7JSArrayD2Ev
__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
__ZN3JSC9StructureD1Ev
-__ZN3JSC11JSByteArray15createStructureENS_10JSValuePtrE
+__ZN3JSC9StructureD2Ev
+__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
+__ZN3JSC11JSByteArrayD1Ev
+__ZN3JSC8JSStringD1Ev
+__ZN3JSC10JSFunctionD1Ev
+__ZN3JSC10JSFunctionD2Ev
+__ZN3JSC8JSObjectD2Ev
+__ZN3JSC12JSGlobalDataC2EbRKNS_7VPtrSetE
__ZN3JSC21createIdentifierTableEv
__ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
+__ZN3JSC17CommonIdentifiersC2EPNS_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_
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24HashT
__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_
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTra
+__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev
__ZN3JSC12SmallStringsC1Ev
-__ZN3JSC5LexerC1EPNS_12JSGlobalDataE
-__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
__ZN3JSC19ExecutableAllocator17intializePageSizeEv
__ZN3JSC14ExecutablePool11systemAllocEm
-__ZN3JSC27startProfilerServerIfNeededEv
-+[ProfilerServer sharedProfileServer]
--[ProfilerServer init]
-__ZN3JSC11Interpreter10initializeEPNS_12JSGlobalDataE
+__ZN3JSC5LexerC1EPNS_12JSGlobalDataE
+__ZN3JSC5LexerC2EPNS_12JSGlobalDataE
+__ZN3JSC11InterpreterC1Ev
+__ZN3JSC11InterpreterC2Ev
+__ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_7JSValueE
+__ZN3WTF7HashMapIPvN3JSC8OpcodeIDENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS6_IS3_EEE3addERKS1_RKS3_
+__ZN3WTF9HashTableIPvSt4pairIS1_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS5_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTrai
+__ZN3JSC8JITStubsC1EPNS_12JSGlobalDataE
__ZN3JSC3JITC1EPNS_12JSGlobalDataEPNS_9CodeBlockE
-__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEv
+__ZN3JSC3JITC2EPNS_12JSGlobalDataEPNS_9CodeBlockE
+__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEPN3WTF6RefPtrINS_14ExecutablePoolEEEPNS_12JSGlobalDataEPPvS9_S9_S9_S9_S9_
+__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDE
+__ZN3JSC12X86Assembler3jCCENS0_9ConditionE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE6ImmPtrENS_3X8610RegisterIDE
+__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDE
__ZN3JSC15AssemblerBuffer11ensureSpaceEi
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common9ConditionENS_3X8610RegisterIDENS_22AbstractMacroAsse
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDENS_3X8610RegisterIDE
+__ZN3JSC20MacroAssemblerX86_644callEv
__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDEi
-__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDE
-__ZN3JSC14MacroAssembler4pokeENS_3X8610RegisterIDEi
__ZN3JSC3JIT32compileOpCallInitializeCallFrameEv
-__ZN3JSC14MacroAssembler5jnz32ENS_3X8610RegisterIDENS0_5Imm32E
-__ZN3WTF11fastReallocEPvm
-__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDEi
+__ZN3JSC20MacroAssemblerX86_6421makeTailRecursiveCallENS_22AbstractMacroAssemblerINS_12X86AssemblerEE4JumpE
+__ZN3JSC14TimeoutCheckerC1Ev
+__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
+__ZN3JSC27startProfilerServerIfNeededEv
++[ProfilerServer sharedProfileServer]
+-[ProfilerServer init]
+__ZN3JSC9Structure17stopIgnoringLeaksEv
__ZN3JSC4Heap8allocateEm
__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv
+__ZN3JSC4Heap4heapENS_7JSValueE
+__ZN3JSC4Heap7protectENS_7JSValueE
+__ZN3WTF7HashMapIPN3JSC6JSCellEjNS_7PtrHashIS3_EENS_10HashTraitsIS3_EENS6_IjEEE3addERKS3_RKj
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraits
__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject5resetENS_10JSValuePtrE
+__ZN3JSC14JSGlobalObject5resetENS_7JSValueE
__ZN3JSC4Heap12heapAllocateILNS_8HeapTypeE0EEEPvm
-__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
__ZN3JSC7UStringC1EPKc
__ZN3JSCL9createRepEPKc
-__ZN3JSC8JSObject9putDirectERKNS_10IdentifierENS_10JSValuePtrEjbRNS_15PutPropertySlotE
+__ZN3JSC8JSObject9putDirectERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjRm
__ZN3JSC9Structure3getERKNS_10IdentifierERj
__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
__ZN3JSC9Structure3putERKNS_10IdentifierEj
+__ZN3JSC8JSObject26putDirectWithoutTransitionERKNS_10IdentifierENS_7JSValueEj
__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEj
-__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureE
-__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_10JSValuePtrES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureEPPNS_10JSFunctionES7_
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RK
+__ZN3JSC12JSGlobalData17createNativeThunkEv
+__ZN3JSC16FunctionBodyNode17createNativeThunkEPNS_12JSGlobalDataE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC21ParserArenaRefCountedEEELm0EE15reserveCapacityEm
+__ZN3JSC11ParserArena5resetEv
__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
__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
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26Symbo
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17Identif
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjec
+__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
__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
+__ZN3JSC4Heap9unprotectENS_7JSValueE
__ZN3JSC6JSCellnwEmPNS_9ExecStateE
-__ZN3JSC14JSGlobalObject17startTimeoutCheckEv
-__ZN3JSC11Interpreter17resetTimeoutCheckEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_10JSValuePtrE
+__ZN3JSC14TimeoutChecker5resetEv
+__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
__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_
+__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslatorEE
+__ZN3WTF15SegmentedVectorINS_10IdentifierELm64EE6appendIS1_EEvRKT_
__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
+__ZN3JSC20ParserArenaDeletablenwEmPNS_12JSGlobalDataE
+__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE15reserveCapacityEm
+__ZN3JSC5Lexer10sourceCodeEiii
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3WTF6VectorIPN3JSC12FuncDeclNodeELm0EE14expandCapacityEm
+__ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
__ZNK3JSC13StatementNode16isEmptyStatementEv
-__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_20ParserRefCountedDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEEEPNS3_INS5_INS4_6RefPtrINS_12FuncDeclNodeEEELm0EEEEEjii
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
+__ZL20makeFunctionCallNodePvN3JSC8NodeInfoIPNS0_14ExpressionNodeEEENS1_IPNS0_13ArgumentsNodeEEEiii
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3JSC5Lexer7record8Ei
+__ZN3JSC5Lexer10scanRegExpEv
+__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE
+__ZN3JSC7UString3Rep7destroyEv
__ZN3JSC5Lexer5clearEv
+__ZN3JSC10Identifier6removeEPNS_7UString3RepE
__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
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPN
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14shrinkCapacityEm
+__ZN3JSC11ParserArena10removeLastEv
__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
-__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_10JSValuePtrE
+__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_7JSValueE
__ZN3JSC11ProgramNode16generateBytecodeEPNS_14ScopeChainNodeE
-__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
+__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
+__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEEN
__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm
__ZN3JSC9Structure22toDictionaryTransitionEPS0_
+__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
+__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
+__ZN3JSC9Structure6removeERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
__ZN3JSC17BytecodeGenerator11newRegisterEv
__ZN3JSC9Structure24fromDictionaryTransitionEPS0_
__ZN3JSC17BytecodeGenerator8generateEv
__ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
-__ZN3JSC17BytecodeGenerator11addConstantENS_10JSValuePtrE
-__ZN3WTF9HashTableIPN3JSC23JSValueEncodedAsPointerESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS1_17BytecodeGenerator17JSValueHashTraitsENS_10HashTraitsIjEEEESC_E6expandEv
+__ZN3JSC17BytecodeGenerator11addConstantENS_7JSValueE
+__ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC17JSValueHashTraitsENS
__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEm
-__ZNK3JSC13StatementNode6isLoopEv
+__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_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
+__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
+__ZNK3JSC21UStringSourceProvider6lengthEv
+__ZNK3JSC21UStringSourceProvider4dataEv
+__ZN3JSC19extractFunctionBodyEPNS_11ProgramNodeE
+__ZNK3JSC17ExprStatementNode15isExprStatementEv
+__ZNK3JSC12FuncExprNode14isFuncExprNodeEv
+__ZN3JSC16FunctionBodyNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser14reparseInPlaceEPNS_12JSGlobalDataEPNS_16FunctionBodyNodeE
+__ZL11makeSubNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC14ExpressionNode14stripUnaryPlusEv
+__ZNK3JSC14ExpressionNode8isNumberEv
+__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
+__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3Re
+__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
+__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator12newTemporaryEv
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
+__ZNK3JSC9BlockNode7isBlockEv
+__ZNK3JSC10ReturnNode12isReturnNodeEv
__ZN3JSC9CodeBlock11shrinkToFitEv
__ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14shrinkCapacityEm
__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14shrinkCapacityEm
__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
-__ZN3JSC17ExprStatementNodeD1Ev
-__ZN3JSC19FunctionCallDotNodeD1Ev
-__ZN3JSC19FunctionCallDotNode12releaseNodesERNS_12NodeReleaserE
-__ZN3WTF6VectorINS_6RefPtrIN3JSC16ParserRefCountedEEELm0EE14expandCapacityEm
-__ZN3JSC16ParserRefCounted12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC13ArgumentsNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC11ResolveNodeD1Ev
-__ZN3JSC13ArgumentsNodeD1Ev
+__ZN3JSC11ParserArenaD1Ev
+__ZN3JSC11ResolveNodeD0Ev
+__ZN3JSC7SubNodeD0Ev
+__ZN3JSC10ReturnNodeD0Ev
+__ZN3JSC14SourceElementsD0Ev
+__ZN3JSC9BlockNodeD0Ev
+__ZN3JSC17BytecodeGeneratorD2Ev
+__ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
+__ZThn16_N3JSC11ProgramNodeD0Ev
+__ZN3JSC11ProgramNodeD0Ev
+__ZN3JSC13ParameterNodeD0Ev
+__ZN3JSC17ExprStatementNodeD0Ev
+__ZThn16_N3JSC12FuncExprNodeD0Ev
+__ZN3JSC12FuncExprNodeD0Ev
+__ZThn16_N3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC9CodeBlockD1Ev
+__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC21UStringSourceProviderD0Ev
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_12FuncDeclNodeELm0EEEED0Ev
+__ZN3JSC16ArgumentListNodeD0Ev
+__ZN3JSC13ArgumentsNodeD0Ev
+__ZN3JSC23FunctionCallResolveNodeD0Ev
__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
__ZN3JSC3JIT14privateCompileEv
__ZN3JSC3JIT22privateCompileMainPassEv
-__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
-__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
-__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
+__ZN3JSC3JIT13emit_op_enterEPNS_11InstructionE
+__ZN3JSC3JIT16emit_op_new_funcEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_648storePtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE6ImmPtrENS3_15ImplicitAddressE
+__ZN3JSC11JITStubCall4callEj
__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEm
-__ZN3JSC3JIT22privateCompileLinkPassEv
+__ZN3JSC3JIT11emit_op_movEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_new_func_expEPNS_11InstructionE
+__ZN3JSC3JIT12emit_op_callEPNS_11InstructionE
+__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
+__ZN3JSC3JIT11emit_op_endEPNS_11InstructionE
+__ZN3JSC11JITStubCall4callEv
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14shrinkCapacityEm
__ZN3JSC3JIT23privateCompileSlowCasesEv
-__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEj
+__ZN3JSC3JIT16emitSlow_op_callEPNS_11InstructionERPNS_13SlowCaseEntryE
__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
-__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
+_ctiTrampoline
+__ZN3JSC8JITStubs15cti_op_new_funcEPPv
__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
+__ZN3JSC8JITStubs19cti_op_new_func_expEPPv
+__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC8JITStubs22cti_op_call_JSFunctionEPPv
+__ZN3JSC16FunctionBodyNode15generateJITCodeEPNS_14ScopeChainNodeE
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator8newLabelEv
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
+__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEiNS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_17BytecodeGenerator28Identifi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHa
__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
-__ZNK3JSC14LogicalNotNode8opcodeIDEv
+__ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+__ZN3JSC17BytecodeGenerator19emitResolveFunctionEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14Pair
+__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
__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_
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC13StatementNode12isReturnNodeEv
+__ZN3JSC15DotAccessorNodeD0Ev
+__ZN3JSC10StringNodeD0Ev
+__ZN3JSC11BooleanNodeD0Ev
+__ZN3JSC6IfNodeD0Ev
+__ZN3JSC10IfElseNodeD0Ev
+__ZN3JSC3JIT22emit_op_get_global_varEPNS_11InstructionE
+__ZN3JSC3JIT29emitGetVariableObjectRegisterENS_3X8610RegisterIDEiS2_
+__ZN3JSC3JIT17emit_op_get_by_idEPNS_11InstructionE
+__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEmPKS2_
+__ZN3JSC3JIT14emit_op_jfalseEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_3X8610RegisterIDENS_22AbstractMacroAssembler
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_3X8610RegisterIDES4_
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
+__ZN3JSC3JIT20emit_op_resolve_funcEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_jmpEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_retEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_get_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEj
+__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_9ConditionENS_3X8610RegisterIDENS_22AbstractMacroAssemblerINS_12X86Assemble
+__ZN3JSC8JITStubs23cti_vm_dontLazyLinkCallEPPv
+__ZN3JSC31ctiPatchNearCallByReturnAddressENS_22AbstractMacroAssemblerINS_12X86AssemblerEE22ProcessorReturnAddressEPv
+__ZN3JSC8JITStubs23cti_register_file_checkEPPv
+__ZN3JSC8JITStubs16cti_op_get_by_idEPPv
+__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC27ctiPatchCallByReturnAddressENS_22AbstractMacroAssemblerINS_12X86AssemblerEE22ProcessorReturnAddressEPv
+__ZN3JSC8JITStubs12cti_op_jtrueEPPv
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZN3JSC8JITStubs19cti_op_resolve_funcEPPv
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC8JSString8toStringEPNS_9ExecStateE
+__ZN3JSC8JITStubs23cti_op_get_by_id_secondEPPv
+__ZN3JSC8JITStubs15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_mNS_22AbstractMacroAssemblerINS_12X86Assembl
+__ZN3JSC3JIT22compileGetDirectOffsetEPNS_8JSObjectENS_3X8610RegisterIDES4_m
+__ZN3JSC8JITStubs19cti_vm_lazyLinkCallEPPv
+__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockENS_7JITCodeEPNS_12CallLinkInfoEi
+__ZN3JSC8JITStubs10cti_op_endEPPv
+__ZThn16_N3JSC12FuncDeclNodeD0Ev
+__ZN3JSC12FuncDeclNodeD0Ev
+__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
+__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeCha
+__ZNK3JSC15DotAccessorNode10isLocationEv
+__ZNK3JSC14ExpressionNode13isResolveNodeEv
+__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
+__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC19FunctionCallDotNodeD0Ev
+__ZL26appendToVarDeclarationListPvRPN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j
+__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEm
+__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii
+__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__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
+__ZN3JSC4Yarr15jitCompileRegexEPNS_12JSGlobalDataERNS0_14RegexCodeBlockERKNS_7UStringERjRPKcbb
+__ZN3JSC4Yarr12compileRegexERKNS_7UStringERNS0_12RegexPatternE
+__ZN3JSC4Yarr18PatternDisjunction17addNewAlternativeEv
+__ZN3WTF6VectorIPN3JSC4Yarr18PatternAlternativeELm0EE14expandCapacityEm
+__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE11parseTokensEv
+__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEm
+__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE11parseEscapeILb0ES2_EEbRT0_
+__ZN3JSC4Yarr23RegexPatternConstructor25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
+__ZN3JSC4Yarr14wordcharCreateEv
+__ZN3WTF6VectorItLm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEm
+__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEm
+__ZN3JSC4Yarr14RegexGenerator19generateDisjunctionEPNS0_18PatternDisjunctionE
__ZN3JSC12X86Assembler7addl_irEiNS_3X8610RegisterIDE
-__ZN3JSC4WREC9Generator21generateReturnSuccessEv
-__ZN3JSC4WREC9Generator22generateIncrementIndexEPNS_14MacroAssembler4JumpE
-__ZN3JSC4WREC9Generator27generateJumpIfNotEndOfInputENS_14MacroAssembler5LabelE
-__ZN3JSC4WREC9Generator21generateReturnFailureEv
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_9ConditionENS_3X8610RegisterIDES3_
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6appendENS2_4JumpE
+__ZN3JSC4Yarr14RegexGenerator12generateTermERNS1_19TermGenerationStateE
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_9ConditionENS_3X8610RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5I
+__ZN3JSC4Yarr14RegexGenerator19TermGenerationState15jumpToBacktrackENS_22AbstractMacroAssemblerINS_12X86AssemblerEE4JumpEPNS_14
+__ZN3JSC4Yarr14RegexGenerator13readCharacterEiNS_3X8610RegisterIDE
+__ZN3JSC4Yarr14RegexGenerator19matchCharacterClassENS_3X8610RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpLis
+__ZN3JSC4Yarr14RegexGenerator24matchCharacterClassRangeENS_3X8610RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8Ju
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList4linkEPS2_
+__ZN3JSC23MacroAssemblerX86Common4jumpEv
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EED1Ev
+__ZN3JSC4Yarr14RegexGenerator28generateCharacterClassGreedyERNS1_19TermGenerationStateE
+__ZN3JSC12X86Assembler7subl_irEiNS_3X8610RegisterIDE
+__ZN3JSC15AssemblerBuffer4growEv
+__ZN3WTF15deleteAllValuesIPN3JSC4Yarr14CharacterClassELm0EEEvRKNS_6VectorIT_XT0_EEE
__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
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
+__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
+__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode5isAddEv
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC17AssignResolveNodeD0Ev
+__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED0Ev
+__ZN3JSC16VarStatementNodeD0Ev
+__ZN3JSC14LogicalNotNodeD0Ev
+__ZN3JSC10RegExpNodeD0Ev
+__ZN3JSC10NumberNodeD0Ev
+__ZN3JSC19BracketAccessorNodeD0Ev
+__ZN3JSC9EqualNodeD0Ev
+__ZN3JSC15ConditionalNodeD0Ev
+__ZN3JSC7AddNodeD0Ev
+__ZN3JSC13GreaterEqNodeD0Ev
+__ZN3JSC13AssignDotNodeD0Ev
+__ZN3JSC3JIT13emit_op_jtrueEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_new_regexpEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_get_by_valEPNS_11InstructionE
+__ZN3JSC3JIT10emit_op_eqEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_addEPNS_11InstructionE
+__ZN3JSC11JITStubCall11addArgumentEjNS_3X8610RegisterIDE
+__ZN3JSC3JIT16emit_op_jnlesseqEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_put_by_idEPNS_11InstructionE
__ZN3JSC3JIT21compilePutByIdHotPathEiPNS_10IdentifierEij
-__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE6appendIS2_EEvRKT_
-__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDES4_ii
-__ZN3JSC3JIT11emitCTICallEPFPNS_23JSValueEncodedAsPointerEPvzE
-__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
-__ZN3JSC3JIT23compileFastArith_op_addEPNS_11InstructionE
+__ZN3JSC3JIT17emitSlow_op_jtrueEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22emitSlow_op_get_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT14emitSlow_op_eqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT20emitSlow_op_jnlesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common9ConditionENS_3X8610RegisterIDES4_
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDE
+__ZN3JSC23MacroAssemblerX86Common12branchDoubleENS0_15DoubleConditionENS_3X8613XMMRegisterIDES3_
+__ZN3JSC3JIT21emitSlow_op_put_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
__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
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC13LogicalOpNodeD0Ev
+__ZN3JSC3JIT22emit_op_resolve_globalEPNS_11InstructionE
+__ZN3JSC8JITStubs21cti_op_resolve_globalEPPv
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZNK3JSC6JSCell9classInfoEv
+__ZN3JSC4Yarr23RegexPatternConstructor20atomPatternCharacterEt
+__ZN3JSC4Yarr25CharacterClassConstructor7putCharEt
+__ZN3JSC4Yarr25CharacterClassConstructor9addSortedERN3WTF6VectorItLm0EEEt
+__ZN3JSC4Yarr23RegexPatternConstructor21atomCharacterClassEndEv
+__ZN3JSC4Yarr23RegexPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj
+__ZN3JSC4Yarr14RegexGenerator25generateParenthesesSingleERNS1_19TermGenerationStateE
+__ZN3JSC4Yarr14RegexGenerator30generateParenthesesDisjunctionERNS0_11PatternTermERNS1_19TermGenerationStateEj
+__ZN3WTF6VectorIN3JSC4Yarr14RegexGenerator26AlternativeBacktrackRecordELm0EE14expandCapacityEm
+__ZN3JSC4Yarr14RegexGenerator19jumpIfCharNotEqualsEti
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_3X8610RegisterIDES4_ii
+__ZN3JSC4Yarr14RegexGenerator19TermGenerationState15jumpToBacktrackERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEP
__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
+__ZN3JSC4Yarr12executeRegexERNS0_14RegexCodeBlockEPKtjjPii
+__ZN3JSC8JITStubs17cti_op_new_regexpEPPv
+__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
+__ZNK3JSC12RegExpObject9classInfoEv
+__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
+__ZN3JSC8JITStubs17cti_op_get_by_valEPPv
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JITStubs9cti_op_eqEPPv
+__ZN3JSCeqERKNS_7UStringES2_
+__ZN3JSC8JITStubs10cti_op_addEPPv
+__ZN3JSC11concatenateEPNS_7UString3RepES2_
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString4findERKS0_i
+__ZN3JSC8JITStubs16cti_op_put_by_idEPPv
+__ZNK3JSC7UString8toUInt32EPbb
+__ZNK3JSC7UString8toDoubleEbb
+__ZNK3JSC7UString10getCStringERN3WTF6VectorIcLm32EEE
+__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
+__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
+__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
+__ZL11checkEscapePPKtS0_P9ErrorCodeib
+__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
+__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZL5matchPKtPKhiR9MatchData
+__ZNK3JSC7UString14toStrictUInt32EPb
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
+__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC12PropertyNodeD0Ev
+__ZN3JSC16PropertyListNodeD0Ev
+__ZN3JSC17ObjectLiteralNodeD0Ev
+__ZN3JSC7TryNodeD0Ev
+__ZN3JSC3JIT18emit_op_new_objectEPNS_11InstructionE
+__ZN3JSC3JIT13emit_op_catchEPNS_11InstructionE
+__ZN3JSC3JIT22emit_op_push_new_scopeEPNS_11InstructionE
+__ZN3JSC3JIT15emit_op_resolveEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_pop_scopeEPNS_11InstructionE
+__ZN3JSC8JITStubs17cti_op_new_objectEPPv
+__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
+__ZN3JSC17StructureStubInfo5derefEv
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EES
+__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8ThisNodeD0Ev
+__ZN3JSC6InNodeD0Ev
+__ZN3JSC3JIT29emit_op_enter_with_activationEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_convert_thisEPNS_11InstructionE
+__ZN3JSC3JIT27emit_op_tear_off_activationEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_convert_thisEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs22cti_op_push_activationEPPv
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivationC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
+__ZN3JSC4Yarr12digitsCreateEv
+__ZN3JSC4Yarr25CharacterClassConstructor6appendEPKNS0_14CharacterClassE
+__ZN3JSC4Yarr25CharacterClassConstructor14addSortedRangeERN3WTF6VectorINS0_14CharacterRangeELm0EEEtt
+__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE28CharacterClassParserDelegate20atomPatternCharacterEt
+__ZN3JSC11GreaterNodeD0Ev
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC7UStringC2EPtib
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11JSImmediate12nonInlineNaNEv
+__ZN3JSC8JITStubs11cti_op_lessEPPv
+__ZN3JSC8JITStubs9cti_op_inEPPv
+__ZNK3JSC6JSCell9getUInt32ERj
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
__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
-__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
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
+__ZN3JSC8LessNodeD0Ev
+__ZN3JSC17PrefixResolveNodeD0Ev
+__ZN3JSC12ContinueNodeD0Ev
+__ZN3JSC7ForNodeD0Ev
+__ZN3JSC21ReadModifyResolveNodeD0Ev
+__ZN3JSC11NewExprNodeD0Ev
+__ZN3JSC3JIT11emit_op_notEPNS_11InstructionE
+__ZN3JSC3JIT15emit_op_pre_incEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_loop_if_lessEPNS_11InstructionE
+__ZN3JSC3JIT16emitTimeoutCheckEv
+__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE
+__ZN3JSC3JIT11emit_op_subEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_constructEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_construct_verifyEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_notEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT19emitSlow_op_pre_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT24emitSlow_op_loop_if_lessEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT15emitSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesE
+__ZN3JSC15AssemblerBuffer7putByteEi
+__ZN3JSC12X86Assembler23X86InstructionFormatter11twoByteOp64ENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDE
+__ZN3JSC3JIT15emitSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT27compileOpConstructSetupArgsEPNS_11InstructionE
+__ZN3JSC3JIT28emitSlow_op_construct_verifyEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC7UString4fromEj
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
+__ZN3JSC8JITStubs10cti_op_notEPPv
+__ZN3JSC8JITStubs24cti_op_get_by_id_genericEPPv
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEERKNS_7ArgListE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs31cti_op_construct_NotJSConstructEPPv
+__ZN3JSC3JIT33privateCompilePatchGetArrayLengthENS_22AbstractMacroAssemblerINS_12X86AssemblerEE22ProcessorReturnAddressE
+__ZN3JSC8JITStubs27cti_op_get_by_id_proto_listEPPv
+__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_mP
+__ZN3JSC3JIT16patchGetByIdSelfEPNS_17StructureStubInfoEPNS_9StructureEmNS_22AbstractMacroAssemblerINS_12X86AssemblerEE22Process
+__ZN3JSC14StructureChainC1EPNS_9StructureE
+__ZN3JSC14StructureChainC2EPNS_9StructureE
+__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmmNS_22AbstractMacroAssemb
+__ZN3JSC8JITStubs23cti_op_put_by_id_secondEPPv
+__ZN3JSC8JITStubs15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPvNS_7JSValueERKNS_15PutPropertySlotE
+__ZN3JSC8JITStubs24cti_op_put_by_id_genericEPPv
+__ZN3JSC8JITStubs26cti_op_tear_off_activationEPPv
+__ZN3JSC8JITStubs21cti_op_ret_scopeChainEPPv
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
+__ZN3JSC3JIT22emit_op_get_scoped_varEPNS_11InstructionE
+__ZN3JSC3JIT22emit_op_put_scoped_varEPNS_11InstructionE
+__ZN3JSC3JIT29emitPutVariableObjectRegisterENS_3X8610RegisterIDES2_i
+__ZN3JSC12X86Assembler7movq_rrENS_3X8610RegisterIDENS1_13XMMRegisterIDE
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15StrictEqualNodeD0Ev
+__ZN3JSC3JIT16emit_op_stricteqEPNS_11InstructionE
+__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
+__ZN3JSC3JIT20emitSlow_op_stricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs15cti_op_stricteqEPPv
__ZN3WTF12detachThreadEj
__ZN3WTFL26pthreadHandleForIdentifierEj
__ZN3WTFL31clearPthreadHandleForIdentifierEj
-__ZN3WTF15ThreadConditionD1Ev
-__ZN3WTF23waitForThreadCompletionEjPPv
-__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
-__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3WTF14FastMallocZone10statisticsEP14_malloc_zone_tP19malloc_statistics_t
-__ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZNK3JSC11ResolveNode10isLocationEv
-__ZNK3JSC11ResolveNode13isResolveNodeEv
-__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSObjectE
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE15reserveCapacityEm
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8NullNodeD0Ev
+__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjEPNS3_9StructureENS3_28StructureTransitionTableHashENS3_34StructureTra
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_PNS3_9StructureEENS_18PairFirstExtractorISA_EENS3_28Structur
+__ZN3JSC9Structure22materializePropertyMapEv
+__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15TypeOfValueNodeD0Ev
+__ZN3JSC12NotEqualNodeD0Ev
+__ZN3JSC3JIT11emit_op_neqEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_neqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs13cti_op_typeofEPPv
+__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC8JITStubs10cti_op_neqEPPv
+__ZN3JSC14ExecutablePool13systemReleaseERKNS0_10AllocationE
+__ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
+__ZNK3JSC10NumberNode8isNumberEv
+__ZNK3JSC14ExpressionNode10isLocationEv
+__ZN3WTF6VectorIPN3JSC10RegisterIDELm32EE14expandCapacityEm
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC4Yarr13newlineCreateEv
+__ZN3JSC12X86Assembler23X86InstructionFormatter15emitRexIfNeededEiii
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_3X8610RegisterIDES3_ii
+__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__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
+__ZN3JSC17BytecodeGenerator20emitLoadGlobalObjectEPNS_10RegisterIDEPNS_8JSObjectE
+__ZN3WTF6VectorIN3JSC7JSValueELm0EE14expandCapacityEm
+__ZNK3JSC7AddNode5isAddEv
+__ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
+__ZNK3JSC10StringNode8isStringEv
+__ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
+__ZN3JSC4Yarr12spacesCreateEv
+__ZN3JSC4Yarr15nonspacesCreateEv
+__ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5Imm32ENS_3X8610RegisterIDE
+__ZN3JSC14MacroAssembler4peekENS_3X8610RegisterIDEi
+__ZN3JSC4Yarr14RegexGenerator12atEndOfInputEv
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6linkToENS2_5LabelEPS2_
+__ZN3JSC14MacroAssembler4pokeENS_3X8610RegisterIDEi
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
+__ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC4Yarr14RegexGenerator29generateAssertionWordBoundaryERNS1_19TermGenerationStateE
+__ZN3JSC4Yarr14RegexGenerator22matchAssertionWordcharERNS1_19TermGenerationStateERNS_22AbstractMacroAssemblerINS_12X86Assembler
+__ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEm
+__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsId
+__ZN3JSC17TypeOfResolveNodeD0Ev
+__ZN3JSC18NotStrictEqualNodeD0Ev
+__ZN3JSC8WithNodeD0Ev
+__ZN3JSC21FunctionCallValueNodeD0Ev
+__ZN3JSC9ArrayNodeD0Ev
+__ZN3JSC11ElementNodeD0Ev
+__ZN3JSC23CallFunctionCallDotNodeD0Ev
+__ZN3JSC9ThrowNodeD0Ev
+__ZN3JSC9CommaNodeD0Ev
+__ZN3JSC3JIT23emit_op_unexpected_loadEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_to_primitiveEPNS_11InstructionE
+__ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_nstricteqEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_push_scopeEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
+__ZN3JSC3JIT16emit_op_jneq_ptrEPNS_11InstructionE
+__ZN3JSC3JIT13emit_op_throwEPNS_11InstructionE
+__ZN3JSC3JIT14emit_op_jnlessEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_to_primitiveEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT18emitSlow_op_jnlessEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18PostfixResolveNodeD0Ev
+__ZN3JSC8JITStubs22cti_op_call_arityCheckEPPv
+__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSCplERKNS_7UStringES2_
+__ZN3JSC7UString6appendERKS0_
+__ZN3JSC7UString17expandPreCapacityEi
+__ZN3WTF11fastReallocILb0EEEPvS1_m
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b
__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
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC7ModNodeD0Ev
+__ZN3JSC7DivNodeD0Ev
+__ZN3JSC8MultNodeD0Ev
+__ZN3JSC9WhileNodeD0Ev
+__ZN3JSC3JIT11emit_op_modEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_mulEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_loop_if_trueEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT15emitSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT24emitSlow_op_loop_if_trueEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
+__ZN3JSC8JITStubs10cti_op_divEPPv
+__ZN3JSC3JIT22emit_op_loop_if_lesseqEPNS_11InstructionE
+__ZN3JSC3JIT26emitSlow_op_loop_if_lesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs13cti_op_lesseqEPPv
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF6VectorItLm256EE6appendItEEvPKT_m
+__ZN3WTF6VectorItLm256EE14expandCapacityEm
+__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE15reserveCapacityEm
+__ZN3JSC4Heap7collectEv
+__ZN3JSC4Heap30markStackObjectsConservativelyEv
+__ZN3JSC4Heap31markCurrentThreadConservativelyEv
+__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv
+__ZN3JSC4Heap18markConservativelyEPvS1_
+__ZN3JSC7JSArray4markEv
+__ZN3JSC8JSObject4markEv
__ZN3JSC10JSFunction4markEv
+__ZN3JSC6JSCell4markEv
+__ZN3JSC14JSGlobalObject4markEv
+__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC18GlobalEvalFunction4markEv
__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
+__ZN3JSC4Heap20markProtectedObjectsEv
+__ZN3JSC12SmallStrings4markEv
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC15ObjectPrototypeD1Ev
+__ZN3JSC14ArrayPrototypeD1Ev
+__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC16BooleanPrototypeD1Ev
+__ZN3JSC15NumberPrototypeD1Ev
+__ZN3JSC13DatePrototypeD1Ev
+__ZN3JSC12DateInstanceD2Ev
+__ZN3JSC15RegExpPrototypeD1Ev
+__ZN3JSC14ErrorPrototypeD1Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC17RegExpConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
+__ZN3JSC22NativeErrorConstructorD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC18GlobalEvalFunctionD1Ev
+__ZN3JSC8JSObjectD1Ev
+__ZN3JSC9CodeBlock13unlinkCallersEv
+__ZN3WTF6VectorINS_6RefPtrIN3JSC6RegExpEEELm0EE6shrinkEm
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC12JSActivationD2Ev
+__ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC18RegExpMatchesArrayD1Ev
+__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF17TCMalloc_PageHeap3NewEm
+__ZN3JSC8JITStubs28cti_op_construct_JSConstructEPPv
__ZN3JSC8JSObject17createInheritorIDEv
-__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
-__ZNK3JSC7ForNode6isLoopEv
-__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZNK3JSC19BracketAccessorNode10isLocationEv
+__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
__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
+__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17AssignBracketNodeD0Ev
+__ZN3JSC14PostfixDotNodeD0Ev
+__ZN3JSC17ReadModifyDotNodeD0Ev
+__ZN3JSC3JIT18emit_op_put_by_valEPNS_11InstructionE
+__ZN3JSC3JIT22emitSlow_op_put_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
__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
+__ZN3JSC8JITStubs23cti_op_put_by_val_arrayEPPv
+__ZN3JSC8JITStubs13cti_op_strcatEPPv
+__ZN3JSC7UString3Rep15reserveCapacityEi
+__ZN3JSC7UString13appendNumericEi
+__ZN3JSC11concatenateEPNS_7UString3RepEi
__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
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12JSActivation14isDynamicScopeEv
+__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
+__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC8JITStubs17cti_op_put_by_valEPPv
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC8JITStubs18cti_op_is_functionEPPv
+__ZN3JSC16jsIsFunctionTypeENS_7JSValueE
+__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
+__ZN3JSC11JSImmediate8toStringENS_7JSValueE
+__ZN3JSC7UString4fromEi
+__ZN3JSC7UString3Rep11computeHashEPKti
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZN3JSC9BreakNodeD0Ev
+__ZN3JSC3JIT15emit_op_eq_nullEPNS_11InstructionE
+__ZN3JSC8JITStubs19cti_op_is_undefinedEPPv
+__ZN3JSC12JSActivation4markEv
+__ZN3JSC12DateInstanceD1Ev
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZN3JSC18EmptyStatementNodeD0Ev
+__ZN3JSC3JIT15emit_op_pre_decEPNS_11InstructionE
+__ZN3JSC3JIT19emitSlow_op_pre_decEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF13tryFastMallocEm
+__ZN3JSC8JITStubs17cti_timeout_checkEPPv
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
+__ZN3JSC8JITStubs14cti_op_pre_decEPPv
+__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
+__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
__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
+__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC10JSFunction9classInfoEv
+__ZNK3JSC21UStringSourceProvider8getRangeEii
+__ZNK3JSC7UString6substrEii
+__ZN3JSC8JITStubs26cti_op_get_by_id_self_failEPPv
+__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEm
+__ZN3JSC8JITStubs16cti_op_nstricteqEPPv
+__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_PNS_5LabelE
+__ZN3JSC9ForInNodeD0Ev
+__ZN3JSC3JIT18emit_op_next_pnameEPNS_11InstructionE
+__ZN3JSC8JITStubs17cti_op_get_pnamesEPPv
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9Structure26getEnumerablePropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayEPNS_8JSObjectE
+__ZN3JSC9Structure35getEnumerableNamesFromPropertyTableERNS_17PropertyNameArrayE
+__ZN3JSC8JITStubs17cti_op_next_pnameEPPv
+__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC22JSPropertyNameIterator10invalidateEv
+__ZN3JSC3JIT22emit_op_init_argumentsEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_create_argumentsEPNS_11InstructionE
+__ZN3JSC8JITStubs33cti_op_create_arguments_no_paramsEPPv
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC3JIT16emit_op_post_decEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_post_decEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs15cti_op_post_decEPPv
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JITStubs16cti_op_new_arrayEPPv
+__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__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
-__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
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JITStubs17cti_op_push_scopeEPPv
+__ZN3JSC8JITStubs14cti_op_resolveEPPv
+__ZN3JSC8JITStubs16cti_op_pop_scopeEPPv
+__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainENS_22AbstractMacr
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE
+__ZN3JSC3JIT19patchPutByIdReplaceEPNS_17StructureStubInfoEPNS_9StructureEmNS_22AbstractMacroAssemblerINS_12X86AssemblerEE22Proc
__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
+__ZN3JSC8JITStubs16cti_op_is_stringEPPv
+__ZN3JSC8JITStubs19cti_op_convert_thisEPPv
__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
-__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
+__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_7J
+__ZN3JSC3JIT16emit_op_post_incEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_post_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
+__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
+__ZN3JSCL21resizePropertyStorageEPNS_8JSObjectEii
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC14ExecutablePool12poolAllocateEm
+__ZN3JSC9Arguments4markEv
+__ZN3JSC22JSPropertyNameIterator4markEv
+__ZN3JSC3JIT10unlinkCallEPNS_12CallLinkInfoE
+__ZN3JSC22JSPropertyNameIteratorD1Ev
+__ZN3JSC9ArgumentsD1Ev
+__ZN3JSC9ArgumentsD2Ev
+__ZN3JSC12StringObjectD1Ev
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE15reserveCapacityEm
+__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC7JSArray9setLengthEj
+__ZN3JSC7UString6appendEPKc
+__ZN3JSC8JITStubs23cti_op_create_argumentsEPPv
+__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
+__ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode13isSimpleArrayEv
+__ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
+__ZN3JSC24ApplyFunctionCallDotNodeD0Ev
+__ZN3JSC3JIT20emit_op_load_varargsEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_call_varargsEPNS_11InstructionE
+__ZN3JSC3JIT20compileOpCallVarargsEPNS_11InstructionE
+__ZN3JSC3JIT29compileOpCallVarargsSetupArgsEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_call_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileOpCallVarargsSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs19cti_op_load_varargsEPPv
+__ZNK3JSC7JSArray9classInfoEv
+__ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+__ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC7UString4fromEd
+__ZN3WTF4dtoaEPcdiPiS1_PS0_
+__ZN3JSC8JITStubs21cti_op_put_by_id_failEPPv
__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3JSC13DeleteDotNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSC11Interpreter16cti_op_del_by_idEPvz
+__ZN3JSC13DeleteDotNodeD0Ev
+__ZN3JSC3JIT17emit_op_del_by_idEPNS_11InstructionE
+__ZN3JSC8JITStubs16cti_op_del_by_idEPPv
__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
-__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZN3JSC3JIT26emit_op_tear_off_argumentsEPNS_11InstructionE
+__ZN3JSC8JITStubs25cti_op_tear_off_argumentsEPPv
+__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
+__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13PrefixDotNodeD0Ev
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
__ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
-__ZN3WTF6VectorIN3JSC14MacroAssembler4JumpELm16EE14expandCapacityEm
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs32cti_op_get_by_id_proto_list_fullEPPv
__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
+__ZN3JSC14InstanceOfNodeD0Ev
+__ZN3JSC3JIT18emit_op_instanceofEPNS_11InstructionE
+__ZN3JSC3JIT22emitSlow_op_instanceofEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC12X86Assembler6orl_irEiNS_3X8610RegisterIDE
+__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12DateInstance9classInfoEv
__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZN3JSC3JIT18emit_op_jmp_scopesEPNS_11InstructionE
+__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_1
+__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7UString6appendEt
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7PtrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
-__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6expandEv
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
-__ZN3JSC11Interpreter19cti_op_convert_thisEPvz
-__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17PrefixBracketNodeD1Ev
-__ZN3JSC17PrefixBracketNode12releaseNodesERNS_12NodeReleaserE
-__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZNK3JSC10JSFunction9classInfoEv
-__ZN3JSC7CStringD1Ev
-__ZN3JSC6JSLock12DropAllLocksC1Eb
-__ZN3JSCL17createJSLockCountEv
-__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC9ArrayNode13isSimpleArrayEv
+__ZN3JSC8JITStubs10cti_op_mulEPPv
+__ZN3JSC8JITStubs16cti_op_is_objectEPPv
+__ZN3JSC14jsIsObjectTypeENS_7JSValueE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
+__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
+__ZNK3JSC10ScopeChain10localDepthEv
+__ZNK3JSC12JSActivation9classInfoEv
+__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IP
+__ZN3JSC13StatementNode6setLocEii
+__ZN3JSC16FunctionBodyNode14copyParametersEv
+__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
+__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3JSC9CodeBlock36hasGlobalResolveInfoAtBytecodeOffsetEj
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZN3WTF6VectorIPvLm0EE14expandCapacityEmPKS1_
+__ZN3WTF6VectorIPvLm0EE15reserveCapacityEm
+__ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
+__ZN3JSC8JITStubs16cti_op_is_numberEPPv
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12StringObject9classInfoEv
+__ZN3JSC8JITStubs28cti_op_get_by_id_string_failEPPv
+__ZN3JSC11JSImmediate9prototypeENS_7JSValueEPNS_9ExecStateE
+__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC3JIT16emit_op_neq_nullEPNS_11InstructionE
+__ZN3JSC4Yarr23RegexPatternConstructor8copyTermERNS0_11PatternTermE
+__ZL17bracketIsAnchoredPKh
+__ZL32branchFindFirstAssertedCharacterPKhb
+__ZL20branchNeedsLineStartPKhjj
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC3JIT17emit_op_jneq_nullEPNS_11InstructionE
+__ZN3JSC8JITStubs25cti_op_call_NotJSFunctionEPPv
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
+__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC23FunctionCallBracketNodeD0Ev
+__ZN3JSC20EvalFunctionCallNodeD0Ev
+__ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_call_evalEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_call_evalEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC14MacroAssembler4jumpENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelE
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString12replaceRangeEiiRKS0_
+__ZN3JSC8JITStubs17cti_op_is_booleanEPPv
+__ZN3JSC3JIT22emit_op_put_global_varEPNS_11InstructionE
+__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC4Yarr14RegexGenerator30generatePatternCharacterGreedyERNS1_19TermGenerationStateE
+__ZN3JSC8JITStubs27cti_op_get_by_id_proto_failEPPv
+__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17DeleteResolveNodeD0Ev
+__ZN3JSC3JIT20emit_op_resolve_baseEPNS_11InstructionE
+__ZN3JSC8JITStubs19cti_op_resolve_baseEPPv
+__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZN3JSC8JITStubs24cti_op_resolve_with_baseEPPv
+__ZN3JSC8JITStubs16cti_op_call_evalEPPv
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_7JSValueE
+__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
+__ZN3JSC13LiteralParser14parseStatementEv
+__ZN3JSC13LiteralParser15parseExpressionEv
+__ZN3JSC13LiteralParser10parseArrayEv
+__ZN3JSC13LiteralParser11parseObjectEv
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKti
+__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF16weakRandomNumberEv
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC4Heap15recordExtraCostEm
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3JSC9ExecState9thisValueEv
+__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC8EvalNode16generateBytecodeEPNS_14ScopeChainNodeE
+__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16
+__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZThn16_N3JSC8EvalNodeD0Ev
+__ZN3JSC8EvalNodeD0Ev
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject9classNameEv
+__ZN3JSC11JSImmediate12toThisObjectENS_7JSValueEPNS_9ExecStateE
+__ZNK3JSC6JSCell17getTruncatedInt32ERi
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSC21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
+__ZN3JSCL12getDSTOffsetEdd
+__ZN3JSC21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
+__ZN3JSCL15dateToDayInYearEiii
+__ZN3JSC8JITStubs19cti_op_to_primitiveEPPv
+__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10formatTimeERKNS_17GregorianDateTimeEb
+__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7UString13appendNumericEd
+__ZN3JSC11concatenateEPNS_7UString3RepEd
+__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE
+__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
+__ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
+__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataEPvRS2_
+_ctiVMThrowTrampoline
+__ZN3JSC8JITStubs12cti_vm_throwEPPv
+__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEjb
+__ZNK3JSC8JSObject22isNotAnObjectErrorStubEv
+__ZNK3JSC8JSObject19isWatchdogExceptionEv
+__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
+__ZN3JSC8JITStubs21cti_op_push_new_scopeEPPv
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEm
+__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3getEPS4
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3setEPS4_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS1_INS2_8EvalNodeEEEENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_
+__ZN3JSC10LessEqNodeD0Ev
+__ZN3JSC8JITStubs14cti_op_jlesseqEPPv
+__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZL18makeRightShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC14RightShiftNodeD0Ev
+__ZN3JSC3JIT14emit_op_rshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_rshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18PostfixBracketNodeD0Ev
+__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyBracketNodeD0Ev
+__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
+__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF23waitForThreadCompletionEjPPv
+__ZN3WTF15ThreadConditionD1Ev
+__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
+__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
-__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_10JSValuePtrERNS_15PutPropertySlotE
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
__ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
-__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_10JSValuePtrENS_7UStringE
+__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_7JSValueENS_7UStringE
+__ZN3JSC13ErrorInstanceD1Ev
+__ZN3JSC22JSNotAnObjectErrorStubD1Ev
+__ZN3JSC13JSNotAnObjectD1Ev
+__ZN3JSC19JSStaticScopeObjectD1Ev
+__ZN3JSC19JSStaticScopeObjectD2Ev
+__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC17DeleteBracketNodeD0Ev
+__ZN3JSC8JITStubs17cti_op_del_by_valEPPv
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
+__ZNK3JSC7UString10UTF8StringEb
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3JSC10NegateNodeD0Ev
+__ZN3JSC8JITStubs13cti_op_negateEPPv
+__ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs10cti_op_subEPPv
+__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
+__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs10cti_op_modEPPv
+__ZN3JSC8JITStubs12cti_op_jlessEPPv
+__ZL17makeLeftShiftNodePvPN3JSC14ExpressionNodeES2_b
+__ZN3JSC13LeftShiftNodeD0Ev
+__ZN3JSC3JIT14emit_op_lshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_lshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC11JITStubCall11addArgumentENS_3X8610RegisterIDE
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10BitAndNodeD0Ev
+__ZN3JSC3JIT14emit_op_bitandEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitandEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs13cti_op_bitandEPPv
+__ZN3JSC14BitwiseNotNodeD0Ev
+__ZN3JSC3JIT14emit_op_bitnotEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitnotEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC22UnsignedRightShiftNodeD0Ev
+__ZN3JSC10BitXOrNodeD0Ev
+__ZN3JSC3JIT14emit_op_bitxorEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitxorEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs14cti_op_urshiftEPPv
+__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC6JSCell18getTruncatedUInt32ERj
+__ZN3JSC3JIT13emit_op_bitorEPNS_11InstructionE
+__ZN3JSC3JIT17emitSlow_op_bitorEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs12cti_op_bitorEPPv
+__ZN3JSC9BitOrNodeD0Ev
+__ZN3JSC8JITStubs13cti_op_rshiftEPPv
+__ZN3JSC8JITStubs13cti_op_bitxorEPPv
+__ZN3JSC9parseDateERKNS_7UStringE
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEmPKS2_
+__ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
+__ZN3JSC3JIT20emit_op_resolve_skipEPNS_11InstructionE
+__ZN3JSC8JITStubs19cti_op_resolve_skipEPPv
+__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC8EvalNode4markEv
+__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
+__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
+__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
+__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
+__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
+__ZN3JSC14CaseClauseNodeD0Ev
+__ZN3JSC14ClauseListNodeD0Ev
+__ZN3JSC13CaseBlockNodeD0Ev
+__ZN3JSC10SwitchNodeD0Ev
+__ZN3JSC3JIT19emit_op_switch_charEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE17CodeLocationLabelELm0EE4growEm
+__ZN3JSC8JITStubs18cti_op_switch_charEPPv
+__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIcLm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
+__ZN3JSC7JSArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState10arrayTableEPS0_
+__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehas
+__ZN3JSC8JITStubs24cti_op_get_by_val_stringEPPv
+__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString8toDoubleEv
+__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E4findIS4_NS_22Id
+__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
+__ZN3JSCltERKNS_7UStringES2_
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
+__Z12jsRegExpFreeP8JSRegExp
+__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
+__ZN3WTF7Unicode18UTF8SequenceLengthEc
+__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
+__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16integerPartNoExpEd
+__ZN3WTF14FastMallocZone10statisticsEP14_malloc_zone_tP19malloc_statistics_t
+__ZN3JSC4Heap26protectedGlobalObjectCountEv
+__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
+__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEm
+__ZN3JSC8JITStubs14cti_op_pre_incEPPv
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
+__ZN3JSC13UnaryPlusNodeD0Ev
+__ZN3JSC3JIT19emit_op_to_jsnumberEPNS_11InstructionE
+__ZN3JSC3JIT23emitSlow_op_to_jsnumberEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JITStubs18cti_op_to_jsnumberEPPv
+__ZN3JSC6JSLock12DropAllLocksC1Eb
+__ZN3JSCL17createJSLockCountEv
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE15reserveCapacityEm
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_14OffsetLocationENS_7StrHashIS5_EENS_10HashTraitsIS5_EENS9_IS6_EEE3addEPS4_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_14OffsetLocationEENS_18PairFirstExtractorIS8_EENS_7StrHashIS5_
+__ZN3JSC3JIT21emit_op_switch_stringEPNS_11InstructionE
+__ZN3JSC8JITStubs20cti_op_switch_stringEPPv
+__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE14expandCapacityEm
+__ZN3JSC12JSGlobalData6createEb
+__ZN3JSCL13allocateBlockILNS_8HeapTypeE1EEEPNS_14CollectorBlockEv
+__ZN3JSC7JSValueC1EPNS_9ExecStateEd
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RK
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC7CStringD1Ev
+__ZN3WTF7HashMapIPvjNS_7PtrHashIS1_EEN3JSC17JSValueHashTraitsENS_10HashTraitsIjEEE3addERKS1_RKj
+__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncExprNodeEEELm0EE14shrinkCapacityEm
+__ZN3JSC14ExpressionNodeD2Ev
+__ZThn12_N3JSC11ProgramNodeD0Ev
+__ZThn12_N3JSC12FuncExprNodeD0Ev
+__ZThn12_N3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC8JITStubs16cti_op_new_arrayEPvz
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE15reserveCapacityEm
+__ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_3X8610RegisterIDES2_
+__ZN3JSC8JITStubs15cti_op_new_funcEPvz
+__ZN3JSC8JITStubs21cti_op_resolve_globalEPvz
+__ZN3JSC8JITStubs16cti_op_get_by_idEPvz
+__ZN3JSC8JITStubs31cti_op_construct_NotJSConstructEPvz
+__ZN3JSC8JITStubs16cti_op_put_by_idEPvz
+__ZN3JSC8JITStubs13cti_op_strcatEPvz
+__ZN3JSC8JITStubs19cti_op_resolve_funcEPvz
+__ZN3JSC8JITStubs23cti_vm_dontLazyLinkCallEPvz
+__ZN3JSC8JITStubs22cti_op_call_JSFunctionEPvz
+__ZN3JSC8JITStubs23cti_register_file_checkEPvz
+__ZN3JSC8JITStubs13cti_op_negateEPvz
+__ZN3JSC8JITStubs28cti_op_construct_JSConstructEPvz
+__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_5Imm
+__ZN3JSC8JITStubs23cti_op_put_by_val_arrayEPvz
+__ZN3JSC8JITStubs23cti_op_put_by_id_secondEPvz
+__ZN3JSC15AssemblerBuffer14executableCopyEPNS_14ExecutablePoolE
+__ZN3JSC12X86Assembler8sarl_i8rEiNS_3X8610RegisterIDE
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_3X8610RegisterIDEi
+__ZN3JSC8JITStubs10cti_op_mulEPvz
+__ZN3JSC12jsNumberCellEPNS_12JSGlobalDataEd
+__ZN3JSC8JITStubs10cti_op_subEPvz
+__ZN3JSC8JITStubs10cti_op_divEPvz
+__ZN3JSC8JITStubs23cti_op_get_by_id_secondEPvz
+__ZN3JSC8JITStubs19cti_vm_lazyLinkCallEPvz
+__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC8JITStubs19cti_op_convert_thisEPvz
+__ZN3JSC8JITStubs21cti_op_put_by_id_failEPvz
+__ZN3JSC8JITStubs10cti_op_addEPvz
+__ZN3JSC8JITStubs17cti_timeout_checkEPvz
+__ZN3JSC9jsBooleanEb
+__ZN3JSC9CodeBlock19isKnownNotImmediateEi
+__ZN3JSC12X86Assembler8movsd_mrEiNS_3X8610RegisterIDENS1_13XMMRegisterIDE
+__ZN3JSC8JITStubs25cti_op_call_NotJSFunctionEPvz
+__ZNK3JSC12JSNumberCell8toNumberEPNS_9ExecStateE
+__ZN3JSC8JITStubs26cti_op_get_by_id_self_failEPvz
+__ZN3JSC8JITStubs10cti_op_endEPvz
+__ZThn12_N3JSC12FuncDeclNodeD0Ev
+__ZN3JSC8JITStubs24cti_op_resolve_with_baseEPvz
+__ZN3JSC8JITStubs19cti_op_new_func_expEPvz
+__ZN3JSC8JITStubs22cti_op_push_activationEPvz
+__ZN3JSC8JITStubs17cti_op_get_by_valEPvz
+__ZN3JSC8JITStubs22cti_op_call_arityCheckEPvz
+__ZN3JSC8JITStubs11cti_op_lessEPvz
+__ZN3JSC12JSNumberCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDE
+__ZN3JSC8JITStubs27cti_op_get_by_id_proto_listEPvz
+__ZN3JSC8JITStubs12cti_op_jtrueEPvz
+__ZN3JSC8JITStubs10cti_op_modEPvz
+__ZN3JSC8JITStubs10cti_op_neqEPvz
+__ZN3JSC8JITStubs12cti_op_jlessEPvz
+__ZN3JSC8JITStubs24cti_op_get_by_id_genericEPvz
+__ZN3JSC8JITStubs14cti_op_jlesseqEPvz
+__ZN3JSC8JITStubs26cti_op_tear_off_activationEPvz
+__ZN3JSC8JITStubs21cti_op_ret_scopeChainEPvz
+__ZN3JSC8JITStubs19cti_op_to_primitiveEPvz
+__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE
+__ZN3JSC8JITStubs13cti_op_bitandEPvz
+__ZN3JSC8JITStubs13cti_op_lshiftEPvz
+__ZN3JSC8JITStubs13cti_op_bitnotEPvz
+__ZNK3JSC12JSNumberCell9toBooleanEPNS_9ExecStateE
+__ZN3JSC8JITStubs14cti_op_urshiftEPvz
+__ZNK3JSC12JSNumberCell18getTruncatedUInt32ERj
+__ZN3JSC4Yarr14RegexGenerator28generateCharacterClassSingleERNS1_19TermGenerationStateE
+__ZN3WTF15deleteAllValuesIPN3JSC4Yarr18PatternDisjunctionELm4EEEvRKNS_6VectorIT_XT0_EEE
+__ZN3JSC8JITStubs17cti_op_new_regexpEPvz
+__ZN3JSC8JITStubs12cti_op_bitorEPvz
+__ZNK3JSC12JSNumberCell17getTruncatedInt32ERi
+__ZN3JSC8JITStubs13cti_op_rshiftEPvz
+__ZN3JSC8JITStubs13cti_op_bitxorEPvz
+__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_
+__ZN3JSC8JITStubs9cti_op_eqEPvz
+__ZN3JSC8JITStubs16cti_op_call_evalEPvz
+__ZN3JSC8JITStubs19cti_op_resolve_skipEPvz
+__ZN3JSC8JITStubs17cti_op_new_objectEPvz
+__ZN3JSC8JITStubs14cti_op_resolveEPvz
+__ZN3JSC8JITStubs17cti_op_put_by_valEPvz
+__ZN3JSC8JITStubs18cti_op_switch_charEPvz
+__ZN3JSC8JITStubs28cti_op_get_by_id_string_failEPvz
+__ZThn12_N3JSC8EvalNodeD0Ev
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEm
+__ZN3JSC8JITStubs17cti_op_get_pnamesEPvz
+__ZN3JSC8JITStubs17cti_op_next_pnameEPvz
+__ZN3WTF7HashSetIPN3JSC20MarkedArgumentBufferENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findI
+__ZN3JSC8JITStubs24cti_op_get_by_val_stringEPvz
+__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE28CharacterClassParserDelegate25atomBuiltInCharacterClassENS0_23BuiltInChar
+__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSC8JITStubs18cti_op_is_functionEPvz
+__ZN3JSC8JITStubs16cti_op_is_objectEPvz
+__ZN3JSC8JITStubs16cti_op_nstricteqEPvz
+__ZN3JSC8JITStubs13cti_op_lesseqEPvz
+__ZNK3JSC12JSNumberCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC4Yarr14RegexGenerator27generateCharacterClassFixedERNS1_19TermGenerationStateE
+__ZN3JSC4Heap7destroyEv
+__ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12JSGlobalDataD2Ev
+__ZN3JSC12RegisterFileD1Ev
+__ZNK3JSC9HashTable11deleteTableEv
+__ZN3JSC5LexerD1Ev
+__ZN3JSC5LexerD2Ev
+__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_E
+__ZN3JSC17CommonIdentifiersD2Ev
+__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC4HeapD1Ev
+__ZN3JSC12SmallStringsD1Ev
+__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray3popEv
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11DoWhileNodeD0Ev
+__ZN3JSC3JIT18emit_op_switch_immEPNS_11InstructionE
+__ZN3JSC8JITStubs17cti_op_switch_immEPPv
+__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
+__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callNumberConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZN3JSC8JITStubs19cti_op_is_undefinedEPvz
+__ZN3JSC8JITStubs13cti_op_typeofEPvz
+__ZN3JSC8JITStubs33cti_op_create_arguments_no_paramsEPvz
+__ZN3JSC8JITStubs19cti_op_load_varargsEPvz
+__ZN3JSC8JITStubs10cti_op_notEPvz
+__ZN3JSC8JITStubs16cti_op_is_stringEPvz
+__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
+__ZN3JSC8JITStubs20cti_op_switch_stringEPvz
+__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JITStubs18cti_op_to_jsnumberEPvz
+__ZN3JSC8JITStubs19cti_op_loop_if_lessEPvz
+__ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9LabelNodeD0Ev
__ZNK3JSC7UString5asciiEv
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
-__ZN3WTF13tryFastCallocEmm
-__ZN3JSC13JSNotAnObjectD0Ev
-__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatERKNS_7ArgListE
+__ZN3JSC8JITStubs27cti_op_get_by_id_array_failEPvz
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiPv
+__ZN3JSC8JITStubs23cti_op_create_argumentsEPvz
+__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs25cti_op_tear_off_argumentsEPvz
+__ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3JSC7JSArray17compactForSortingEv
+__ZN3JSCL22compareNumbersForQSortEPKvS1_
+__ZN3JSC8JITStubs15cti_op_post_incEPPv
+__ZN3JSC8JITStubs24cti_op_put_by_id_genericEPvz
+__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar5EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23stringProtoFuncFontsizeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs21cti_op_loop_if_lesseqEPPv
+__ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC4Yarr17nonwordcharCreateEv
+__ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEmPKS4_
+__Z15jsc_pcre_xclassiPKh
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs27cti_op_get_by_id_array_failEPPv
+__ZNK3JSC9Arguments9classInfoEv
+__ZN3JSC9Arguments15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+__ZN3JSC19JSStaticScopeObject4markEv
+__ZN3JSC8JITStubs19cti_op_loop_if_lessEPPv
+__ZN3JSC8JITStubs16cti_op_del_by_idEPvz
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC7UString6appendEPKti
+__ZN3JSC8JITStubs17cti_op_push_scopeEPvz
+__ZN3JSC8JITStubs19cti_op_resolve_baseEPvz
+__ZN3JSC8JITStubs16cti_op_pop_scopeEPvz
+__ZN3JSC8JITStubs17cti_op_is_booleanEPvz
+__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs17cti_op_jmp_scopesEPvz
+__ZN3JSC8JITStubs9cti_op_inEPvz
+__ZN3JSC8JITStubs15cti_op_stricteqEPvz
+__ZN3JSC8JITStubs32cti_op_get_by_id_proto_list_fullEPvz
+__ZN3WTF6VectorIiLm8EE14expandCapacityEm
+__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs12cti_vm_throwEPvz
+__ZN3JSC8JITStubs21cti_op_push_new_scopeEPvz
+__ZN3JSC8JITStubs16cti_op_is_numberEPvz
+__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE
+__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC9ExecState11stringTableEPS0_
+__ZN3JSC11JSImmediate8toObjectENS_7JSValueEPNS_9ExecStateE
+__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC13BooleanObjectD1Ev
+__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj
+__ZN3JSC8JITStubs17cti_op_del_by_valEPvz
+__ZN3JSC8JITStubs27cti_op_get_by_id_proto_failEPvz
+__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
+__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC12JSNumberCell8toObjectEPNS_9ExecStateE
+__ZN3JSC15constructNumberEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC12NumberObject11getJSNumberEv
+__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12NumberObjectD1Ev
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
-__ZNK3JSC6JSCell9getStringERNS_7UStringE
-__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC12JSNumberCell11getJSNumberEv
+__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_7JSValueEjPNS_9CodeBlockE
+__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17PrefixBracketNodeD0Ev
__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_10JSValuePtrERKNS_7ArgListE
-__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_10JSValuePtrEjPNS_9CodeBlockE
-__ZN3JSC11Interpreter17cti_op_jmp_scopesEPvz
+__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateE
+__ZN3JSCL27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
+__ZN3JSC8JITStubs17cti_op_switch_immEPvz
+__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC18RegExpMatchesArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC12NumberObject9classInfoEv
+__ZN3JSC8JITStubs12cti_op_throwEPvz
+__ZN3JSCL19isNonASCIIIdentPartEi
+__ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatERKNS_7ArgListE
+__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12JSNumberCell12toThisObjectEPNS_9ExecStateE
+__ZN3JSC16ErrorConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callErrorConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
+__ZN3JSC17PrototypeFunctionD1Ev
+__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC3JIT11emit_op_jsrEPNS_11InstructionE
__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_
+__ZN3JSC3JIT12emit_op_sretEPNS_11InstructionE
__ZN3JSC6Parser7reparseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
-__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm0EEERKNS_10SourceCodeEji
+__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IPNS_12Func
__ZN3JSC8EvalNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3JSC20FixedVMPoolAllocator17coalesceFreeSpaceEv
+__ZN3WTF6VectorIPN3JSC13FreeListEntryELm0EE15reserveCapacityEm
+__ZN3JSCL35reverseSortFreeListEntriesByPointerEPKvS1_
+__ZN3JSC14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
+__ZNK3JSC7JSValue12toThisObjectEPNS_9ExecStateE
+__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8VoidNodeD0Ev
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC20MarkedArgumentBuffer9markListsERN3WTF7HashSetIPS0_NS1_7PtrHashIS3_EENS1_10HashTraitsIS3_EEEE
+__ZN3JSC7CStringaSERKS0_
+__ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv
+__ZN3JSCL33reverseSortCommonSizedAllocationsEPKvS1_
+__ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE
__ZN3JSCL30constructWithNumberConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEb
+__ZN3JSC8JITStubs12cti_op_throwEPPv
+__ZN3JSC6JSCell9getObjectEv
+__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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
+__ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL27compareByStringPairForQSortEPKvS1_
+__Z22jsc_pcre_ucp_othercasej
+__ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZN3WTF7HashMapIjN3JSC7JSValueENS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3setERKjRKS2_
+__ZN3WTF9HashTableIjSt4pairIjN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEE
+__ZN3JSC12RegisterFile21releaseExcessCapacityEv
+__ZN3JSCL20isNonASCIIIdentStartEi
+__ZN3JSC17BytecodeGenerator14emitPutByIndexEPNS_10RegisterIDEjS2_
+__ZN3JSC3JIT20emit_op_put_by_indexEPNS_11InstructionE
+__ZN3JSC8JITStubs19cti_op_put_by_indexEPPv
__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
+__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JITStubs17cti_op_jmp_scopesEPPv
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
+__ZN3JSCL17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeEPNS_7JSValueE
+_JSContextGetGlobalObject
+__ZN3JSC4Heap14registerThreadEv
+__ZN3JSC6JSLockC1EPNS_9ExecStateE
+_JSStringCreateWithUTF8CString
+__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+_JSClassCreate
__ZN13OpaqueJSClass6createEPK17JSClassDefinition
__ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_
__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
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEP19StaticFunctionEntryNS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3addERKS
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_P19StaticFunctionEntryENS_18PairFirstExtractorIS9_EENS_7StrHashIS5
+__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEEP16StaticValueEntryNS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3addERKS5_R
+_JSClassRetain
+_JSObjectMake
__ZN3JSC16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE
__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE
__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE
-__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14Pa
__ZN24OpaqueJSClassContextDataC2EP13OpaqueJSClass
-JSStringCreateWithCFString
-JSObjectSetProperty
+__ZN3JSC7UString3Rep13createCopyingEPKti
+_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
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+_JSStringRelease
__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
+__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
-JSValueIsObjectOfClass
-__ZN3JSC6JSCell9getObjectEv
+_JSObjectGetPrivate
__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classInfoEv
-JSObjectGetPrivate
-JSValueMakeString
+_JSValueMakeUndefined
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE17staticValueGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN14OpaqueJSString6createERKN3JSC7UStringE
+_JSStringCreateWithCharacters
+_JSValueMakeString
__ZNK14OpaqueJSString7ustringEv
-JSValueMakeBoolean
-JSContextGetGlobalObject
-JSStringCreateWithUTF8CString
-JSObjectGetProperty
-JSValueToObject
-JSObjectIsFunction
-JSObjectCallAsFunction
-JSValueMakeUndefined
-__ZN3JSC18JSCallbackFunctionD0Ev
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEED0Ev
+__ZN3JSC7UStringC1EPtib
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEED1Ev
+_JSClassRelease
__ZL25clearReferenceToPrototypeP13OpaqueJSValue
-JSClassRelease
-__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+_JSObjectGetProperty
+_JSValueToObject
+__ZN3JSCL22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString8toUInt32EPb
+__ZN3JSCL24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL7dateUTCEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
+__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
+_JSValueMakeBoolean
+_JSValueToNumber
+_JSStringCreateWithCFString
+__ZN3WTF13tryFastCallocEmm
+_JSValueMakeNumber
+__ZN3JSC18JSCallbackFunctionD1Ev
+_JSValueToStringCopy
+_JSStringCopyCFString
+__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE
+__ZN3JSC13ConstDeclNodeD0Ev
+__ZN3JSC18ConstStatementNodeD0Ev
+__ZN3JSC18BooleanConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL31constructWithBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC16constructBooleanEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC21DebuggerStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21DebuggerStatementNodeD0Ev
+__ZN3JSC4Yarr12RegexPattern21newlineCharacterClassEv
+__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZN3JSC12GetterSetter4markEv
+__ZN3JSC12GetterSetterD1Ev
+__ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC17NumberConstructor9classInfoEv
+__ZNK3JSC17RegExpConstructor9classInfoEv
+__ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject14isGlobalObjectEv
+_JSValueToBoolean
+__ZN3JSC8JITStubs13cti_op_lshiftEPPv
+__ZN3JSC8JITStubs13cti_op_bitnotEPPv
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE
+__ZN3WTF9ByteArray6createEm
+__ZNK3JSC6JSCell9getStringERNS_7UStringE
+__ZN3JSC3JIT12emit_op_loopEPNS_11InstructionE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArrayC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JITStubs28cti_op_get_by_val_byte_arrayEPPv
+__ZN3JSC8JITStubs28cti_op_put_by_val_byte_arrayEPPv
+__ZL30makeGetterOrSetterPropertyNodePvRKN3JSC10IdentifierES3_PNS0_13ParameterNodeEPNS0_16FunctionBodyNodeERKNS0_10SourceCodeE
+__ZN3JSC17BytecodeGenerator13emitPutGetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC17BytecodeGenerator13emitPutSetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC3JIT18emit_op_put_getterEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_put_setterEPNS_11InstructionE
+__ZN3JSC8JITStubs17cti_op_put_getterEPPv
+__ZN3JSC8JITStubs17cti_op_put_setterEPPv
+__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZNK3JSC12GetterSetter14isGetterSetterEv
+__ZNK3JSC6JSCell14isGetterSetterEv
+__ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSC5Lexer19copyCodeWithoutBOMsEv
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
+__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_7JSValueEjPNS_9CodeBlockE
+__ZN3JSC15isStrWhiteSpaceEt
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
+__ZNK3JSC22NativeErrorConstructor9classInfoEv
+__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classNameEv
+__ZN3JSC4Heap11objectCountEv
+__ZNK3JSC12SmallStrings5countEv
+__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSCL27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC9Structure22getterSetterTransitionEPS0_
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE
+__ZN3JSC12PropertySlot14functionGetterEPNS_9ExecStateERKNS_10IdentifierERKS0_
+__ZN3JSCL28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE
+__ZNK3JSC7UString6is8BitEv
+__ZN3JSC8JSObject15unwrappedObjectEv
+__ZN3JSC22NativeErrorConstructor11getCallDataERNS_8CallDataE
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE11getCallDataERNS_8CallDataE
+__ZN3JSC17BytecodeGenerator21emitComplexJumpScopesEPNS_5LabelEPNS_18ControlFlowContextES4_
__ZN3JSC23ThrowableExpressionData14emitThrowErrorERNS_17BytecodeGeneratorENS_9ErrorTypeEPKc
-__ZN3JSC17BytecodeGenerator12emitNewErrorEPNS_10RegisterIDENS_9ErrorTypeENS_10JSValuePtrE
-__ZN3JSC15AssignErrorNodeD1Ev
-__ZN3JSC15AssignErrorNode12releaseNodesERNS_12NodeReleaserE
+__ZN3JSC17BytecodeGenerator12emitNewErrorEPNS_10RegisterIDENS_9ErrorTypeENS_7JSValueE
+__ZN3JSC3JIT17emit_op_new_errorEPNS_11InstructionE
+__ZN3JSC23MacroAssemblerX86Common8branch16ENS0_9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE9BaseIndexENS4_5Imm32E
+_JSStringRetain
+__ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL20arrayProtoFuncReduceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL25arrayProtoFuncReduceRightEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC8JITStubs16cti_op_new_errorEPPv
+__ZN3JSC15AssignErrorNodeD0Ev
+__ZN3JSC17BytecodeGenerator18emitUnexpectedLoadEPNS_10RegisterIDEd
+__ZN3JSC19JSStaticScopeObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC9ExecState9dateTableEPS0_
+__ZNK3JSC15RegExpPrototype9classInfoEv
__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
+__ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23throwStackOverflowErrorEPNS_9ExecStateEPNS_12JSGlobalDataEPvRS4_
+__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSC15DeleteValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DeleteValueNodeD0Ev
+__ZN3JSC16PostfixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15PrefixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16PostfixErrorNodeD0Ev
+__ZN3JSC15PrefixErrorNodeD0Ev
+__ZN3JSC23createInvalidParamErrorEPNS_9ExecStateEPKcNS_7JSValueEjPNS_9CodeBlockE
+__ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
+__ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC4Heap24setGCProtectNeedsLockingEv
+__ZN3JSCL23callFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE8toStringEPNS_9ExecStateE
+__ZN3JSC8JITStubs17cti_op_instanceofEPPv
+__ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv
+__ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL12charSequenceEci
+__ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
+__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
+__ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
+__ZN3JSC9ExecState22regExpConstructorTableEPS0_
+__ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar9EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL22regExpConstructorInputEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL25setRegExpConstructorInputEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSCL26regExpConstructorLastMatchEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL26regExpConstructorLastParenEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL26regExpConstructorMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSC4Yarr15nondigitsCreateEv
+__ZNK3JSC19JSStaticScopeObject12toThisObjectEPNS_9ExecStateE
+__ZN3JSC12JSActivation18getArgumentsGetterEv
+__ZN3JSC12JSActivation15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_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_
+__ZN3JSC9ExecState9mathTableEPS0_
__ZN3WTF6VectorIN3JSC20FunctionRegisterInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT25emit_op_profile_will_callEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_profile_did_callEPNS_11InstructionE
+__ZN3JSC8Profiler8profilerEv
__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
+__ZN3JSC8Profiler20createCallIdentifierEPNS_12JSGlobalDataENS_7JSValueERKNS_7UStringEi
+__ZN3JSC16InternalFunction21calculatedDisplayNameEPNS_12JSGlobalDataE
__ZN3JSC11ProfileNode10insertNodeEN3WTF10PassRefPtrIS0_EE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC11ProfileNodeEEELm0EE14expandCapacityEm
__ZN3WTF6VectorINS_6RefPtrIN3JSC16ProfileGeneratorEEELm0EE14expandCapacityEm
-__ZN3WTF10RefCountedIN3JSC16ProfileGeneratorEE5derefEv
-__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_10JSValuePtrE
-__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_10JSValuePtrE
-__ZN3JSC16ProfileGenerator11willExecuteERKNS_14CallIdentifierE
-__ZN3JSC11ProfileNode11willExecuteERKNS_14CallIdentifierE
-__ZN3JSC11Interpreter24cti_op_profile_will_callEPvz
-__ZN3JSC11Interpreter23cti_op_profile_did_callEPvz
+__ZN3JSC8JITStubs23cti_op_profile_did_callEPPv
+__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_7JSValueE
__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
+__ZN3JSC8JITStubs24cti_op_profile_will_callEPPv
+__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC16ProfileGenerator11willExecuteERKNS_14CallIdentifierE
+__ZN3JSC11ProfileNode11willExecuteERKNS_14CallIdentifierE
+__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16ProfileGenerator13stopProfilingEv
+__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
+__ZNK3JSC11ProfileNode25traverseNextNodePostOrderEv
+__ZN3JSC11ProfileNode13stopProfilingEv
+__ZN3JSCeqERKNS_7UStringEPKc
+__ZN3JSC11ProfileNode11removeChildEPS0_
+__ZN3JSC11ProfileNode8addChildEN3WTF10PassRefPtrIS0_EE
+_JSValueIsObjectOfClass
+_JSObjectCallAsConstructor
+__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+_JSObjectCallAsFunction
+__ZN3JSC4Heap14primaryHeapEndEv
+__ZN3JSC4Heap16primaryHeapBeginEv
+__ZNK3JSC18JSCallbackFunction9classInfoEv
+__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateERKNS_7UStringEi
+__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateERKNS_7UStringEi
+__ZNK3JSC16ProfileGenerator5titleEv
+__ZN3JSC7ProfileD0Ev
+__ZN3WTF10RefCountedIN3JSC11ProfileNodeEE5derefEv
+__ZN3JSC4Yarr14RegexGenerator33generatePatternCharacterNonGreedyERNS1_19TermGenerationStateE
+__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
+__ZNK3JSC25InterruptedExecutionError19isWatchdogExceptionEv
+__ZN3JSC25InterruptedExecutionErrorD1Ev
__ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3JSC18RegExpMatchesArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
__ZN3WTF8CollatorC1EPKc
__ZN3WTF8Collator18setOrderLowerFirstEb
-__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
-__ZNK3JSC25InterruptedExecutionError19isWatchdogExceptionEv
+__ZN3WTF12randomNumberEv
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZNK3JSC6JSCell9getStringEv
+__ZNK3JSC12DateInstance7getTimeERdRi
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
+_JSGlobalContextCreate
+_JSGlobalContextCreateInGroup
+__ZN3JSC4Heap29makeUsableFromMultipleThreadsEv
+_JSGlobalContextRetain
+__ZN3JSC6JSLock6unlockEb
+_JSEvaluateScript
+__ZNK3JSC14JSGlobalObject17supportsProfilingEv
+_JSGlobalContextRelease
+__ZN3JSC14JSGlobalObjectD1Ev
+__ZN3JSC14JSGlobalObject18JSGlobalObjectDataD0Ev
+__ZN3JSC17FunctionPrototype11getCallDataERNS_8CallDataE
+__ZN3JSC15DateConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL8callDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13JSNotAnObject4markEv
+_JSObjectIsFunction
+__ZN3JSC4Heap17globalObjectCountEv
+__ZN3JSC4Heap20protectedObjectCountEv
+__ZN3JSC4Heap25protectedObjectTypeCountsEv
+__ZN3WTF9HashTableIPKcSt4pairIS2_jENS_18PairFirstExtractorIS4_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSA_I
+__ZN3WTF20fastMallocStatisticsEv
+__ZNK3JSC4Heap10statisticsEv
+__ZN3WTF27releaseFastMallocFreeMemoryEv
+__ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
+__ZN3JSC10JSFunction9constructEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
+__ZN3WTF7HashSetIPN3JSC14JSGlobalObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC3JIT13emit_op_debugEPNS_11InstructionE
+__ZN3JSC8JITStubs12cti_op_debugEPPv
+__ZN3JSC11Interpreter5debugEPNS_9ExecStateENS_11DebugHookIDEii
+__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
+__ZN3JSC9CodeBlock33functionRegisterForBytecodeOffsetEjRi
+_JSStringIsEqualToUTF8CString
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+_JSObjectSetPrivate
+__ZN3JSC7UString3Rep11computeHashEPKci
+__ZN3JSC16JSCallbackObjectINS_8JSObjectEE14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+_JSGarbageCollect
+__ZN3JSC4Heap6isBusyEv
+__ZN3JSCL18styleFromArgStringERKNS_7UStringEl
# JavaScriptCore - Qt4 build info
VPATH += $$PWD
-INCLUDEPATH += tmp
-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__
+CONFIG(debug, debug|release) {
+ isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}debug
+ OBJECTS_DIR = obj/debug
+} else { # Release
+ isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}release
+ OBJECTS_DIR = obj/release
+}
+
+INCLUDEPATH += $$GENERATED_SOURCES_DIR \
+ $$PWD \
+ $$PWD/parser \
+ $$PWD/bytecompiler \
+ $$PWD/debugger \
+ $$PWD/runtime \
+ $$PWD/wtf \
+ $$PWD/wtf/unicode \
+ $$PWD/interpreter \
+ $$PWD/jit \
+ $$PWD/profiler \
+ $$PWD/wrec \
+ $$PWD/yarr \
+ $$PWD/API \
+ $$PWD/.. \
+ $$PWD/ForwardingHeaders \
+ $$PWD/bytecode \
+ $$PWD/assembler \
-isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
-GENERATED_SOURCES_DIR_SLASH = $$GENERATED_SOURCES_DIR/
+DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF
+
+GENERATED_SOURCES_DIR_SLASH = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}
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
-# }
-#}
+# Default rules to turn JIT on/off
+!contains(DEFINES, ENABLE_JIT=.) {
+ isEqual(QT_ARCH,i386)|isEqual(QT_ARCH,windows) {
+ # Require gcc >= 4.1
+ CONFIG(release):linux-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) {
+ DEFINES += ENABLE_JIT=1
+ }
+ win32-msvc* {
+ DEFINES += ENABLE_JIT=1
+ }
+ }
+}
+
+# Rules when JIT enabled
+contains(DEFINES, ENABLE_JIT=1) {
+ !contains(DEFINES, ENABLE_YARR=.): DEFINES += ENABLE_YARR=1
+ !contains(DEFINES, ENABLE_YARR_JIT=.): DEFINES += ENABLE_YARR_JIT=1
+ !contains(DEFINES, ENABLE_JIT_OPTIMIZE_CALL=.): DEFINES += ENABLE_JIT_OPTIMIZE_CALL=1
+ !contains(DEFINES, ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS=.): DEFINES += ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS=1
+ !contains(DEFINES, ENABLE_JIT_OPTIMIZE_ARITHMETIC=.): DEFINES += ENABLE_JIT_OPTIMIZE_ARITHMETIC=1
+ linux-g++* {
+ !contains(DEFINES, WTF_USE_JIT_STUB_ARGUMENT_VA_LIST=.): DEFINES += WTF_USE_JIT_STUB_ARGUMENT_VA_LIST=1
+ QMAKE_CXXFLAGS += -fno-stack-protector
+ QMAKE_CFLAGS += -fno-stack-protector
+ }
+ win32-msvc* {
+ !contains(DEFINES, WTF_USE_JIT_STUB_ARGUMENT_REGISTER=.): DEFINES += WTF_USE_JIT_STUB_ARGUMENT_REGISTER=1
+ }
+}
include(pcre/pcre.pri)
LUT_FILES += \
runtime/DatePrototype.cpp \
+ runtime/JSONObject.cpp \
runtime/NumberConstructor.cpp \
runtime/StringPrototype.cpp \
runtime/ArrayPrototype.cpp \
wtf/MainThread.cpp \
wtf/RandomNumber.cpp \
wtf/RefCountedLeakCounter.cpp \
+ wtf/TypeTraits.cpp \
wtf/unicode/CollatorDefault.cpp \
wtf/unicode/icu/CollatorICU.cpp \
wtf/unicode/UTF8.cpp \
runtime/JSVariableObject.cpp \
runtime/JSActivation.cpp \
runtime/JSNotAnObject.cpp \
+ runtime/JSONObject.cpp \
+ runtime/LiteralParser.cpp \
+ runtime/TimeoutChecker.cpp \
bytecode/CodeBlock.cpp \
bytecode/StructureStubInfo.cpp \
bytecode/JumpTable.cpp \
jit/JIT.cpp \
jit/JITCall.cpp \
jit/JITArithmetic.cpp \
+ jit/JITOpcodes.cpp \
jit/JITPropertyAccess.cpp \
jit/ExecutableAllocator.cpp \
+ jit/JITStubs.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 \
+ yarr/RegexCompiler.cpp \
+ yarr/RegexInterpreter.cpp \
+ yarr/RegexJIT.cpp \
interpreter/RegisterFile.cpp
win32-*: SOURCES += jit/ExecutableAllocatorWin.cpp
runtime/ConstructData.cpp \
wtf/CurrentTime.cpp \
runtime/DateConstructor.cpp \
+ runtime/DateConversion.cpp \
runtime/DateInstance.cpp \
- runtime/DateMath.cpp \
runtime/DatePrototype.cpp \
debugger/Debugger.cpp \
debugger/DebuggerCallFrame.cpp \
runtime/InternalFunction.cpp \
runtime/Completion.cpp \
runtime/JSArray.cpp \
+ runtime/JSAPIValueWrapper.cpp \
runtime/JSByteArray.cpp \
runtime/JSCell.cpp \
runtime/JSFunction.cpp \
runtime/ObjectPrototype.cpp \
runtime/Operations.cpp \
parser/Parser.cpp \
+ parser/ParserArena.cpp \
runtime/PropertyNameArray.cpp \
runtime/PropertySlot.cpp \
runtime/PrototypeFunction.cpp \
profiler/ProfileNode.cpp \
profiler/Profiler.cpp \
profiler/TreeProfile.cpp \
+ wtf/DateMath.cpp \
wtf/FastMalloc.cpp \
wtf/Threading.cpp \
- wtf/ThreadingQt.cpp \
wtf/qt/MainThreadQt.cpp
+!contains(DEFINES, ENABLE_SINGLE_THREADED=1) {
+ SOURCES += wtf/qt/ThreadingQt.cpp
+} else {
+ DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0
+ SOURCES += wtf/ThreadingNone.cpp
+}
+
# GENERATOR 1-A: LUT creator
-lut.output = $$GENERATED_SOURCES_DIR/${QMAKE_FILE_BASE}.lut.h
+lut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.lut.h
lut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
lut.depend = ${QMAKE_FILE_NAME}
lut.input = LUT_FILES
addExtraCompiler(lut)
# GENERATOR 1-B: particular LUT creator (for 1 file only)
-keywordlut.output = $$GENERATED_SOURCES_DIR/Lexer.lut.h
+keywordlut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}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
addExtraCompiler(keywordlut)
# GENERATOR 2: bison grammar
-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.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.cpp
+jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.h $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.h
jscbison.depend = ${QMAKE_FILE_NAME}
jscbison.input = JSCBISON
jscbison.variable_out = GENERATED_SOURCES
}
isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
-GENERATED_SOURCES_DIR_SLASH = $$GENERATED_SOURCES_DIR/
-win32-*: GENERATED_SOURCES_DIR_SLASH ~= s|/|\|
+GENERATED_SOURCES_DIR_SLASH = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}
INCLUDEPATH += $$GENERATED_SOURCES_DIR
!CONFIG(QTDIR_build) {
- OBJECTS_DIR = tmp
+ CONFIG(debug, debug|release) {
+ OBJECTS_DIR = obj/debug
+ } else { # Release
+ OBJECTS_DIR = obj/release
+ }
}
include($$OUTPUT_DIR/config.pri)
QMAKE_EXTRA_TARGETS += generated_files
-qt-port: lessThan(QT_MINOR_VERSION, 4) {
+lessThan(QT_MINOR_VERSION, 4) {
DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
}
+++ /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"())
parser/Lexer.cpp
parser/Nodes.cpp
parser/Parser.cpp
+ parser/ParserArena.cpp
</set>
<set append="1" var="JSCORE_PROFILER_SOURCES">
profiler/HeavyProfile.cpp
runtime/CommonIdentifiers.cpp
runtime/ConstructData.cpp
runtime/DateConstructor.cpp
+ runtime/DateConversion.cpp
runtime/DateInstance.cpp
- runtime/DateMath.cpp
runtime/DatePrototype.cpp
runtime/Error.cpp
runtime/ErrorConstructor.cpp
runtime/JSNotAnObject.cpp
runtime/JSNumberCell.cpp
runtime/JSObject.cpp
+ runtime/JSONObject.cpp
runtime/JSPropertyNameIterator.cpp
runtime/JSStaticScopeObject.cpp
runtime/JSString.cpp
runtime/JSValue.cpp
runtime/JSVariableObject.cpp
runtime/JSWrapperObject.cpp
+ runtime/LiteralParser.cpp
runtime/Lookup.cpp
runtime/MathObject.cpp
runtime/NativeErrorConstructor.cpp
bytecode/StructureStubInfo.cpp
bytecode/JumpTable.cpp
runtime/ExceptionHelpers.cpp
+ runtime/TimeoutChecker.cpp
interpreter/Interpreter.cpp
bytecode/Opcode.cpp
bytecode/SamplingTool.cpp
interpreter/RegisterFile.cpp
+ jit/ExecutableAllocator.cpp
+ </set>
+ <set append="1" var="JSCORE_VM_SOURCES_WIN">
+ jit/ExecutableAllocatorWin.cpp
+ </set>
+ <set append="1" var="JSCORE_VM_SOURCES_POSIX">
+ jit/ExecutableAllocatorPosix.cpp
</set>
<set append="1" var="JSCORE_WTF_SOURCES">
wtf/Assertions.cpp
wtf/ByteArray.cpp
wtf/CurrentTime.cpp
+ wtf/DateMath.cpp
wtf/FastMalloc.cpp
wtf/HashTable.cpp
wtf/MainThread.cpp
wtf/TCSystemAlloc.cpp
wtf/Threading.cpp
wtf/ThreadingNone.cpp
+ wtf/TypeTraits.cpp
wtf/wx/MainThreadWx.cpp
wtf/unicode/CollatorDefault.cpp
wtf/unicode/icu/CollatorICU.cpp
+++ /dev/null
-SConscript(['JavaScriptCore.scons'])
--- /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 ARMAssembler_h
+#define ARMAssembler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && PLATFORM_ARM_ARCH(7)
+
+#include "AssemblerBuffer.h"
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+#include <stdint.h>
+
+namespace JSC {
+
+namespace ARM {
+ typedef enum {
+ r0,
+ r1,
+ r2,
+ r3,
+ r4,
+ r5,
+ r6,
+ r7, wr = r7, // thumb work register
+ r8,
+ r9, sb = r9, // static base
+ r10, sl = r10, // stack limit
+ r11, fp = r11, // frame pointer
+ r12, ip = r12,
+ r13, sp = r13,
+ r14, lr = r14,
+ r15, pc = r15,
+ } RegisterID;
+
+ // s0 == d0 == q0
+ // s4 == d2 == q1
+ // etc
+ typedef enum {
+ s0 = 0,
+ s1 = 1,
+ s2 = 2,
+ s3 = 3,
+ s4 = 4,
+ s5 = 5,
+ s6 = 6,
+ s7 = 7,
+ s8 = 8,
+ s9 = 9,
+ s10 = 10,
+ s11 = 11,
+ s12 = 12,
+ s13 = 13,
+ s14 = 14,
+ s15 = 15,
+ s16 = 16,
+ s17 = 17,
+ s18 = 18,
+ s19 = 19,
+ s20 = 20,
+ s21 = 21,
+ s22 = 22,
+ s23 = 23,
+ s24 = 24,
+ s25 = 25,
+ s26 = 26,
+ s27 = 27,
+ s28 = 28,
+ s29 = 29,
+ s30 = 30,
+ s31 = 31,
+ d0 = 0 << 1,
+ d1 = 1 << 1,
+ d2 = 2 << 1,
+ d3 = 3 << 1,
+ d4 = 4 << 1,
+ d5 = 5 << 1,
+ d6 = 6 << 1,
+ d7 = 7 << 1,
+ d8 = 8 << 1,
+ d9 = 9 << 1,
+ d10 = 10 << 1,
+ d11 = 11 << 1,
+ d12 = 12 << 1,
+ d13 = 13 << 1,
+ d14 = 14 << 1,
+ d15 = 15 << 1,
+ d16 = 16 << 1,
+ d17 = 17 << 1,
+ d18 = 18 << 1,
+ d19 = 19 << 1,
+ d20 = 20 << 1,
+ d21 = 21 << 1,
+ d22 = 22 << 1,
+ d23 = 23 << 1,
+ d24 = 24 << 1,
+ d25 = 25 << 1,
+ d26 = 26 << 1,
+ d27 = 27 << 1,
+ d28 = 28 << 1,
+ d29 = 29 << 1,
+ d30 = 30 << 1,
+ d31 = 31 << 1,
+ q0 = 0 << 2,
+ q1 = 1 << 2,
+ q2 = 2 << 2,
+ q3 = 3 << 2,
+ q4 = 4 << 2,
+ q5 = 5 << 2,
+ q6 = 6 << 2,
+ q7 = 7 << 2,
+ q8 = 8 << 2,
+ q9 = 9 << 2,
+ q10 = 10 << 2,
+ q11 = 11 << 2,
+ q12 = 12 << 2,
+ q13 = 13 << 2,
+ q14 = 14 << 2,
+ q15 = 15 << 2,
+ q16 = 16 << 2,
+ q17 = 17 << 2,
+ q18 = 18 << 2,
+ q19 = 19 << 2,
+ q20 = 20 << 2,
+ q21 = 21 << 2,
+ q22 = 22 << 2,
+ q23 = 23 << 2,
+ q24 = 24 << 2,
+ q25 = 25 << 2,
+ q26 = 26 << 2,
+ q27 = 27 << 2,
+ q28 = 28 << 2,
+ q29 = 29 << 2,
+ q30 = 30 << 2,
+ q31 = 31 << 2,
+ } FPRegisterID;
+}
+
+class ARMv7Assembler;
+class ARMThumbImmediate {
+ friend class ARMv7Assembler;
+
+ typedef uint8_t ThumbImmediateType;
+ static const ThumbImmediateType TypeInvalid = 0;
+ static const ThumbImmediateType TypeEncoded = 1;
+ static const ThumbImmediateType TypeUInt16 = 2;
+
+ typedef union {
+ int16_t asInt;
+ struct {
+ unsigned imm8 : 8;
+ unsigned imm3 : 3;
+ unsigned i : 1;
+ unsigned imm4 : 4;
+ };
+ // If this is an encoded immediate, then it may describe a shift, or a pattern.
+ struct {
+ unsigned shiftValue7 : 7;
+ unsigned shiftAmount : 5;
+ };
+ struct {
+ unsigned immediate : 8;
+ unsigned pattern : 4;
+ };
+ } ThumbImmediateValue;
+
+ // byte0 contains least significant bit; not using an array to make client code endian agnostic.
+ typedef union {
+ int32_t asInt;
+ struct {
+ uint8_t byte0;
+ uint8_t byte1;
+ uint8_t byte2;
+ uint8_t byte3;
+ };
+ } PatternBytes;
+
+ ALWAYS_INLINE static int32_t countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
+ {
+ if (value & ~((1<<N)-1)) /* check for any of the top N bits (of 2N bits) are set */ \
+ value >>= N; /* if any were set, lose the bottom N */ \
+ else /* if none of the top N bits are set, */ \
+ zeros += N; /* then we have identified N leading zeros */
+ }
+
+ static int32_t countLeadingZeros(uint32_t value)
+ {
+ if (!value)
+ return 32;
+
+ int32_t zeros = 0;
+ countLeadingZerosPartial(value, zeros, 16);
+ countLeadingZerosPartial(value, zeros, 8);
+ countLeadingZerosPartial(value, zeros, 4);
+ countLeadingZerosPartial(value, zeros, 2);
+ countLeadingZerosPartial(value, zeros, 1);
+ return zeros;
+ }
+
+ ARMThumbImmediate()
+ : m_type(TypeInvalid)
+ {
+ m_value.asInt = 0;
+ }
+
+ ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
+ : m_type(type)
+ , m_value(value)
+ {
+ }
+
+ ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
+ : m_type(TypeUInt16)
+ {
+ m_value.asInt = value;
+ }
+
+public:
+ static ARMThumbImmediate makeEncodedImm(uint32_t value)
+ {
+ ThumbImmediateValue encoding;
+ encoding.asInt = 0;
+
+ // okay, these are easy.
+ if (value < 256) {
+ encoding.immediate = value;
+ encoding.pattern = 0;
+ return ARMThumbImmediate(TypeEncoded, encoding);
+ }
+
+ int32_t leadingZeros = countLeadingZeros(value);
+ // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
+ ASSERT(leadingZeros < 24);
+
+ // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
+ // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
+ // zero. count(B) == 8, so the count of bits to be checked is 24 - count(Z).
+ int32_t rightShiftAmount = 24 - leadingZeros;
+ if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
+ // Shift the value down to the low byte position. The assign to
+ // shiftValue7 drops the implicit top bit.
+ encoding.shiftValue7 = value >> rightShiftAmount;
+ // The endoded shift amount is the magnitude of a right rotate.
+ encoding.shiftAmount = 8 + leadingZeros;
+ return ARMThumbImmediate(TypeEncoded, encoding);
+ }
+
+ PatternBytes bytes;
+ bytes.asInt = value;
+
+ if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
+ encoding.immediate = bytes.byte0;
+ encoding.pattern = 3;
+ return ARMThumbImmediate(TypeEncoded, encoding);
+ }
+
+ if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
+ encoding.immediate = bytes.byte0;
+ encoding.pattern = 1;
+ return ARMThumbImmediate(TypeEncoded, encoding);
+ }
+
+ if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
+ encoding.immediate = bytes.byte0;
+ encoding.pattern = 2;
+ return ARMThumbImmediate(TypeEncoded, encoding);
+ }
+
+ return ARMThumbImmediate();
+ }
+
+ static ARMThumbImmediate makeUInt12(int32_t value)
+ {
+ return (!(value & 0xfffff000))
+ ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
+ : ARMThumbImmediate();
+ }
+
+ static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
+ {
+ // If this is not a 12-bit unsigned it, try making an encoded immediate.
+ return (!(value & 0xfffff000))
+ ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
+ : makeEncodedImm(value);
+ }
+
+ // The 'make' methods, above, return a !isValid() value if the argument
+ // cannot be represented as the requested type. This methods is called
+ // 'get' since the argument can always be represented.
+ static ARMThumbImmediate makeUInt16(uint16_t value)
+ {
+ return ARMThumbImmediate(TypeUInt16, value);
+ }
+
+ bool isValid()
+ {
+ return m_type != TypeInvalid;
+ }
+
+ // These methods rely on the format of encoded byte values.
+ bool isUInt3() { return !(m_value.asInt & 0xfff8); }
+ bool isUInt4() { return !(m_value.asInt & 0xfff0); }
+ bool isUInt5() { return !(m_value.asInt & 0xffe0); }
+ bool isUInt6() { return !(m_value.asInt & 0xffc0); }
+ bool isUInt7() { return !(m_value.asInt & 0xff80); }
+ bool isUInt8() { return !(m_value.asInt & 0xff00); }
+ bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
+ bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
+ bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
+ bool isUInt16() { return m_type == TypeUInt16; }
+ uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
+ uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
+ uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
+ uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
+ uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
+ uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
+ uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
+ uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
+ uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
+ uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
+
+ bool isEncodedImm() { return m_type == TypeEncoded; }
+
+private:
+ ThumbImmediateType m_type;
+ ThumbImmediateValue m_value;
+};
+
+
+typedef enum {
+ SRType_LSL,
+ SRType_LSR,
+ SRType_ASR,
+ SRType_ROR,
+
+ SRType_RRX = SRType_ROR
+} ARMShiftType;
+
+class ARMv7Assembler;
+class ShiftTypeAndAmount {
+ friend class ARMv7Assembler;
+
+public:
+ ShiftTypeAndAmount()
+ {
+ m_u.type = (ARMShiftType)0;
+ m_u.amount = 0;
+ }
+
+ ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
+ {
+ m_u.type = type;
+ m_u.amount = amount & 31;
+ }
+
+ unsigned lo4() { return m_u.lo4; }
+ unsigned hi4() { return m_u.hi4; }
+
+private:
+ union {
+ struct {
+ unsigned lo4 : 4;
+ unsigned hi4 : 4;
+ };
+ struct {
+ unsigned type : 2;
+ unsigned amount : 5;
+ };
+ } m_u;
+};
+
+
+/*
+Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
+instructions supported by ARMv7-M are as follows:
+• use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction
+• use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction
+• use of the SP as <Rm> in a 16-bit CMP (register) instruction
+• use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC.
+• use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base
+register writeback
+*/
+
+class ARMv7Assembler {
+public:
+ typedef ARM::RegisterID RegisterID;
+ typedef ARM::FPRegisterID FPRegisterID;
+
+ // (HS, LO, HI, LS) -> (AE, B, A, BE)
+ // (VS, VC) -> (O, NO)
+ typedef enum {
+ ConditionEQ,
+ ConditionNE,
+ ConditionHS,
+ ConditionLO,
+ ConditionMI,
+ ConditionPL,
+ ConditionVS,
+ ConditionVC,
+ ConditionHI,
+ ConditionLS,
+ ConditionGE,
+ ConditionLT,
+ ConditionGT,
+ ConditionLE,
+ ConditionAL,
+
+ ConditionCS = ConditionHS,
+ ConditionCC = ConditionLO,
+ } Condition;
+
+ class JmpSrc {
+ friend class ARMv7Assembler;
+ friend class ARMInstructionFormatter;
+ public:
+ JmpSrc()
+ : m_offset(-1)
+ {
+ }
+
+ private:
+ JmpSrc(int offset)
+ : m_offset(offset)
+ {
+ }
+
+ int m_offset;
+ };
+
+ class JmpDst {
+ friend class ARMv7Assembler;
+ friend class ARMInstructionFormatter;
+ public:
+ JmpDst()
+ : m_offset(-1)
+ , m_used(false)
+ {
+ }
+
+ bool isUsed() const { return m_used; }
+ void used() { m_used = true; }
+ private:
+ JmpDst(int offset)
+ : m_offset(offset)
+ , m_used(false)
+ {
+ ASSERT(m_offset == offset);
+ }
+
+ int m_offset : 31;
+ int m_used : 1;
+ };
+
+private:
+
+ // ARMv7, Appx-A.6.3
+ bool BadReg(RegisterID reg)
+ {
+ return (reg == ARM::sp) || (reg == ARM::pc);
+ }
+
+ bool isSingleRegister(FPRegisterID reg)
+ {
+ // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
+ return !(reg & ~31);
+ }
+
+ bool isDoubleRegister(FPRegisterID reg)
+ {
+ // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
+ return !(reg & ~(31 << 1));
+ }
+
+ bool isQuadRegister(FPRegisterID reg)
+ {
+ return !(reg & ~(31 << 2));
+ }
+
+ uint32_t singleRegisterNum(FPRegisterID reg)
+ {
+ ASSERT(isSingleRegister(reg));
+ return reg;
+ }
+
+ uint32_t doubleRegisterNum(FPRegisterID reg)
+ {
+ ASSERT(isDoubleRegister(reg));
+ return reg >> 1;
+ }
+
+ uint32_t quadRegisterNum(FPRegisterID reg)
+ {
+ ASSERT(isQuadRegister(reg));
+ return reg >> 2;
+ }
+
+ uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift)
+ {
+ uint32_t rdNum = singleRegisterNum(rd);
+ uint32_t rdMask = (rdNum >> 1) << highBitsShift;
+ if (rdNum & 1)
+ rdMask |= 1 << lowBitShift;
+ return rdMask;
+ }
+
+ uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift)
+ {
+ uint32_t rdNum = doubleRegisterNum(rd);
+ uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
+ if (rdNum & 16)
+ rdMask |= 1 << highBitShift;
+ return rdMask;
+ }
+
+ typedef enum {
+ OP_ADD_reg_T1 = 0x1800,
+ OP_ADD_S_reg_T1 = 0x1800,
+ OP_SUB_reg_T1 = 0x1A00,
+ OP_SUB_S_reg_T1 = 0x1A00,
+ OP_ADD_imm_T1 = 0x1C00,
+ OP_ADD_S_imm_T1 = 0x1C00,
+ OP_SUB_imm_T1 = 0x1E00,
+ OP_SUB_S_imm_T1 = 0x1E00,
+ OP_MOV_imm_T1 = 0x2000,
+ OP_CMP_imm_T1 = 0x2800,
+ OP_ADD_imm_T2 = 0x3000,
+ OP_ADD_S_imm_T2 = 0x3000,
+ OP_SUB_imm_T2 = 0x3800,
+ OP_SUB_S_imm_T2 = 0x3800,
+ OP_AND_reg_T1 = 0x4000,
+ OP_EOR_reg_T1 = 0x4040,
+ OP_TST_reg_T1 = 0x4200,
+ OP_CMP_reg_T1 = 0x4280,
+ OP_ORR_reg_T1 = 0x4300,
+ OP_MVN_reg_T1 = 0x43C0,
+ OP_ADD_reg_T2 = 0x4400,
+ OP_MOV_reg_T1 = 0x4600,
+ OP_BLX = 0x4700,
+ OP_BX = 0x4700,
+ OP_LDRH_reg_T1 = 0x5A00,
+ OP_STR_reg_T1 = 0x5000,
+ OP_LDR_reg_T1 = 0x5800,
+ OP_STR_imm_T1 = 0x6000,
+ OP_LDR_imm_T1 = 0x6800,
+ OP_LDRH_imm_T1 = 0x8800,
+ OP_STR_imm_T2 = 0x9000,
+ OP_LDR_imm_T2 = 0x9800,
+ OP_ADD_SP_imm_T1 = 0xA800,
+ OP_ADD_SP_imm_T2 = 0xB000,
+ OP_SUB_SP_imm_T1 = 0xB080,
+ OP_BKPT = 0xBE00,
+ OP_IT = 0xBF00,
+ } OpcodeID;
+
+ typedef enum {
+ OP_AND_reg_T2 = 0xEA00,
+ OP_TST_reg_T2 = 0xEA10,
+ OP_ORR_reg_T2 = 0xEA40,
+ OP_ASR_imm_T1 = 0xEA4F,
+ OP_LSL_imm_T1 = 0xEA4F,
+ OP_LSR_imm_T1 = 0xEA4F,
+ OP_ROR_imm_T1 = 0xEA4F,
+ OP_MVN_reg_T2 = 0xEA6F,
+ OP_EOR_reg_T2 = 0xEA80,
+ OP_ADD_reg_T3 = 0xEB00,
+ OP_ADD_S_reg_T3 = 0xEB10,
+ OP_SUB_reg_T2 = 0xEBA0,
+ OP_SUB_S_reg_T2 = 0xEBB0,
+ OP_CMP_reg_T2 = 0xEBB0,
+ OP_B_T4a = 0xF000,
+ OP_AND_imm_T1 = 0xF000,
+ OP_TST_imm = 0xF010,
+ OP_ORR_imm_T1 = 0xF040,
+ OP_MOV_imm_T2 = 0xF040,
+ OP_MVN_imm = 0xF060,
+ OP_EOR_imm_T1 = 0xF080,
+ OP_ADD_imm_T3 = 0xF100,
+ OP_ADD_S_imm_T3 = 0xF110,
+ OP_CMN_imm = 0xF110,
+ OP_SUB_imm_T3 = 0xF1A0,
+ OP_SUB_S_imm_T3 = 0xF1B0,
+ OP_CMP_imm_T2 = 0xF1B0,
+ OP_ADD_imm_T4 = 0xF200,
+ OP_MOV_imm_T3 = 0xF240,
+ OP_SUB_imm_T4 = 0xF2A0,
+ OP_MOVT = 0xF2C0,
+ OP_LDRH_reg_T2 = 0xF830,
+ OP_LDRH_imm_T3 = 0xF830,
+ OP_STR_imm_T4 = 0xF840,
+ OP_STR_reg_T2 = 0xF840,
+ OP_LDR_imm_T4 = 0xF850,
+ OP_LDR_reg_T2 = 0xF850,
+ OP_LDRH_imm_T2 = 0xF8B0,
+ OP_STR_imm_T3 = 0xF8C0,
+ OP_LDR_imm_T3 = 0xF8D0,
+ OP_LSL_reg_T2 = 0xFA00,
+ OP_LSR_reg_T2 = 0xFA20,
+ OP_ASR_reg_T2 = 0xFA40,
+ OP_ROR_reg_T2 = 0xFA60,
+ OP_SMULL_T1 = 0xFB80,
+ } OpcodeID1;
+
+ typedef enum {
+ OP_B_T4b = 0x9000,
+ } OpcodeID2;
+
+ struct FourFours {
+ FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
+ {
+ m_u.f0 = f0;
+ m_u.f1 = f1;
+ m_u.f2 = f2;
+ m_u.f3 = f3;
+ }
+
+ union {
+ unsigned value;
+ struct {
+ unsigned f0 : 4;
+ unsigned f1 : 4;
+ unsigned f2 : 4;
+ unsigned f3 : 4;
+ };
+ } m_u;
+ };
+
+ class ARMInstructionFormatter;
+
+ // false means else!
+ bool ifThenElseConditionBit(Condition condition, bool isIf)
+ {
+ return isIf ? (condition & 1) : !(condition & 1);
+ }
+ uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
+ {
+ int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
+ | (ifThenElseConditionBit(condition, inst3if) << 2)
+ | (ifThenElseConditionBit(condition, inst4if) << 1)
+ | 1;
+ ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
+ return (condition << 4) | mask;
+ }
+ uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
+ {
+ int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
+ | (ifThenElseConditionBit(condition, inst3if) << 2)
+ | 2;
+ ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
+ return (condition << 4) | mask;
+ }
+ uint8_t ifThenElse(Condition condition, bool inst2if)
+ {
+ int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
+ | 4;
+ ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
+ return (condition << 4) | mask;
+ }
+
+ uint8_t ifThenElse(Condition condition)
+ {
+ int mask = 8;
+ ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
+ return (condition << 4) | mask;
+ }
+
+public:
+
+ void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ // Rd can only be SP if Rn is also SP.
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isValid());
+
+ if (rn == ARM::sp) {
+ if (!(rd & 8) && imm.isUInt10()) {
+ m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
+ return;
+ } else if ((rd == ARM::sp) && imm.isUInt9()) {
+ m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
+ return;
+ }
+ } else if (!((rd | rn) & 8)) {
+ if (imm.isUInt3()) {
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
+ return;
+ } else if ((rd == rn) && imm.isUInt8()) {
+ m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
+ return;
+ }
+ }
+
+ if (imm.isEncodedImm())
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
+ else {
+ ASSERT(imm.isUInt12());
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
+ }
+ }
+
+ void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ // NOTE: In an IT block, add doesn't modify the flags register.
+ void add(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if (rd == rn)
+ m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
+ else if (rd == rm)
+ m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
+ else if (!((rd | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
+ else
+ add(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ // Not allowed in an IT (if then) block.
+ void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ // Rd can only be SP if Rn is also SP.
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isEncodedImm());
+
+ if (!((rd | rn) & 8)) {
+ if (imm.isUInt3()) {
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
+ return;
+ } else if ((rd == rn) && imm.isUInt8()) {
+ m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8());
+ return;
+ }
+ }
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
+ }
+
+ // Not allowed in an IT (if then) block?
+ void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ // Not allowed in an IT (if then) block.
+ void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if (!((rd | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd);
+ else
+ add_S(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(imm.isEncodedImm());
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
+ }
+
+ void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if ((rd == rn) && !((rd | rm) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
+ else if ((rd == rm) && !((rd | rn) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
+ else
+ ARM_and(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rm));
+ ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
+ m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void asr(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
+ }
+
+ // Only allowed in IT (if then) block if last instruction.
+ JmpSrc b()
+ {
+ m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
+ return JmpSrc(m_formatter.size());
+ }
+
+ // Only allowed in IT (if then) block if last instruction.
+ JmpSrc blx(RegisterID rm)
+ {
+ ASSERT(rm != ARM::pc);
+ m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
+ return JmpSrc(m_formatter.size());
+ }
+
+ // Only allowed in IT (if then) block if last instruction.
+ JmpSrc bx(RegisterID rm)
+ {
+ m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
+ return JmpSrc(m_formatter.size());
+ }
+
+ void bkpt(uint8_t imm=0)
+ {
+ m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
+ }
+
+ void cmn(RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isEncodedImm());
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
+ }
+
+ void cmp(RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isEncodedImm());
+
+ if (!(rn & 8) && imm.isUInt8())
+ m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
+ else
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
+ }
+
+ void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
+ }
+
+ void cmp(RegisterID rn, RegisterID rm)
+ {
+ if ((rn | rm) & 8)
+ cmp(rn, rm, ShiftTypeAndAmount());
+ else
+ m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
+ }
+
+ // xor is not spelled with an 'e'. :-(
+ void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(imm.isEncodedImm());
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
+ }
+
+ // xor is not spelled with an 'e'. :-(
+ void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ // xor is not spelled with an 'e'. :-(
+ void eor(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if ((rd == rn) && !((rd | rm) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
+ else if ((rd == rm) && !((rd | rn) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
+ else
+ eor(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ void it(Condition cond)
+ {
+ m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
+ }
+
+ void it(Condition cond, bool inst2if)
+ {
+ m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
+ }
+
+ void it(Condition cond, bool inst2if, bool inst3if)
+ {
+ m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
+ }
+
+ void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
+ {
+ m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
+ }
+
+ // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+ void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(rn != ARM::pc); // LDR (literal)
+ ASSERT(imm.isUInt12());
+
+ if (!((rt | rn) & 8) && imm.isUInt7())
+ m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
+ else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
+ m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
+ else
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
+ }
+
+ // If index is set, this is a regular offset or a pre-indexed load;
+ // if index is not set then is is a post-index load.
+ //
+ // If wback is set rn is updated - this is a pre or post index load,
+ // if wback is not set this is a regular offset memory access.
+ //
+ // (-255 <= offset <= 255)
+ // _reg = REG[rn]
+ // _tmp = _reg + offset
+ // MEM[index ? _tmp : _reg] = REG[rt]
+ // if (wback) REG[rn] = _tmp
+ void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+ {
+ ASSERT(rt != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(index || wback);
+ ASSERT(!wback | (rt != rn));
+
+ bool add = true;
+ if (offset < 0) {
+ add = false;
+ offset = -offset;
+ }
+ ASSERT((offset & ~0xff) == 0);
+
+ offset |= (wback << 8);
+ offset |= (add << 9);
+ offset |= (index << 10);
+ offset |= (1 << 11);
+
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
+ }
+
+ // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+ void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+ {
+ ASSERT(rn != ARM::pc); // LDR (literal)
+ ASSERT(!BadReg(rm));
+ ASSERT(shift <= 3);
+
+ if (!shift && !((rt | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
+ else
+ m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
+ }
+
+ // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+ void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(rn != ARM::pc); // LDR (literal)
+ ASSERT(imm.isUInt12());
+
+ if (!((rt | rn) & 8) && imm.isUInt6())
+ m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
+ else
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
+ }
+
+ // If index is set, this is a regular offset or a pre-indexed load;
+ // if index is not set then is is a post-index load.
+ //
+ // If wback is set rn is updated - this is a pre or post index load,
+ // if wback is not set this is a regular offset memory access.
+ //
+ // (-255 <= offset <= 255)
+ // _reg = REG[rn]
+ // _tmp = _reg + offset
+ // MEM[index ? _tmp : _reg] = REG[rt]
+ // if (wback) REG[rn] = _tmp
+ void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+ {
+ ASSERT(rt != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(index || wback);
+ ASSERT(!wback | (rt != rn));
+
+ bool add = true;
+ if (offset < 0) {
+ add = false;
+ offset = -offset;
+ }
+ ASSERT((offset & ~0xff) == 0);
+
+ offset |= (wback << 8);
+ offset |= (add << 9);
+ offset |= (index << 10);
+ offset |= (1 << 11);
+
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
+ }
+
+ void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+ {
+ ASSERT(!BadReg(rt)); // Memory hint
+ ASSERT(rn != ARM::pc); // LDRH (literal)
+ ASSERT(!BadReg(rm));
+ ASSERT(shift <= 3);
+
+ if (!shift && !((rt | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
+ else
+ m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
+ }
+
+ void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rm));
+ ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
+ m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
+ }
+
+ void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rm));
+ ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
+ m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
+ }
+
+ void movT3(RegisterID rd, ARMThumbImmediate imm)
+ {
+ ASSERT(imm.isValid());
+ ASSERT(!imm.isEncodedImm());
+ ASSERT(!BadReg(rd));
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
+ }
+
+ void mov(RegisterID rd, ARMThumbImmediate imm)
+ {
+ ASSERT(imm.isValid());
+ ASSERT(!BadReg(rd));
+
+ if ((rd < 8) && imm.isUInt8())
+ m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
+ else if (imm.isEncodedImm())
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
+ else
+ movT3(rd, imm);
+ }
+
+ void mov(RegisterID rd, RegisterID rm)
+ {
+ m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
+ }
+
+ void movt(RegisterID rd, ARMThumbImmediate imm)
+ {
+ ASSERT(imm.isUInt16());
+ ASSERT(!BadReg(rd));
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
+ }
+
+ void mvn(RegisterID rd, ARMThumbImmediate imm)
+ {
+ ASSERT(imm.isEncodedImm());
+ ASSERT(!BadReg(rd));
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
+ }
+
+ void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void mvn(RegisterID rd, RegisterID rm)
+ {
+ if (!((rd | rm) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
+ else
+ mvn(rd, rm, ShiftTypeAndAmount());
+ }
+
+ void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(imm.isEncodedImm());
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
+ }
+
+ void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void orr(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if ((rd == rn) && !((rd | rm) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
+ else if ((rd == rm) && !((rd | rn) & 8))
+ m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
+ else
+ orr(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rm));
+ ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
+ m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ void ror(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ ASSERT(!BadReg(rd));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
+ }
+
+ void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
+ {
+ ASSERT(!BadReg(rdLo));
+ ASSERT(!BadReg(rdHi));
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ ASSERT(rdLo != rdHi);
+ m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
+ }
+
+ // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+ void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(rt != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isUInt12());
+
+ if (!((rt | rn) & 8) && imm.isUInt7())
+ m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
+ else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
+ m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
+ else
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
+ }
+
+ // If index is set, this is a regular offset or a pre-indexed store;
+ // if index is not set then is is a post-index store.
+ //
+ // If wback is set rn is updated - this is a pre or post index store,
+ // if wback is not set this is a regular offset memory access.
+ //
+ // (-255 <= offset <= 255)
+ // _reg = REG[rn]
+ // _tmp = _reg + offset
+ // MEM[index ? _tmp : _reg] = REG[rt]
+ // if (wback) REG[rn] = _tmp
+ void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+ {
+ ASSERT(rt != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(index || wback);
+ ASSERT(!wback | (rt != rn));
+
+ bool add = true;
+ if (offset < 0) {
+ add = false;
+ offset = -offset;
+ }
+ ASSERT((offset & ~0xff) == 0);
+
+ offset |= (wback << 8);
+ offset |= (add << 9);
+ offset |= (index << 10);
+ offset |= (1 << 11);
+
+ m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
+ }
+
+ // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+ void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+ {
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ ASSERT(shift <= 3);
+
+ if (!shift && !((rt | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
+ else
+ m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
+ }
+
+ void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ // Rd can only be SP if Rn is also SP.
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isValid());
+
+ if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
+ m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
+ return;
+ } else if (!((rd | rn) & 8)) {
+ if (imm.isUInt3()) {
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
+ return;
+ } else if ((rd == rn) && imm.isUInt8()) {
+ m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
+ return;
+ }
+ }
+
+ if (imm.isEncodedImm())
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
+ else {
+ ASSERT(imm.isUInt12());
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
+ }
+ }
+
+ void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ // NOTE: In an IT block, add doesn't modify the flags register.
+ void sub(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if (!((rd | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
+ else
+ sub(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ // Not allowed in an IT (if then) block.
+ void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+ {
+ // Rd can only be SP if Rn is also SP.
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(imm.isValid());
+
+ if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
+ m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
+ return;
+ } else if (!((rd | rn) & 8)) {
+ if (imm.isUInt3()) {
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
+ return;
+ } else if ((rd == rn) && imm.isUInt8()) {
+ m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8());
+ return;
+ }
+ }
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
+ }
+
+ // Not allowed in an IT (if then) block?
+ void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT((rd != ARM::sp) || (rn == ARM::sp));
+ ASSERT(rd != ARM::pc);
+ ASSERT(rn != ARM::pc);
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
+ }
+
+ // Not allowed in an IT (if then) block.
+ void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
+ {
+ if (!((rd | rn | rm) & 8))
+ m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd);
+ else
+ sub_S(rd, rn, rm, ShiftTypeAndAmount());
+ }
+
+ void tst(RegisterID rn, ARMThumbImmediate imm)
+ {
+ ASSERT(!BadReg(rn));
+ ASSERT(imm.isEncodedImm());
+
+ m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
+ }
+
+ void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+ {
+ ASSERT(!BadReg(rn));
+ ASSERT(!BadReg(rm));
+ m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
+ }
+
+ void tst(RegisterID rn, RegisterID rm)
+ {
+ if ((rn | rm) & 8)
+ tst(rn, rm, ShiftTypeAndAmount());
+ else
+ m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
+ }
+
+ void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
+ {
+ m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
+ }
+
+ void vcmp_F64(FPRegisterID rd, FPRegisterID rm)
+ {
+ m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
+ }
+
+ void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm)
+ {
+ m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21));
+ }
+
+ void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm)
+ {
+ m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16));
+ }
+
+ void vldr(FPRegisterID rd, RegisterID rn, int32_t imm)
+ {
+ vmem(rd, rn, imm, true);
+ }
+
+ void vmov(RegisterID rd, FPRegisterID sn)
+ {
+ m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
+ }
+
+ void vmov(FPRegisterID sn, RegisterID rd)
+ {
+ m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
+ }
+
+ // move FPSCR flags to APSR.
+ void vmrs_APSR_nzcv_FPSCR()
+ {
+ m_formatter.vfpOp(0xfa10eef1);
+ }
+
+ void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
+ {
+ m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
+ }
+
+ void vstr(FPRegisterID rd, RegisterID rn, int32_t imm)
+ {
+ vmem(rd, rn, imm, false);
+ }
+
+ void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
+ {
+ m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
+ }
+
+
+ JmpDst label()
+ {
+ return JmpDst(m_formatter.size());
+ }
+
+ JmpDst align(int alignment)
+ {
+ while (!m_formatter.isAligned(alignment))
+ bkpt();
+
+ return label();
+ }
+
+ static void* getRelocatedAddress(void* code, JmpSrc jump)
+ {
+ ASSERT(jump.m_offset != -1);
+
+ 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;
+ }
+
+ // Assembler admin methods:
+
+ size_t size() const
+ {
+ return m_formatter.size();
+ }
+
+ void* executableCopy(ExecutablePool* allocator)
+ {
+ void* copy = m_formatter.executableCopy(allocator);
+ ASSERT(copy);
+ return copy;
+ }
+
+ static unsigned getCallReturnOffset(JmpSrc call)
+ {
+ ASSERT(call.m_offset >= 0);
+ return call.m_offset;
+ }
+
+ // Linking & patching:
+ //
+ // 'link' and 'patch' methods are for use on unprotected code - such as the code
+ // within the AssemblerBuffer, and code being patched by the patch buffer. Once
+ // code has been finalized it is (platform support permitting) within a non-
+ // writable region of memory; to modify the code in an execute-only execuable
+ // pool the 'repatch' and 'relink' methods should be used.
+
+ void linkJump(JmpSrc from, JmpDst to)
+ {
+ ASSERT(to.m_offset != -1);
+ ASSERT(from.m_offset != -1);
+
+ uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset);
+ intptr_t relative = to.m_offset - from.m_offset;
+
+ linkWithOffset(location, relative);
+ }
+
+ static void linkJump(void* code, JmpSrc from, void* to)
+ {
+ ASSERT(from.m_offset != -1);
+
+ uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
+ intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location);
+
+ linkWithOffset(location, relative);
+ }
+
+ // bah, this mathod should really be static, since it is used by the LinkBuffer.
+ // return a bool saying whether the link was successful?
+ static void linkCall(void* code, JmpSrc from, void* to)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
+ ASSERT(from.m_offset != -1);
+ ASSERT(reinterpret_cast<intptr_t>(to) & 1);
+
+ setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
+ }
+
+ static void linkPointer(void* code, JmpDst where, void* value)
+ {
+ setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
+ }
+
+ static void relinkJump(void* from, void* to)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
+ ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
+
+ intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
+ linkWithOffset(reinterpret_cast<uint16_t*>(from), relative);
+
+ ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t));
+ }
+
+ static void relinkCall(void* from, void* to)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
+ ASSERT(reinterpret_cast<intptr_t>(to) & 1);
+
+ setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
+
+ ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
+ }
+
+ static void repatchInt32(void* where, int32_t value)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
+
+ setInt32(where, value);
+
+ ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
+ }
+
+ static void repatchPointer(void* where, void* value)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
+
+ setPointer(where, value);
+
+ ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
+ }
+
+ static void repatchLoadPtrToLEA(void* where)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
+
+ uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
+ ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2);
+
+ *loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf);
+ ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
+ }
+
+private:
+
+ // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
+ // (i.e. +/-(0..255) 32-bit words)
+ void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
+ {
+ bool up;
+ uint32_t offset;
+ if (imm < 0) {
+ offset = -imm;
+ up = false;
+ } else {
+ offset = imm;
+ up = true;
+ }
+
+ // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
+ // reperesented in the instruction. Left shift by 14, to mov it into position 0x00AA0000.
+ ASSERT((offset & ~(0xff << 2)) == 0);
+ offset <<= 14;
+
+ m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
+ }
+
+ static void setInt32(void* code, uint32_t value)
+ {
+ uint16_t* location = reinterpret_cast<uint16_t*>(code);
+
+ uint16_t lo16 = value;
+ uint16_t hi16 = value >> 16;
+
+ spliceHi5(location - 4, lo16);
+ spliceLo11(location - 3, lo16);
+ spliceHi5(location - 2, hi16);
+ spliceLo11(location - 1, hi16);
+
+ ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
+ }
+
+ static void setPointer(void* code, void* value)
+ {
+ setInt32(code, reinterpret_cast<uint32_t>(value));
+ }
+
+ // Linking & patching:
+ // This method assumes that the JmpSrc being linked is a T4 b instruction.
+ static void linkWithOffset(uint16_t* instruction, intptr_t relative)
+ {
+ // Currently branches > 16m = mostly deathy.
+ if (((relative << 7) >> 7) != relative) {
+ // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7.
+ fprintf(stderr, "Error: Cannot link T4b.\n");
+ CRASH();
+ }
+
+ // ARM encoding for the top two bits below the sign bit is 'peculiar'.
+ if (relative >= 0)
+ relative ^= 0xC00000;
+
+ // All branch offsets should be an even distance.
+ ASSERT(!(relative & 1));
+
+ int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
+ int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
+
+ instruction[-2] = OP_B_T4a | word1;
+ instruction[-1] = OP_B_T4b | word2;
+ }
+
+ // These functions can be used to splice 16-bit immediates back into previously generated instructions.
+ static void spliceHi5(uint16_t* where, uint16_t what)
+ {
+ uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1);
+ *where = (*where & 0xFBF0) | pattern;
+ }
+ static void spliceLo11(uint16_t* where, uint16_t what)
+ {
+ uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF);
+ *where = (*where & 0x8F00) | pattern;
+ }
+
+ class ARMInstructionFormatter {
+ public:
+ void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
+ {
+ m_buffer.putShort(op | (rd << 8) | imm);
+ }
+
+ void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
+ {
+ m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
+ }
+
+ void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
+ {
+ m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
+ }
+
+ void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
+ {
+ m_buffer.putShort(op | imm);
+ }
+
+ void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
+ {
+ m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
+ }
+ void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
+ {
+ m_buffer.putShort(op | imm);
+ }
+
+ void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
+ {
+ m_buffer.putShort(op | (reg1 << 3) | reg2);
+ }
+
+ void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
+ {
+ m_buffer.putShort(op | reg);
+ m_buffer.putShort(ff.m_u.value);
+ }
+
+ void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
+ {
+ m_buffer.putShort(op);
+ m_buffer.putShort(ff.m_u.value);
+ }
+
+ void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
+ {
+ m_buffer.putShort(op1);
+ m_buffer.putShort(op2);
+ }
+
+ void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
+ {
+ m_buffer.putShort(op | (imm.m_value.i << 10) | imm4);
+ m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8);
+ }
+
+ void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
+ {
+ m_buffer.putShort(op | reg1);
+ m_buffer.putShort((reg2 << 12) | imm);
+ }
+
+ void vfpOp(int32_t op)
+ {
+ m_buffer.putInt(op);
+ }
+
+
+ // 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:
+ AssemblerBuffer m_buffer;
+ } m_formatter;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && PLATFORM_ARM_ARCH(7)
+
+#endif // ARMAssembler_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 AbstractMacroAssembler_h
+#define AbstractMacroAssembler_h
+
+#include <wtf/Platform.h>
+
+#include <MacroAssemblerCodeRef.h>
+#include <CodeLocation.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/UnusedParam.h>
+
+#if ENABLE(ASSEMBLER)
+
+namespace JSC {
+
+class LinkBuffer;
+class RepatchBuffer;
+
+template <class AssemblerType>
+class AbstractMacroAssembler {
+public:
+ typedef AssemblerType AssemblerType_T;
+
+ typedef MacroAssemblerCodePtr CodePtr;
+ typedef MacroAssemblerCodeRef CodeRef;
+
+ class Jump;
+
+ typedef typename AssemblerType::RegisterID RegisterID;
+ typedef typename AssemblerType::FPRegisterID FPRegisterID;
+ typedef typename AssemblerType::JmpSrc JmpSrc;
+ typedef typename AssemblerType::JmpDst JmpDst;
+
+
+ // Section 1: MacroAssembler operand types
+ //
+ // The following types are used as operands to MacroAssembler operations,
+ // describing immediate and memory operands to the instructions to be planted.
+
+
+ enum Scale {
+ TimesOne,
+ TimesTwo,
+ TimesFour,
+ TimesEight,
+ };
+
+ // 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;
+ };
+
+ // 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_ARM_ARCH(7)
+ , m_isPointer(false)
+#endif
+ {
+ }
+
+#if !PLATFORM(X86_64)
+ explicit Imm32(ImmPtr ptr)
+ : m_value(ptr.asIntptr())
+#if PLATFORM_ARM_ARCH(7)
+ , m_isPointer(true)
+#endif
+ {
+ }
+#endif
+
+ int32_t m_value;
+#if PLATFORM_ARM_ARCH(7)
+ // We rely on being able to regenerate code to recover exception handling
+ // information. Since ARMv7 supports 16-bit immediates there is a danger
+ // that if pointer values change the layout of the generated code will change.
+ // To avoid this problem, always generate pointers (and thus Imm32s constructed
+ // from ImmPtrs) with a code sequence that is able to represent any pointer
+ // value - don't use a more compact form in these cases.
+ bool m_isPointer;
+#endif
+ };
+
+
+ // Section 2: MacroAssembler code buffer handles
+ //
+ // The following types are used to reference items in the code buffer
+ // during JIT code generation. For example, the type Jump is used to
+ // track the location of a jump instruction so that it may later be
+ // linked to a label marking its destination.
+
+
+ // 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 {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+ friend class Jump;
+ friend class MacroAssemblerCodeRef;
+ friend class LinkBuffer;
+
+ public:
+ Label()
+ {
+ }
+
+ Label(AbstractMacroAssembler<AssemblerType>* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ bool isUsed() const { return m_label.isUsed(); }
+ void used() { m_label.used(); }
+ private:
+ JmpDst m_label;
+ };
+
+ // 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 {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+ friend class LinkBuffer;
+ public:
+ DataLabelPtr()
+ {
+ }
+
+ DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ private:
+ 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 {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+ friend class LinkBuffer;
+ public:
+ DataLabel32()
+ {
+ }
+
+ DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ private:
+ JmpDst m_label;
+ };
+
+ // Call:
+ //
+ // A Call object is a reference to a call instruction that has been planted
+ // into the code buffer - it is typically used to link the call, setting the
+ // relative offset such that when executed it will call to the desired
+ // destination.
+ class Call {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+
+ public:
+ enum Flags {
+ None = 0x0,
+ Linkable = 0x1,
+ Near = 0x2,
+ LinkableNear = 0x3,
+ };
+
+ Call()
+ : m_flags(None)
+ {
+ }
+
+ Call(JmpSrc jmp, Flags flags)
+ : m_jmp(jmp)
+ , m_flags(flags)
+ {
+ }
+
+ bool isFlagSet(Flags flag)
+ {
+ return m_flags & flag;
+ }
+
+ static Call fromTailJump(Jump jump)
+ {
+ return Call(jump.m_jmp, Linkable);
+ }
+
+ JmpSrc m_jmp;
+
+ private:
+ Flags m_flags;
+ };
+
+ // 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.
+ class Jump {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+ friend class Call;
+ friend class LinkBuffer;
+ public:
+ Jump()
+ {
+ }
+
+ Jump(JmpSrc jmp)
+ : m_jmp(jmp)
+ {
+ }
+
+ void link(AbstractMacroAssembler<AssemblerType>* masm)
+ {
+ masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
+ }
+
+ void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
+ {
+ masm->m_assembler.linkJump(m_jmp, label.m_label);
+ }
+
+ private:
+ 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 LinkBuffer;
+
+ public:
+ typedef Vector<Jump, 16> JumpVector;
+
+ void link(AbstractMacroAssembler<AssemblerType>* 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, AbstractMacroAssembler<AssemblerType>* 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();
+ }
+
+ const JumpVector& jumps() { return m_jumps; }
+
+ private:
+ JumpVector m_jumps;
+ };
+
+
+ // Section 3: Misc admin methods
+
+ static CodePtr trampolineAt(CodeRef ref, Label label)
+ {
+ return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
+ }
+
+ size_t size()
+ {
+ return m_assembler.size();
+ }
+
+ Label label()
+ {
+ return Label(this);
+ }
+
+ Label align()
+ {
+ m_assembler.align(16);
+ return Label(this);
+ }
+
+ ptrdiff_t differenceBetween(Label from, Jump to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+ ptrdiff_t differenceBetween(Label from, Call to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+ ptrdiff_t differenceBetween(Label from, Label to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(Label from, DataLabel32 to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+ ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
+
+ ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+ }
+
+protected:
+ AssemblerType m_assembler;
+
+ friend class LinkBuffer;
+ friend class RepatchBuffer;
+
+ static void linkJump(void* code, Jump jump, CodeLocationLabel target)
+ {
+ AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
+ }
+
+ static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
+ {
+ AssemblerType::linkPointer(code, label, value);
+ }
+
+ static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
+ {
+ return AssemblerType::getRelocatedAddress(code, label);
+ }
+
+ static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
+ {
+ return AssemblerType::getRelocatedAddress(code, label);
+ }
+
+ static unsigned getLinkerCallReturnOffset(Call call)
+ {
+ return AssemblerType::getCallReturnOffset(call.m_jmp);
+ }
+
+ static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
+ {
+ AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
+ }
+
+ static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
+ {
+ AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
+ }
+
+ static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
+ {
+ AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
+ }
+
+ static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
+ {
+ AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
+ }
+
+ static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+ {
+ AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
+ }
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // AbstractMacroAssembler_h
void putIntUnchecked(int value)
{
+ ASSERT(!(m_size > m_capacity - 4));
*reinterpret_cast<int*>(&m_buffer[m_size]) = value;
m_size += 4;
}
void putInt64Unchecked(int64_t value)
{
+ ASSERT(!(m_size > m_capacity - 8));
*reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
m_size += 8;
}
if (!result)
return 0;
+ ExecutableAllocator::makeWritable(result, m_size);
+
return memcpy(result, m_buffer, m_size);
}
- private:
- void grow()
+ protected:
+ void append(const char* data, int size)
+ {
+ if (m_size > m_capacity - size)
+ grow(size);
+
+ memcpy(m_buffer + m_size, data, size);
+ m_size += size;
+ }
+
+ void grow(int extraCapacity = 0)
{
- m_capacity += m_capacity / 2;
+ m_capacity += m_capacity / 2 + extraCapacity;
if (m_buffer == m_inlineBuffer) {
char* newBuffer = static_cast<char*>(fastMalloc(m_capacity));
--- /dev/null
+/*
+ * Copyright (C) 2009 University of Szeged
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 AssemblerBufferWithConstantPool_h
+#define AssemblerBufferWithConstantPool_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "AssemblerBuffer.h"
+#include <wtf/SegmentedVector.h>
+
+namespace JSC {
+
+/*
+ On a constant pool 4 or 8 bytes data can be stored. The values can be
+ constants or addresses. The addresses should be 32 or 64 bits. The constants
+ should be double-precisions float or integer numbers which are hard to be
+ encoded as few machine instructions.
+
+ TODO: The pool is desinged to handle both 32 and 64 bits values, but
+ currently only the 4 bytes constants are implemented and tested.
+
+ The AssemblerBuffer can contain multiple constant pools. Each pool is inserted
+ into the instruction stream - protected by a jump instruction from the
+ execution flow.
+
+ The flush mechanism is called when no space remain to insert the next instruction
+ into the pool. Three values are used to determine when the constant pool itself
+ have to be inserted into the instruction stream (Assembler Buffer):
+
+ - maxPoolSize: size of the constant pool in bytes, this value cannot be
+ larger than the maximum offset of a PC relative memory load
+
+ - barrierSize: size of jump instruction in bytes which protects the
+ constant pool from execution
+
+ - maxInstructionSize: maximum length of a machine instruction in bytes
+
+ There are some callbacks which solve the target architecture specific
+ address handling:
+
+ - TYPE patchConstantPoolLoad(TYPE load, int value):
+ patch the 'load' instruction with the index of the constant in the
+ constant pool and return the patched instruction.
+
+ - void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr):
+ patch the a PC relative load instruction at 'loadAddr' address with the
+ final relative offset. The offset can be computed with help of
+ 'constPoolAddr' (the address of the constant pool) and index of the
+ constant (which is stored previously in the load instruction itself).
+
+ - TYPE placeConstantPoolBarrier(int size):
+ return with a constant pool barrier instruction which jumps over the
+ constant pool.
+
+ The 'put*WithConstant*' functions should be used to place a data into the
+ constant pool.
+*/
+
+template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
+class AssemblerBufferWithConstantPool: public AssemblerBuffer {
+ typedef WTF::SegmentedVector<uint32_t, 512> LoadOffsets;
+public:
+ enum {
+ UniqueConst,
+ ReusableConst,
+ UnusedEntry,
+ };
+
+ AssemblerBufferWithConstantPool()
+ : AssemblerBuffer()
+ , m_numConsts(0)
+ , m_maxDistance(maxPoolSize)
+ , m_lastConstDelta(0)
+ {
+ m_pool = static_cast<uint32_t*>(fastMalloc(maxPoolSize));
+ m_mask = static_cast<char*>(fastMalloc(maxPoolSize / sizeof(uint32_t)));
+ }
+
+ ~AssemblerBufferWithConstantPool()
+ {
+ fastFree(m_mask);
+ fastFree(m_pool);
+ }
+
+ void ensureSpace(int space)
+ {
+ flushIfNoSpaceFor(space);
+ AssemblerBuffer::ensureSpace(space);
+ }
+
+ void ensureSpace(int insnSpace, int constSpace)
+ {
+ flushIfNoSpaceFor(insnSpace, constSpace);
+ AssemblerBuffer::ensureSpace(insnSpace);
+ }
+
+ bool isAligned(int alignment)
+ {
+ flushIfNoSpaceFor(alignment);
+ return AssemblerBuffer::isAligned(alignment);
+ }
+
+ void putByteUnchecked(int value)
+ {
+ AssemblerBuffer::putByteUnchecked(value);
+ correctDeltas(1);
+ }
+
+ void putByte(int value)
+ {
+ flushIfNoSpaceFor(1);
+ AssemblerBuffer::putByte(value);
+ correctDeltas(1);
+ }
+
+ void putShortUnchecked(int value)
+ {
+ AssemblerBuffer::putShortUnchecked(value);
+ correctDeltas(2);
+ }
+
+ void putShort(int value)
+ {
+ flushIfNoSpaceFor(2);
+ AssemblerBuffer::putShort(value);
+ correctDeltas(2);
+ }
+
+ void putIntUnchecked(int value)
+ {
+ AssemblerBuffer::putIntUnchecked(value);
+ correctDeltas(4);
+ }
+
+ void putInt(int value)
+ {
+ flushIfNoSpaceFor(4);
+ AssemblerBuffer::putInt(value);
+ correctDeltas(4);
+ }
+
+ void putInt64Unchecked(int64_t value)
+ {
+ AssemblerBuffer::putInt64Unchecked(value);
+ correctDeltas(8);
+ }
+
+ int size()
+ {
+ flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t));
+ return AssemblerBuffer::size();
+ }
+
+ void* executableCopy(ExecutablePool* allocator)
+ {
+ flushConstantPool(false);
+ return AssemblerBuffer::executableCopy(allocator);
+ }
+
+ void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
+ {
+ flushIfNoSpaceFor(4, 4);
+
+ m_loadOffsets.append(AssemblerBuffer::size());
+ if (isReusable)
+ for (int i = 0; i < m_numConsts; ++i) {
+ if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
+ AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i));
+ correctDeltas(4);
+ return;
+ }
+ }
+
+ m_pool[m_numConsts] = constant;
+ m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
+
+ AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
+ ++m_numConsts;
+
+ correctDeltas(4, 4);
+ }
+
+ // This flushing mechanism can be called after any unconditional jumps.
+ void flushWithoutBarrier()
+ {
+ // Flush if constant pool is more than 60% full to avoid overuse of this function.
+ if (5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
+ flushConstantPool(false);
+ }
+
+ uint32_t* poolAddress()
+ {
+ return m_pool;
+ }
+
+private:
+ void correctDeltas(int insnSize)
+ {
+ m_maxDistance -= insnSize;
+ m_lastConstDelta -= insnSize;
+ if (m_lastConstDelta < 0)
+ m_lastConstDelta = 0;
+ }
+
+ void correctDeltas(int insnSize, int constSize)
+ {
+ correctDeltas(insnSize);
+
+ m_maxDistance -= m_lastConstDelta;
+ m_lastConstDelta = constSize;
+ }
+
+ void flushConstantPool(bool useBarrier = true)
+ {
+ if (m_numConsts == 0)
+ return;
+ int alignPool = (AssemblerBuffer::size() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
+
+ if (alignPool)
+ alignPool = sizeof(uint64_t) - alignPool;
+
+ // Callback to protect the constant pool from execution
+ if (useBarrier)
+ AssemblerBuffer::putInt(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool));
+
+ if (alignPool) {
+ if (alignPool & 1)
+ AssemblerBuffer::putByte(AssemblerType::padForAlign8);
+ if (alignPool & 2)
+ AssemblerBuffer::putShort(AssemblerType::padForAlign16);
+ if (alignPool & 4)
+ AssemblerBuffer::putInt(AssemblerType::padForAlign32);
+ }
+
+ int constPoolOffset = AssemblerBuffer::size();
+ append(reinterpret_cast<char*>(m_pool), m_numConsts * sizeof(uint32_t));
+
+ // Patch each PC relative load
+ for (LoadOffsets::Iterator iter = m_loadOffsets.begin(); iter != m_loadOffsets.end(); ++iter) {
+ void* loadAddr = reinterpret_cast<void*>(m_buffer + *iter);
+ AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast<void*>(m_buffer + constPoolOffset));
+ }
+
+ m_loadOffsets.clear();
+ m_numConsts = 0;
+ m_maxDistance = maxPoolSize;
+ }
+
+ void flushIfNoSpaceFor(int nextInsnSize)
+ {
+ if (m_numConsts == 0)
+ return;
+ if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
+ flushConstantPool();
+ }
+
+ void flushIfNoSpaceFor(int nextInsnSize, int nextConstSize)
+ {
+ if (m_numConsts == 0)
+ return;
+ if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)) ||
+ (m_numConsts + nextConstSize / sizeof(uint32_t) >= maxPoolSize))
+ flushConstantPool();
+ }
+
+ uint32_t* m_pool;
+ char* m_mask;
+ LoadOffsets m_loadOffsets;
+
+ int m_numConsts;
+ int m_maxDistance;
+ int m_lastConstDelta;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // AssemblerBufferWithConstantPool_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.
+ */
+
+#ifndef CodeLocation_h
+#define CodeLocation_h
+
+#include <wtf/Platform.h>
+
+#include <MacroAssemblerCodeRef.h>
+
+#if ENABLE(ASSEMBLER)
+
+namespace JSC {
+
+class CodeLocationInstruction;
+class CodeLocationLabel;
+class CodeLocationJump;
+class CodeLocationCall;
+class CodeLocationNearCall;
+class CodeLocationDataLabel32;
+class CodeLocationDataLabelPtr;
+
+// The CodeLocation* types are all pretty much do-nothing wrappers around
+// CodePtr (or MacroAssemblerCodePtr, to give it its full name). These
+// classes only exist to provide type-safety when linking and patching code.
+//
+// The one new piece of functionallity introduced by these classes is the
+// ability to create (or put another way, to re-discover) another CodeLocation
+// at an offset from one you already know. When patching code to optimize it
+// we often want to patch a number of instructions that are short, fixed
+// offsets apart. To reduce memory overhead we will only retain a pointer to
+// one of the instructions, and we will use the *AtOffset methods provided by
+// CodeLocationCommon to find the other points in the code to modify.
+class CodeLocationCommon : public MacroAssemblerCodePtr {
+public:
+ CodeLocationInstruction instructionAtOffset(int offset);
+ CodeLocationLabel labelAtOffset(int offset);
+ CodeLocationJump jumpAtOffset(int offset);
+ CodeLocationCall callAtOffset(int offset);
+ CodeLocationNearCall nearCallAtOffset(int offset);
+ CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
+ CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
+
+protected:
+ CodeLocationCommon()
+ {
+ }
+
+ CodeLocationCommon(MacroAssemblerCodePtr location)
+ : MacroAssemblerCodePtr(location)
+ {
+ }
+};
+
+class CodeLocationInstruction : public CodeLocationCommon {
+public:
+ CodeLocationInstruction() {}
+ explicit CodeLocationInstruction(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationInstruction(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationLabel : public CodeLocationCommon {
+public:
+ CodeLocationLabel() {}
+ explicit CodeLocationLabel(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationLabel(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationJump : public CodeLocationCommon {
+public:
+ CodeLocationJump() {}
+ explicit CodeLocationJump(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationJump(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationCall : public CodeLocationCommon {
+public:
+ CodeLocationCall() {}
+ explicit CodeLocationCall(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationCall(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationNearCall : public CodeLocationCommon {
+public:
+ CodeLocationNearCall() {}
+ explicit CodeLocationNearCall(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationNearCall(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationDataLabel32 : public CodeLocationCommon {
+public:
+ CodeLocationDataLabel32() {}
+ explicit CodeLocationDataLabel32(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationDataLabel32(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+class CodeLocationDataLabelPtr : public CodeLocationCommon {
+public:
+ CodeLocationDataLabelPtr() {}
+ explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr location)
+ : CodeLocationCommon(location) {}
+ explicit CodeLocationDataLabelPtr(void* location)
+ : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
+};
+
+inline CodeLocationInstruction CodeLocationCommon::instructionAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationInstruction(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationLabel CodeLocationCommon::labelAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationLabel(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationJump CodeLocationCommon::jumpAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationJump(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationCall CodeLocationCommon::callAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationCall(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationDataLabelPtr CodeLocationCommon::dataLabelPtrAtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationDataLabelPtr(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+inline CodeLocationDataLabel32 CodeLocationCommon::dataLabel32AtOffset(int offset)
+{
+ ASSERT_VALID_CODE_OFFSET(offset);
+ return CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // CodeLocation_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.
+ */
+
+#ifndef LinkBuffer_h
+#define LinkBuffer_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include <MacroAssembler.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+// LinkBuffer:
+//
+// 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 Call may be acquired.
+// * The address of a Label pointing into the code may be resolved.
+// * The value referenced by a DataLabel may be set.
+//
+class LinkBuffer : public Noncopyable {
+ typedef MacroAssemblerCodeRef CodeRef;
+ typedef MacroAssembler::Label Label;
+ typedef MacroAssembler::Jump Jump;
+ typedef MacroAssembler::JumpList JumpList;
+ typedef MacroAssembler::Call Call;
+ typedef MacroAssembler::DataLabel32 DataLabel32;
+ typedef MacroAssembler::DataLabelPtr DataLabelPtr;
+
+public:
+ // Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
+ // First, executablePool is copied into m_executablePool, then the initialization of
+ // m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
+ LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool)
+ : m_executablePool(executablePool)
+ , m_code(masm->m_assembler.executableCopy(m_executablePool.get()))
+ , m_size(masm->m_assembler.size())
+#ifndef NDEBUG
+ , m_completed(false)
+#endif
+ {
+ }
+
+ ~LinkBuffer()
+ {
+ ASSERT(m_completed);
+ }
+
+ // These methods are used to link or set values at code generation time.
+
+ void link(Call call, FunctionPtr function)
+ {
+ ASSERT(call.isFlagSet(Call::Linkable));
+ MacroAssembler::linkCall(code(), call, function);
+ }
+
+ void link(Jump jump, CodeLocationLabel label)
+ {
+ MacroAssembler::linkJump(code(), jump, label);
+ }
+
+ void link(JumpList list, CodeLocationLabel label)
+ {
+ for (unsigned i = 0; i < list.m_jumps.size(); ++i)
+ MacroAssembler::linkJump(code(), list.m_jumps[i], label);
+ }
+
+ void patch(DataLabelPtr label, void* value)
+ {
+ MacroAssembler::linkPointer(code(), label.m_label, value);
+ }
+
+ void patch(DataLabelPtr label, CodeLocationLabel value)
+ {
+ MacroAssembler::linkPointer(code(), label.m_label, value.executableAddress());
+ }
+
+ // These methods are used to obtain handles to allow the code to be relinked / repatched later.
+
+ CodeLocationCall locationOf(Call call)
+ {
+ ASSERT(call.isFlagSet(Call::Linkable));
+ ASSERT(!call.isFlagSet(Call::Near));
+ return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
+ }
+
+ CodeLocationNearCall locationOfNearCall(Call call)
+ {
+ ASSERT(call.isFlagSet(Call::Linkable));
+ ASSERT(call.isFlagSet(Call::Near));
+ return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
+ }
+
+ CodeLocationLabel locationOf(Label label)
+ {
+ return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label.m_label));
+ }
+
+ CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
+ {
+ return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label.m_label));
+ }
+
+ CodeLocationDataLabel32 locationOf(DataLabel32 label)
+ {
+ return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label.m_label));
+ }
+
+ // This method obtains the return address of the call, given as an offset from
+ // the start of the code.
+ unsigned returnAddressOffset(Call call)
+ {
+ return MacroAssembler::getLinkerCallReturnOffset(call);
+ }
+
+ // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
+ // once to complete generation of the code. 'finalizeCode()' is suited to situations
+ // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
+ // suited to adding to an existing allocation.
+ CodeRef finalizeCode()
+ {
+ performFinalization();
+
+ return CodeRef(m_code, m_executablePool, m_size);
+ }
+ CodeLocationLabel finalizeCodeAddendum()
+ {
+ performFinalization();
+
+ return CodeLocationLabel(code());
+ }
+
+private:
+ // Keep this private! - the underlying code should only be obtained externally via
+ // finalizeCode() or finalizeCodeAddendum().
+ void* code()
+ {
+ return m_code;
+ }
+
+ void performFinalization()
+ {
+#ifndef NDEBUG
+ ASSERT(!m_completed);
+ m_completed = true;
+#endif
+
+ ExecutableAllocator::makeExecutable(code(), m_size);
+ ExecutableAllocator::cacheFlush(code(), m_size);
+ }
+
+ RefPtr<ExecutablePool> m_executablePool;
+ void* m_code;
+ size_t m_size;
+#ifndef NDEBUG
+ bool m_completed;
+#endif
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // LinkBuffer_h
#if ENABLE(ASSEMBLER)
-#include "X86Assembler.h"
+#if PLATFORM_ARM_ARCH(7)
+#include "MacroAssemblerARMv7.h"
+namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
-namespace JSC {
+#elif PLATFORM(X86)
+#include "MacroAssemblerX86.h"
+namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
-class MacroAssembler {
-protected:
- X86Assembler m_assembler;
+#elif PLATFORM(X86_64)
+#include "MacroAssemblerX86_64.h"
+namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
-#if PLATFORM(X86_64)
- static const X86::RegisterID scratchRegister = X86::r11;
+#else
+#error "The MacroAssembler is not supported on this platform."
#endif
+
+namespace JSC {
+
+class MacroAssembler : public MacroAssemblerBase {
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
+
+ using MacroAssemblerBase::pop;
+ using MacroAssemblerBase::jump;
+ using MacroAssemblerBase::branch32;
+ using MacroAssemblerBase::branch16;
#if PLATFORM(X86_64)
- ScalePtr = TimesEight
+ using MacroAssemblerBase::branchPtr;
+ using MacroAssemblerBase::branchTestPtr;
#endif
- };
- MacroAssembler()
+
+ // Platform agnostic onvenience functions,
+ // described in terms of other macro assembly methods.
+ void pop()
{
+ addPtr(Imm32(sizeof(void*)), stackPointerRegister);
}
- size_t size() { return m_assembler.size(); }
- void* copyCode(ExecutablePool* allocator)
+ void peek(RegisterID dest, int index = 0)
{
- return m_assembler.executableCopy(allocator);
+ loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
}
-
- // 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)
+ void poke(RegisterID src, int index = 0)
{
-#if PLATFORM(X86_64)
- m_assembler.addq_rr(src, dest);
-#else
- add32(src, dest);
-#endif
+ storePtr(src, Address(stackPointerRegister, (index * sizeof(void*))));
}
- void addPtr(Imm32 imm, RegisterID srcDest)
+ void poke(Imm32 value, int index = 0)
{
-#if PLATFORM(X86_64)
- m_assembler.addq_ir(imm.m_value, srcDest);
-#else
- add32(imm, srcDest);
-#endif
+ store32(value, Address(stackPointerRegister, (index * sizeof(void*))));
}
- void addPtr(ImmPtr imm, RegisterID dest)
+ void poke(ImmPtr imm, int index = 0)
{
-#if PLATFORM(X86_64)
- move(imm, scratchRegister);
- m_assembler.addq_rr(scratchRegister, dest);
-#else
- add32(Imm32(imm), dest);
-#endif
+ storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*))));
}
- void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
- {
- m_assembler.leal_mr(imm.m_value, src, dest);
- }
- void add32(RegisterID src, RegisterID dest)
+ // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
+ void branchPtr(Condition cond, RegisterID op1, ImmPtr imm, Label target)
{
- m_assembler.addl_rr(src, dest);
+ branchPtr(cond, op1, imm).linkTo(target, this);
}
- void add32(Imm32 imm, Address address)
+ void branch32(Condition cond, RegisterID op1, RegisterID op2, Label target)
{
- m_assembler.addl_im(imm.m_value, address.offset, address.base);
+ branch32(cond, op1, op2).linkTo(target, this);
}
- void add32(Imm32 imm, RegisterID dest)
+ void branch32(Condition cond, RegisterID op1, Imm32 imm, Label target)
{
- m_assembler.addl_ir(imm.m_value, dest);
+ branch32(cond, op1, imm).linkTo(target, this);
}
-
- void add32(Imm32 imm, AbsoluteAddress address)
+
+ void branch32(Condition cond, RegisterID left, Address right, Label target)
{
-#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
+ branch32(cond, left, right).linkTo(target, this);
}
-
- void add32(Address src, RegisterID dest)
+
+ void branch16(Condition cond, BaseIndex left, RegisterID right, Label target)
{
- m_assembler.addl_mr(src.offset, src.base, dest);
+ branch16(cond, left, right).linkTo(target, this);
}
- void andPtr(RegisterID src, RegisterID dest)
+ void branchTestPtr(Condition cond, RegisterID reg, Label target)
{
-#if PLATFORM(X86_64)
- m_assembler.andq_rr(src, dest);
-#else
- and32(src, dest);
-#endif
+ branchTestPtr(cond, reg).linkTo(target, this);
}
- void andPtr(Imm32 imm, RegisterID srcDest)
+ void jump(Label target)
{
-#if PLATFORM(X86_64)
- m_assembler.andq_ir(imm.m_value, srcDest);
-#else
- and32(imm, srcDest);
-#endif
+ jump().linkTo(target, this);
}
- void and32(RegisterID src, RegisterID dest)
- {
- m_assembler.andl_rr(src, dest);
- }
- void and32(Imm32 imm, RegisterID dest)
+ // Ptr methods
+ // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
+#if !PLATFORM(X86_64)
+ void addPtr(RegisterID src, RegisterID dest)
{
- m_assembler.andl_ir(imm.m_value, dest);
+ add32(src, dest);
}
- void lshift32(Imm32 imm, RegisterID dest)
- {
- m_assembler.shll_i8r(imm.m_value, dest);
- }
-
- void lshift32(RegisterID shift_amount, RegisterID dest)
+ void addPtr(Imm32 imm, RegisterID srcDest)
{
- // 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);
+ add32(imm, srcDest);
}
-
- // 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 addPtr(ImmPtr imm, RegisterID dest)
+ {
+ add32(Imm32(imm), dest);
}
- void mul32(RegisterID src, RegisterID dest)
+ void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
{
- m_assembler.imull_rr(src, dest);
+ add32(imm, src, dest);
}
-
- void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+
+ void andPtr(RegisterID src, RegisterID dest)
{
- m_assembler.imull_i32r(src, imm.m_value, dest);
+ and32(src, dest);
}
-
- void not32(RegisterID srcDest)
+
+ void andPtr(Imm32 imm, RegisterID srcDest)
{
- m_assembler.notl_r(srcDest);
+ and32(imm, 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)
+ DataLabel32 loadPtrWithAddressOffsetPatch(Address 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
+ return load32WithAddressOffsetPatch(address, dest);
}
- void load16(BaseIndex address, RegisterID dest)
+ void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
{
- m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
+ set32(cond, left, right, 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)
+ void storePtr(RegisterID src, BaseIndex 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
+ store32(src, address);
}
- void storePtr(RegisterID src, BaseIndex address)
+ void storePtr(RegisterID src, void* 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
+ store32(Imm32(imm), address);
}
-#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)
+ DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
{
- m_assembler.movl_rm(src, address.offset, address.base);
+ return store32WithAddressOffsetPatch(src, address);
}
- 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)
+ Jump branchPtr(Condition cond, RegisterID left, RegisterID right)
{
- 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
+ return branch32(cond, left, right);
}
-
- // 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)
+ Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
{
- m_assembler.pop_r(dest);
+ return branch32(cond, left, Imm32(right));
}
- void push(RegisterID src)
+ Jump branchPtr(Condition cond, RegisterID left, Address right)
{
- m_assembler.push_r(src);
+ return branch32(cond, left, right);
}
- void push(Address address)
+ Jump branchPtr(Condition cond, Address left, RegisterID right)
{
- m_assembler.push_m(address.offset, address.base);
+ return branch32(cond, left, right);
}
- void push(Imm32 imm)
+ Jump branchPtr(Condition cond, AbsoluteAddress left, RegisterID right)
{
- m_assembler.push_i32(imm.m_value);
+ return branch32(cond, left, right);
}
- void pop()
- {
- addPtr(Imm32(sizeof(void*)), X86::esp);
- }
-
- void peek(RegisterID dest, int index = 0)
+ Jump branchPtr(Condition cond, Address left, ImmPtr right)
{
- loadPtr(Address(X86::esp, (index * sizeof(void *))), dest);
+ return branch32(cond, left, Imm32(right));
}
- void poke(RegisterID src, int index = 0)
+ Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right)
{
- storePtr(src, Address(X86::esp, (index * sizeof(void *))));
+ return branch32(cond, left, Imm32(right));
}
- void poke(Imm32 value, int index = 0)
+ Jump branchTestPtr(Condition cond, RegisterID reg, RegisterID mask)
{
- store32(value, Address(X86::esp, (index * sizeof(void *))));
+ return branchTest32(cond, reg, mask);
}
- void poke(ImmPtr imm, int index = 0)
+ Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
{
- storePtr(imm, Address(X86::esp, (index * sizeof(void *))));
+ return branchTest32(cond, reg, mask);
}
- // Register move operations:
- //
- // Move values in registers.
-
- void move(Imm32 imm, RegisterID dest)
+ Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1))
{
- // 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);
+ return branchTest32(cond, address, mask);
}
- void move(RegisterID src, RegisterID dest)
+ Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
{
- // 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
+ return branchTest32(cond, address, mask);
}
- 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)
+ Jump branchAddPtr(Condition cond, RegisterID src, RegisterID dest)
{
-#if PLATFORM(X86_64)
- m_assembler.xchgq_rr(reg1, reg2);
-#else
- m_assembler.xchgl_rr(reg1, reg2);
-#endif
+ return branchAdd32(cond, src, dest);
}
- void signExtend32ToPtr(RegisterID src, RegisterID dest)
+ Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest)
{
-#if PLATFORM(X86_64)
- m_assembler.movsxd_rr(src, dest);
-#else
- if (src != dest)
- move(src, dest);
-#endif
+ return branchSub32(cond, imm, dest);
}
-
- 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
--- /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 MacroAssemblerARMv7_h
+#define MacroAssemblerARMv7_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "ARMv7Assembler.h"
+#include "AbstractMacroAssembler.h"
+
+namespace JSC {
+
+class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> {
+ // FIXME: switch dataTempRegister & addressTempRegister, or possibly use r7?
+ // - dTR is likely used more than aTR, and we'll get better instruction
+ // encoding if it's in the low 8 registers.
+ static const ARM::RegisterID dataTempRegister = ARM::ip;
+ static const RegisterID addressTempRegister = ARM::r3;
+ static const FPRegisterID fpTempRegister = ARM::d7;
+
+ struct ArmAddress {
+ enum AddressType {
+ HasOffset,
+ HasIndex,
+ } type;
+ RegisterID base;
+ union {
+ int32_t offset;
+ struct {
+ RegisterID index;
+ Scale scale;
+ };
+ } u;
+
+ explicit ArmAddress(RegisterID base, int32_t offset = 0)
+ : type(HasOffset)
+ , base(base)
+ {
+ u.offset = offset;
+ }
+
+ explicit ArmAddress(RegisterID base, RegisterID index, Scale scale = TimesOne)
+ : type(HasIndex)
+ , base(base)
+ {
+ u.index = index;
+ u.scale = scale;
+ }
+ };
+
+public:
+
+ static const Scale ScalePtr = TimesFour;
+
+ enum Condition {
+ Equal = ARMv7Assembler::ConditionEQ,
+ NotEqual = ARMv7Assembler::ConditionNE,
+ Above = ARMv7Assembler::ConditionHI,
+ AboveOrEqual = ARMv7Assembler::ConditionHS,
+ Below = ARMv7Assembler::ConditionLO,
+ BelowOrEqual = ARMv7Assembler::ConditionLS,
+ GreaterThan = ARMv7Assembler::ConditionGT,
+ GreaterThanOrEqual = ARMv7Assembler::ConditionGE,
+ LessThan = ARMv7Assembler::ConditionLT,
+ LessThanOrEqual = ARMv7Assembler::ConditionLE,
+ Overflow = ARMv7Assembler::ConditionVS,
+ Signed = ARMv7Assembler::ConditionMI,
+ Zero = ARMv7Assembler::ConditionEQ,
+ NonZero = ARMv7Assembler::ConditionNE
+ };
+
+ enum DoubleCondition {
+ DoubleEqual = ARMv7Assembler::ConditionEQ,
+ DoubleGreaterThan = ARMv7Assembler::ConditionGT,
+ DoubleGreaterThanOrEqual = ARMv7Assembler::ConditionGE,
+ DoubleLessThan = ARMv7Assembler::ConditionLO,
+ DoubleLessThanOrEqual = ARMv7Assembler::ConditionLS,
+ };
+
+ static const RegisterID stackPointerRegister = ARM::sp;
+ static const RegisterID linkRegister = ARM::lr;
+
+ // 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 add32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.add(dest, dest, src);
+ }
+
+ void add32(Imm32 imm, RegisterID dest)
+ {
+ add32(imm, dest, dest);
+ }
+
+ void add32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.add(dest, src, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.add(dest, src, dataTempRegister);
+ }
+ }
+
+ void add32(Imm32 imm, Address address)
+ {
+ load32(address, dataTempRegister);
+
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.add(dataTempRegister, dataTempRegister, armImm);
+ else {
+ // Hrrrm, since dataTempRegister holds the data loaded,
+ // use addressTempRegister to hold the immediate.
+ move(imm, addressTempRegister);
+ m_assembler.add(dataTempRegister, dataTempRegister, addressTempRegister);
+ }
+
+ store32(dataTempRegister, address);
+ }
+
+ void add32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ add32(dataTempRegister, dest);
+ }
+
+ void add32(Imm32 imm, AbsoluteAddress address)
+ {
+ load32(address.m_ptr, dataTempRegister);
+
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.add(dataTempRegister, dataTempRegister, armImm);
+ else {
+ // Hrrrm, since dataTempRegister holds the data loaded,
+ // use addressTempRegister to hold the immediate.
+ move(imm, addressTempRegister);
+ m_assembler.add(dataTempRegister, dataTempRegister, addressTempRegister);
+ }
+
+ store32(dataTempRegister, address.m_ptr);
+ }
+
+ void and32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.ARM_and(dest, dest, src);
+ }
+
+ void and32(Imm32 imm, RegisterID dest)
+ {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.ARM_and(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.ARM_and(dest, dest, dataTempRegister);
+ }
+ }
+
+ void lshift32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.lsl(dest, dest, imm.m_value);
+ }
+
+ void lshift32(RegisterID shift_amount, RegisterID dest)
+ {
+ m_assembler.lsl(dest, dest, shift_amount);
+ }
+
+ void mul32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.smull(dest, dataTempRegister, dest, src);
+ }
+
+ void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ move(imm, dataTempRegister);
+ m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
+ }
+
+ void not32(RegisterID srcDest)
+ {
+ m_assembler.mvn(srcDest, srcDest);
+ }
+
+ void or32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.orr(dest, dest, src);
+ }
+
+ void or32(Imm32 imm, RegisterID dest)
+ {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.orr(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.orr(dest, dest, dataTempRegister);
+ }
+ }
+
+ void rshift32(RegisterID shift_amount, RegisterID dest)
+ {
+ m_assembler.asr(dest, dest, shift_amount);
+ }
+
+ void rshift32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.asr(dest, dest, imm.m_value);
+ }
+
+ void sub32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.sub(dest, dest, src);
+ }
+
+ void sub32(Imm32 imm, RegisterID dest)
+ {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.sub(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.sub(dest, dest, dataTempRegister);
+ }
+ }
+
+ void sub32(Imm32 imm, Address address)
+ {
+ load32(address, dataTempRegister);
+
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.sub(dataTempRegister, dataTempRegister, armImm);
+ else {
+ // Hrrrm, since dataTempRegister holds the data loaded,
+ // use addressTempRegister to hold the immediate.
+ move(imm, addressTempRegister);
+ m_assembler.sub(dataTempRegister, dataTempRegister, addressTempRegister);
+ }
+
+ store32(dataTempRegister, address);
+ }
+
+ void sub32(Address src, RegisterID dest)
+ {
+ load32(src, dataTempRegister);
+ sub32(dataTempRegister, dest);
+ }
+
+ void sub32(Imm32 imm, AbsoluteAddress address)
+ {
+ load32(address.m_ptr, dataTempRegister);
+
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.sub(dataTempRegister, dataTempRegister, armImm);
+ else {
+ // Hrrrm, since dataTempRegister holds the data loaded,
+ // use addressTempRegister to hold the immediate.
+ move(imm, addressTempRegister);
+ m_assembler.sub(dataTempRegister, dataTempRegister, addressTempRegister);
+ }
+
+ store32(dataTempRegister, address.m_ptr);
+ }
+
+ void xor32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.eor(dest, dest, src);
+ }
+
+ void xor32(Imm32 imm, RegisterID dest)
+ {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.eor(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.eor(dest, dest, dataTempRegister);
+ }
+ }
+
+
+ // 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.
+
+private:
+ void load32(ArmAddress address, RegisterID dest)
+ {
+ if (address.type == ArmAddress::HasIndex)
+ m_assembler.ldr(dest, address.base, address.u.index, address.u.scale);
+ else if (address.u.offset >= 0) {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
+ ASSERT(armImm.isValid());
+ m_assembler.ldr(dest, address.base, armImm);
+ } else {
+ ASSERT(address.u.offset >= -255);
+ m_assembler.ldr(dest, address.base, address.u.offset, true, false);
+ }
+ }
+
+ void load16(ArmAddress address, RegisterID dest)
+ {
+ if (address.type == ArmAddress::HasIndex)
+ m_assembler.ldrh(dest, address.base, address.u.index, address.u.scale);
+ else if (address.u.offset >= 0) {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
+ ASSERT(armImm.isValid());
+ m_assembler.ldrh(dest, address.base, armImm);
+ } else {
+ ASSERT(address.u.offset >= -255);
+ m_assembler.ldrh(dest, address.base, address.u.offset, true, false);
+ }
+ }
+
+ void store32(RegisterID src, ArmAddress address)
+ {
+ if (address.type == ArmAddress::HasIndex)
+ m_assembler.str(src, address.base, address.u.index, address.u.scale);
+ else if (address.u.offset >= 0) {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
+ ASSERT(armImm.isValid());
+ m_assembler.str(src, address.base, armImm);
+ } else {
+ ASSERT(address.u.offset >= -255);
+ m_assembler.str(src, address.base, address.u.offset, true, false);
+ }
+ }
+
+public:
+ void load32(ImplicitAddress address, RegisterID dest)
+ {
+ load32(setupArmAddress(address), dest);
+ }
+
+ void load32(BaseIndex address, RegisterID dest)
+ {
+ load32(setupArmAddress(address), dest);
+ }
+
+ void load32(void* address, RegisterID dest)
+ {
+ move(ImmPtr(address), addressTempRegister);
+ m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
+ }
+
+ DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+ {
+ DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
+ load32(ArmAddress(address.base, dataTempRegister), dest);
+ return label;
+ }
+
+ Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+ {
+ Label label(this);
+ moveFixedWidthEncoding(Imm32(address.offset), dataTempRegister);
+ load32(ArmAddress(address.base, dataTempRegister), dest);
+ return label;
+ }
+
+ void load16(BaseIndex address, RegisterID dest)
+ {
+ m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
+ }
+
+ DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
+ {
+ DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
+ store32(src, ArmAddress(address.base, dataTempRegister));
+ return label;
+ }
+
+ void store32(RegisterID src, ImplicitAddress address)
+ {
+ store32(src, setupArmAddress(address));
+ }
+
+ void store32(RegisterID src, BaseIndex address)
+ {
+ store32(src, setupArmAddress(address));
+ }
+
+ void store32(Imm32 imm, ImplicitAddress address)
+ {
+ move(imm, dataTempRegister);
+ store32(dataTempRegister, setupArmAddress(address));
+ }
+
+ void store32(RegisterID src, void* address)
+ {
+ move(ImmPtr(address), addressTempRegister);
+ m_assembler.str(src, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
+ }
+
+ void store32(Imm32 imm, void* address)
+ {
+ move(imm, dataTempRegister);
+ store32(dataTempRegister, address);
+ }
+
+
+ // Floating-point operations:
+
+ bool supportsFloatingPoint() const { return true; }
+ // On x86(_64) the MacroAssembler provides an interface to truncate a double to an integer.
+ // If a value is not representable as an integer, and possibly for some values that are,
+ // (on x86 INT_MIN, since this is indistinguishable from results for out-of-range/NaN input)
+ // a branch will be taken. It is not clear whether this interface will be well suited to
+ // other platforms. On ARMv7 the hardware truncation operation produces multiple possible
+ // failure values (saturates to INT_MIN & INT_MAX, NaN reulsts in a value of 0). This is a
+ // temporary solution while we work out what this interface should be. Either we need to
+ // decide to make this interface work on all platforms, rework the interface to make it more
+ // generic, or decide that the MacroAssembler cannot practically be used to abstracted these
+ // operations, and make clients go directly to the m_assembler to plant truncation instructions.
+ // In short, FIXME:.
+ bool supportsFloatingPointTruncate() const { return false; }
+
+ void loadDouble(ImplicitAddress address, FPRegisterID dest)
+ {
+ RegisterID base = address.base;
+ int32_t offset = address.offset;
+
+ // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
+ if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) {
+ add32(Imm32(offset), base, addressTempRegister);
+ base = addressTempRegister;
+ offset = 0;
+ }
+
+ m_assembler.vldr(dest, base, offset);
+ }
+
+ void storeDouble(FPRegisterID src, ImplicitAddress address)
+ {
+ RegisterID base = address.base;
+ int32_t offset = address.offset;
+
+ // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
+ if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) {
+ add32(Imm32(offset), base, addressTempRegister);
+ base = addressTempRegister;
+ offset = 0;
+ }
+
+ m_assembler.vstr(src, base, offset);
+ }
+
+ void addDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ m_assembler.vadd_F64(dest, dest, src);
+ }
+
+ void addDouble(Address src, FPRegisterID dest)
+ {
+ loadDouble(src, fpTempRegister);
+ addDouble(fpTempRegister, dest);
+ }
+
+ void subDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ m_assembler.vsub_F64(dest, dest, src);
+ }
+
+ void subDouble(Address src, FPRegisterID dest)
+ {
+ loadDouble(src, fpTempRegister);
+ subDouble(fpTempRegister, dest);
+ }
+
+ void mulDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ m_assembler.vmul_F64(dest, dest, src);
+ }
+
+ void mulDouble(Address src, FPRegisterID dest)
+ {
+ loadDouble(src, fpTempRegister);
+ mulDouble(fpTempRegister, dest);
+ }
+
+ void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.vmov(fpTempRegister, src);
+ m_assembler.vcvt_F64_S32(dest, fpTempRegister);
+ }
+
+ Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+ {
+ m_assembler.vcmp_F64(left, right);
+ m_assembler.vmrs_APSR_nzcv_FPSCR();
+ return makeBranch(cond);
+ }
+
+ Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+
+ // 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)
+ {
+ // store postindexed with writeback
+ m_assembler.ldr(dest, ARM::sp, sizeof(void*), false, true);
+ }
+
+ void push(RegisterID src)
+ {
+ // store preindexed with writeback
+ m_assembler.str(src, ARM::sp, -sizeof(void*), true, true);
+ }
+
+ void push(Address address)
+ {
+ load32(address, dataTempRegister);
+ push(dataTempRegister);
+ }
+
+ void push(Imm32 imm)
+ {
+ move(imm, dataTempRegister);
+ push(dataTempRegister);
+ }
+
+ // Register move operations:
+ //
+ // Move values in registers.
+
+ void move(Imm32 imm, RegisterID dest)
+ {
+ uint32_t value = imm.m_value;
+
+ if (imm.m_isPointer)
+ moveFixedWidthEncoding(imm, dest);
+ else {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(value);
+
+ if (armImm.isValid())
+ m_assembler.mov(dest, armImm);
+ else if ((armImm = ARMThumbImmediate::makeEncodedImm(~value)).isValid())
+ m_assembler.mvn(dest, armImm);
+ else {
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(value));
+ if (value & 0xffff0000)
+ m_assembler.movt(dest, ARMThumbImmediate::makeUInt16(value >> 16));
+ }
+ }
+ }
+
+ void move(RegisterID src, RegisterID dest)
+ {
+ m_assembler.mov(dest, src);
+ }
+
+ void move(ImmPtr imm, RegisterID dest)
+ {
+ move(Imm32(imm), dest);
+ }
+
+ void swap(RegisterID reg1, RegisterID reg2)
+ {
+ move(reg1, dataTempRegister);
+ move(reg2, reg1);
+ move(dataTempRegister, reg2);
+ }
+
+ void signExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+ if (src != dest)
+ move(src, dest);
+ }
+
+ void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+ if (src != dest)
+ move(src, dest);
+ }
+
+
+ // 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:
+
+ // Should we be using TEQ for equal/not-equal?
+ void compare32(RegisterID left, Imm32 right)
+ {
+ int32_t imm = right.m_value;
+ if (!imm)
+ m_assembler.tst(left, left);
+ else {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm);
+ if (armImm.isValid())
+ m_assembler.cmp(left, armImm);
+ if ((armImm = ARMThumbImmediate::makeEncodedImm(-imm)).isValid())
+ m_assembler.cmn(left, armImm);
+ else {
+ move(Imm32(imm), dataTempRegister);
+ m_assembler.cmp(left, dataTempRegister);
+ }
+ }
+ }
+
+ void test32(RegisterID reg, Imm32 mask)
+ {
+ int32_t imm = mask.m_value;
+
+ if (imm == -1)
+ m_assembler.tst(reg, reg);
+ else {
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm);
+ if (armImm.isValid())
+ m_assembler.tst(reg, armImm);
+ else {
+ move(mask, dataTempRegister);
+ m_assembler.tst(reg, dataTempRegister);
+ }
+ }
+ }
+
+public:
+ Jump branch32(Condition cond, RegisterID left, RegisterID right)
+ {
+ m_assembler.cmp(left, right);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branch32(Condition cond, RegisterID left, Imm32 right)
+ {
+ compare32(left, right);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branch32(Condition cond, RegisterID left, Address right)
+ {
+ load32(right, dataTempRegister);
+ return branch32(cond, left, dataTempRegister);
+ }
+
+ Jump branch32(Condition cond, Address left, RegisterID right)
+ {
+ load32(left, dataTempRegister);
+ return branch32(cond, dataTempRegister, right);
+ }
+
+ Jump branch32(Condition cond, Address left, Imm32 right)
+ {
+ // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+ load32(left, addressTempRegister);
+ return branch32(cond, addressTempRegister, right);
+ }
+
+ Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+ {
+ // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+ load32(left, addressTempRegister);
+ return branch32(cond, addressTempRegister, right);
+ }
+
+ Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+ {
+ load32(left.m_ptr, dataTempRegister);
+ return branch32(cond, dataTempRegister, right);
+ }
+
+ Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+ {
+ // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+ load32(left.m_ptr, addressTempRegister);
+ return branch32(cond, addressTempRegister, right);
+ }
+
+ Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+ {
+ load16(left, dataTempRegister);
+ m_assembler.lsl(addressTempRegister, right, 16);
+ m_assembler.lsl(dataTempRegister, dataTempRegister, 16);
+ return branch32(cond, dataTempRegister, addressTempRegister);
+ }
+
+ Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+ {
+ // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+ load16(left, addressTempRegister);
+ m_assembler.lsl(addressTempRegister, addressTempRegister, 16);
+ return branch32(cond, addressTempRegister, Imm32(right.m_value << 16));
+ }
+
+ Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ m_assembler.tst(reg, mask);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ test32(reg, mask);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/
+ load32(address, addressTempRegister);
+ return branchTest32(cond, addressTempRegister, mask);
+ }
+
+ Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/
+ load32(address, addressTempRegister);
+ return branchTest32(cond, addressTempRegister, mask);
+ }
+
+ Jump jump()
+ {
+ return Jump(makeJump());
+ }
+
+ void jump(RegisterID target)
+ {
+ m_assembler.bx(target);
+ }
+
+ // Address is a memory location containing the address to jump to
+ void jump(Address address)
+ {
+ load32(address, dataTempRegister);
+ m_assembler.bx(dataTempRegister);
+ }
+
+
+ // 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 branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ m_assembler.add_S(dest, dest, src);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.add_S(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.add_S(dest, dest, dataTempRegister);
+ }
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT(cond == Overflow);
+ m_assembler.smull(dest, dataTempRegister, dest, src);
+ m_assembler.asr(addressTempRegister, dest, 31);
+ return branch32(NotEqual, addressTempRegister, dataTempRegister);
+ }
+
+ Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ ASSERT(cond == Overflow);
+ move(imm, dataTempRegister);
+ m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
+ m_assembler.asr(addressTempRegister, dest, 31);
+ return branch32(NotEqual, addressTempRegister, dataTempRegister);
+ }
+
+ Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ m_assembler.sub_S(dest, dest, src);
+ return Jump(makeBranch(cond));
+ }
+
+ Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+ if (armImm.isValid())
+ m_assembler.sub_S(dest, dest, armImm);
+ else {
+ move(imm, dataTempRegister);
+ m_assembler.sub_S(dest, dest, dataTempRegister);
+ }
+ return Jump(makeBranch(cond));
+ }
+
+
+ // Miscellaneous operations:
+
+ void breakpoint()
+ {
+ m_assembler.bkpt();
+ }
+
+ Call nearCall()
+ {
+ moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+ return Call(m_assembler.blx(dataTempRegister), Call::LinkableNear);
+ }
+
+ Call call()
+ {
+ moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+ return Call(m_assembler.blx(dataTempRegister), Call::Linkable);
+ }
+
+ Call call(RegisterID target)
+ {
+ return Call(m_assembler.blx(target), Call::None);
+ }
+
+ Call call(Address address)
+ {
+ load32(address, dataTempRegister);
+ return Call(m_assembler.blx(dataTempRegister), Call::None);
+ }
+
+ void ret()
+ {
+ m_assembler.bx(linkRegister);
+ }
+
+ void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+ {
+ m_assembler.cmp(left, right);
+ m_assembler.it(armV7Condition(cond), false);
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1));
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
+ }
+
+ void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+ {
+ compare32(left, right);
+ m_assembler.it(armV7Condition(cond), false);
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1));
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
+ }
+
+ // 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 setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+ {
+ load32(address, dataTempRegister);
+ test32(dataTempRegister, mask);
+ m_assembler.it(armV7Condition(cond), false);
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1));
+ m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
+ }
+
+
+ DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst)
+ {
+ moveFixedWidthEncoding(imm, dst);
+ return DataLabel32(this);
+ }
+
+ DataLabelPtr moveWithPatch(ImmPtr imm, RegisterID dst)
+ {
+ moveFixedWidthEncoding(Imm32(imm), dst);
+ return DataLabelPtr(this);
+ }
+
+ Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
+ return branch32(cond, left, dataTempRegister);
+ }
+
+ Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ load32(left, addressTempRegister);
+ dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
+ return branch32(cond, addressTempRegister, dataTempRegister);
+ }
+
+ DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+ {
+ DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
+ store32(dataTempRegister, address);
+ return label;
+ }
+ DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(ImmPtr(0), address); }
+
+
+ Call tailRecursiveCall()
+ {
+ // Like a normal call, but don't link.
+ moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+ return Call(m_assembler.bx(dataTempRegister), Call::Linkable);
+ }
+
+ Call makeTailRecursiveCall(Jump oldJump)
+ {
+ oldJump.link(this);
+ return tailRecursiveCall();
+ }
+
+
+protected:
+ ARMv7Assembler::JmpSrc makeJump()
+ {
+ return m_assembler.b();
+ }
+
+ ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond)
+ {
+ m_assembler.it(cond);
+ return m_assembler.b();
+ }
+ ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
+ ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
+
+ ArmAddress setupArmAddress(BaseIndex address)
+ {
+ if (address.offset) {
+ ARMThumbImmediate imm = ARMThumbImmediate::makeUInt12OrEncodedImm(address.offset);
+ if (imm.isValid())
+ m_assembler.add(addressTempRegister, address.base, imm);
+ else {
+ move(Imm32(address.offset), addressTempRegister);
+ m_assembler.add(addressTempRegister, addressTempRegister, address.base);
+ }
+
+ return ArmAddress(addressTempRegister, address.index, address.scale);
+ } else
+ return ArmAddress(address.base, address.index, address.scale);
+ }
+
+ ArmAddress setupArmAddress(Address address)
+ {
+ if ((address.offset >= -0xff) && (address.offset <= 0xfff))
+ return ArmAddress(address.base, address.offset);
+
+ move(Imm32(address.offset), addressTempRegister);
+ return ArmAddress(address.base, addressTempRegister);
+ }
+
+ ArmAddress setupArmAddress(ImplicitAddress address)
+ {
+ if ((address.offset >= -0xff) && (address.offset <= 0xfff))
+ return ArmAddress(address.base, address.offset);
+
+ move(Imm32(address.offset), addressTempRegister);
+ return ArmAddress(address.base, addressTempRegister);
+ }
+
+ RegisterID makeBaseIndexBase(BaseIndex address)
+ {
+ if (!address.offset)
+ return address.base;
+
+ ARMThumbImmediate imm = ARMThumbImmediate::makeUInt12OrEncodedImm(address.offset);
+ if (imm.isValid())
+ m_assembler.add(addressTempRegister, address.base, imm);
+ else {
+ move(Imm32(address.offset), addressTempRegister);
+ m_assembler.add(addressTempRegister, addressTempRegister, address.base);
+ }
+
+ return addressTempRegister;
+ }
+
+ DataLabel32 moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
+ {
+ uint32_t value = imm.m_value;
+ m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));
+ m_assembler.movt(dst, ARMThumbImmediate::makeUInt16(value >> 16));
+ }
+
+ ARMv7Assembler::Condition armV7Condition(Condition cond)
+ {
+ return static_cast<ARMv7Assembler::Condition>(cond);
+ }
+
+ ARMv7Assembler::Condition armV7Condition(DoubleCondition cond)
+ {
+ return static_cast<ARMv7Assembler::Condition>(cond);
+ }
+
+private:
+ friend class LinkBuffer;
+ friend class RepatchBuffer;
+
+ static void linkCall(void* code, Call call, FunctionPtr function)
+ {
+ ARMv7Assembler::linkCall(code, call.m_jmp, function.value());
+ }
+
+ static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+ {
+ ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+ }
+
+ static void repatchCall(CodeLocationCall call, FunctionPtr destination)
+ {
+ ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+ }
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerARMv7_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.
+ */
+
+#ifndef MacroAssemblerCodeRef_h
+#define MacroAssemblerCodeRef_h
+
+#include <wtf/Platform.h>
+
+#include "ExecutableAllocator.h"
+#include "PassRefPtr.h"
+#include "RefPtr.h"
+#include "UnusedParam.h"
+
+#if ENABLE(ASSEMBLER)
+
+// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
+// instruction address on the platform (for example, check any alignment requirements).
+#if PLATFORM_ARM_ARCH(7)
+// ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
+// into the processor are decorated with the bottom bit set, indicating that this is
+// thumb code (as oposed to 32-bit traditional ARM). The first test checks for both
+// decorated and undectorated null, and the second test ensures that the pointer is
+// decorated.
+#define ASSERT_VALID_CODE_POINTER(ptr) \
+ ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1); \
+ ASSERT(reinterpret_cast<intptr_t>(ptr) & 1)
+#define ASSERT_VALID_CODE_OFFSET(offset) \
+ ASSERT(!(offset & 1)) // Must be multiple of 2.
+#else
+#define ASSERT_VALID_CODE_POINTER(ptr) \
+ ASSERT(ptr)
+#define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
+#endif
+
+namespace JSC {
+
+// FunctionPtr:
+//
+// FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
+// (particularly, the stub functions).
+class FunctionPtr {
+public:
+ FunctionPtr()
+ : m_value(0)
+ {
+ }
+
+ template<typename FunctionType>
+ explicit FunctionPtr(FunctionType* value)
+ : m_value(reinterpret_cast<void*>(value))
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ void* value() const { return m_value; }
+ void* executableAddress() const { return m_value; }
+
+
+private:
+ void* m_value;
+};
+
+// ReturnAddressPtr:
+//
+// ReturnAddressPtr should be used to wrap return addresses generated by processor
+// 'call' instructions exectued in JIT code. We use return addresses to look up
+// exception and optimization information, and to repatch the call instruction
+// that is the source of the return address.
+class ReturnAddressPtr {
+public:
+ ReturnAddressPtr()
+ : m_value(0)
+ {
+ }
+
+ explicit ReturnAddressPtr(void* value)
+ : m_value(value)
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ explicit ReturnAddressPtr(FunctionPtr function)
+ : m_value(function.value())
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ void* value() const { return m_value; }
+
+private:
+ void* m_value;
+};
+
+// MacroAssemblerCodePtr:
+//
+// MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
+class MacroAssemblerCodePtr {
+public:
+ MacroAssemblerCodePtr()
+ : m_value(0)
+ {
+ }
+
+ explicit MacroAssemblerCodePtr(void* value)
+#if PLATFORM_ARM_ARCH(7)
+ // Decorate the pointer as a thumb code pointer.
+ : m_value(reinterpret_cast<char*>(value) + 1)
+#else
+ : m_value(value)
+#endif
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
+ : m_value(ra.value())
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ void* executableAddress() const { return m_value; }
+#if PLATFORM_ARM_ARCH(7)
+ // To use this pointer as a data address remove the decoration.
+ void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
+#else
+ void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
+#endif
+
+ bool operator!()
+ {
+ return !m_value;
+ }
+
+private:
+ void* m_value;
+};
+
+// MacroAssemblerCodeRef:
+//
+// A reference to a section of JIT generated code. A CodeRef consists of a
+// pointer to the code, and a ref pointer to the pool from within which it
+// was allocated.
+class MacroAssemblerCodeRef {
+public:
+ MacroAssemblerCodeRef()
+ : m_size(0)
+ {
+ }
+
+ MacroAssemblerCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
+ : m_code(code)
+ , m_executablePool(executablePool)
+ , m_size(size)
+ {
+ }
+
+ MacroAssemblerCodePtr m_code;
+ RefPtr<ExecutablePool> m_executablePool;
+ size_t m_size;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerCodeRef_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 MacroAssemblerX86_h
+#define MacroAssemblerX86_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && PLATFORM(X86)
+
+#include "MacroAssemblerX86Common.h"
+
+namespace JSC {
+
+class MacroAssemblerX86 : public MacroAssemblerX86Common {
+public:
+ MacroAssemblerX86()
+ : m_isSSE2Present(isSSE2Present())
+ {
+ }
+
+ static const Scale ScalePtr = TimesFour;
+
+ using MacroAssemblerX86Common::add32;
+ using MacroAssemblerX86Common::and32;
+ using MacroAssemblerX86Common::sub32;
+ using MacroAssemblerX86Common::or32;
+ using MacroAssemblerX86Common::load32;
+ using MacroAssemblerX86Common::store32;
+ using MacroAssemblerX86Common::branch32;
+ using MacroAssemblerX86Common::call;
+ using MacroAssemblerX86Common::loadDouble;
+ using MacroAssemblerX86Common::convertInt32ToDouble;
+
+ void add32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ m_assembler.leal_mr(imm.m_value, src, dest);
+ }
+
+ void add32(Imm32 imm, AbsoluteAddress address)
+ {
+ m_assembler.addl_im(imm.m_value, address.m_ptr);
+ }
+
+ void addWithCarry32(Imm32 imm, AbsoluteAddress address)
+ {
+ m_assembler.adcl_im(imm.m_value, address.m_ptr);
+ }
+
+ void and32(Imm32 imm, AbsoluteAddress address)
+ {
+ m_assembler.andl_im(imm.m_value, address.m_ptr);
+ }
+
+ void or32(Imm32 imm, AbsoluteAddress address)
+ {
+ m_assembler.orl_im(imm.m_value, address.m_ptr);
+ }
+
+ void sub32(Imm32 imm, AbsoluteAddress address)
+ {
+ m_assembler.subl_im(imm.m_value, address.m_ptr);
+ }
+
+ void load32(void* address, RegisterID dest)
+ {
+ m_assembler.movl_mr(address, dest);
+ }
+
+ void loadDouble(void* address, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.movsd_mr(address, dest);
+ }
+
+ void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+ {
+ m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
+ }
+
+ void store32(Imm32 imm, void* address)
+ {
+ m_assembler.movl_i32m(imm.m_value, address);
+ }
+
+ void store32(RegisterID src, void* address)
+ {
+ m_assembler.movl_rm(src, address);
+ }
+
+ Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+ {
+ m_assembler.cmpl_rm(right, left.m_ptr);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+ {
+ m_assembler.cmpl_im(right.m_value, left.m_ptr);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Call call()
+ {
+ return Call(m_assembler.call(), Call::Linkable);
+ }
+
+ Call tailRecursiveCall()
+ {
+ return Call::fromTailJump(jump());
+ }
+
+ Call makeTailRecursiveCall(Jump oldJump)
+ {
+ return Call::fromTailJump(oldJump);
+ }
+
+
+ DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+ {
+ m_assembler.movl_i32r(initialValue.asIntptr(), dest);
+ return DataLabelPtr(this);
+ }
+
+ Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
+ dataLabel = DataLabelPtr(this);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
+ dataLabel = DataLabelPtr(this);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+ {
+ m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
+ return DataLabelPtr(this);
+ }
+
+ Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+ {
+ Label label(this);
+ load32(address, dest);
+ return label;
+ }
+
+ bool supportsFloatingPoint() const { return m_isSSE2Present; }
+ // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
+ bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
+
+private:
+ const bool m_isSSE2Present;
+
+ friend class LinkBuffer;
+ friend class RepatchBuffer;
+
+ static void linkCall(void* code, Call call, FunctionPtr function)
+ {
+ X86Assembler::linkCall(code, call.m_jmp, function.value());
+ }
+
+ static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+ {
+ X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+ }
+
+ static void repatchCall(CodeLocationCall call, FunctionPtr destination)
+ {
+ X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+ }
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerX86_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 MacroAssemblerX86Common_h
+#define MacroAssemblerX86Common_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "X86Assembler.h"
+#include "AbstractMacroAssembler.h"
+
+namespace JSC {
+
+class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
+public:
+
+ enum Condition {
+ Equal = X86Assembler::ConditionE,
+ NotEqual = X86Assembler::ConditionNE,
+ Above = X86Assembler::ConditionA,
+ AboveOrEqual = X86Assembler::ConditionAE,
+ Below = X86Assembler::ConditionB,
+ BelowOrEqual = X86Assembler::ConditionBE,
+ GreaterThan = X86Assembler::ConditionG,
+ GreaterThanOrEqual = X86Assembler::ConditionGE,
+ LessThan = X86Assembler::ConditionL,
+ LessThanOrEqual = X86Assembler::ConditionLE,
+ Overflow = X86Assembler::ConditionO,
+ Signed = X86Assembler::ConditionS,
+ Zero = X86Assembler::ConditionE,
+ NonZero = X86Assembler::ConditionNE
+ };
+
+ enum DoubleCondition {
+ DoubleEqual = X86Assembler::ConditionE,
+ DoubleNotEqual = X86Assembler::ConditionNE,
+ DoubleGreaterThan = X86Assembler::ConditionA,
+ DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
+ DoubleLessThan = X86Assembler::ConditionB,
+ DoubleLessThanOrEqual = X86Assembler::ConditionBE,
+ };
+
+ static const RegisterID stackPointerRegister = X86::esp;
+
+ // 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 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(Address src, RegisterID dest)
+ {
+ m_assembler.addl_mr(src.offset, src.base, dest);
+ }
+
+ void add32(RegisterID src, Address dest)
+ {
+ m_assembler.addl_rm(src, dest.offset, dest.base);
+ }
+
+ 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 and32(RegisterID src, Address dest)
+ {
+ m_assembler.andl_rm(src, dest.offset, dest.base);
+ }
+
+ void and32(Address src, RegisterID dest)
+ {
+ m_assembler.andl_mr(src.offset, src.base, dest);
+ }
+
+ void and32(Imm32 imm, Address address)
+ {
+ m_assembler.andl_im(imm.m_value, address.offset, address.base);
+ }
+
+ 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);
+ }
+
+ void mul32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.imull_rr(src, dest);
+ }
+
+ void mul32(Address src, RegisterID dest)
+ {
+ m_assembler.imull_mr(src.offset, src.base, dest);
+ }
+
+ void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ m_assembler.imull_i32r(src, imm.m_value, dest);
+ }
+
+ void neg32(RegisterID srcDest)
+ {
+ m_assembler.negl_r(srcDest);
+ }
+
+ void neg32(Address srcDest)
+ {
+ m_assembler.negl_m(srcDest.offset, srcDest.base);
+ }
+
+ void not32(RegisterID srcDest)
+ {
+ m_assembler.notl_r(srcDest);
+ }
+
+ void not32(Address srcDest)
+ {
+ m_assembler.notl_m(srcDest.offset, srcDest.base);
+ }
+
+ 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 or32(RegisterID src, Address dest)
+ {
+ m_assembler.orl_rm(src, dest.offset, dest.base);
+ }
+
+ void or32(Address src, RegisterID dest)
+ {
+ m_assembler.orl_mr(src.offset, src.base, dest);
+ }
+
+ void or32(Imm32 imm, Address address)
+ {
+ m_assembler.orl_im(imm.m_value, address.offset, address.base);
+ }
+
+ 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 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(Address src, RegisterID dest)
+ {
+ m_assembler.subl_mr(src.offset, src.base, dest);
+ }
+
+ void sub32(RegisterID src, Address dest)
+ {
+ m_assembler.subl_rm(src, dest.offset, dest.base);
+ }
+
+
+ void xor32(RegisterID src, RegisterID dest)
+ {
+ m_assembler.xorl_rr(src, dest);
+ }
+
+ void xor32(Imm32 imm, Address dest)
+ {
+ m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
+ }
+
+ void xor32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.xorl_ir(imm.m_value, dest);
+ }
+
+ void xor32(RegisterID src, Address dest)
+ {
+ m_assembler.xorl_rm(src, dest.offset, dest.base);
+ }
+
+ void xor32(Address src, RegisterID dest)
+ {
+ m_assembler.xorl_mr(src.offset, src.base, dest);
+ }
+
+
+ // 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 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);
+ }
+
+ DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+ {
+ m_assembler.movl_mr_disp32(address.offset, address.base, dest);
+ return DataLabel32(this);
+ }
+
+ void load16(BaseIndex address, RegisterID dest)
+ {
+ m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
+ }
+
+ DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
+ {
+ m_assembler.movl_rm_disp32(src, address.offset, address.base);
+ return DataLabel32(this);
+ }
+
+ 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);
+ }
+
+
+ // Floating-point operation:
+ //
+ // Presently only supports SSE, not x87 floating point.
+
+ void loadDouble(ImplicitAddress address, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.movsd_mr(address.offset, address.base, dest);
+ }
+
+ void storeDouble(FPRegisterID src, ImplicitAddress address)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.movsd_rm(src, address.offset, address.base);
+ }
+
+ void addDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.addsd_rr(src, dest);
+ }
+
+ void addDouble(Address src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.addsd_mr(src.offset, src.base, dest);
+ }
+
+ void divDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.divsd_rr(src, dest);
+ }
+
+ void divDouble(Address src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.divsd_mr(src.offset, src.base, dest);
+ }
+
+ void subDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.subsd_rr(src, dest);
+ }
+
+ void subDouble(Address src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.subsd_mr(src.offset, src.base, dest);
+ }
+
+ void mulDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.mulsd_rr(src, dest);
+ }
+
+ void mulDouble(Address src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.mulsd_mr(src.offset, src.base, dest);
+ }
+
+ void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.cvtsi2sd_rr(src, dest);
+ }
+
+ void convertInt32ToDouble(Address src, FPRegisterID dest)
+ {
+ m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
+ }
+
+ Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.ucomisd_rr(right, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchDouble(DoubleCondition cond, FPRegisterID left, Address right)
+ {
+ m_assembler.ucomisd_mr(right.offset, right.base, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ // Truncates 'src' to an integer, and places the resulting 'dest'.
+ // If the result is not representable as a 32 bit value, branch.
+ // May also branch for some values that are representable in 32 bits
+ // (specifically, in this case, INT_MIN).
+ Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.cvttsd2si_rr(src, dest);
+ return branch32(Equal, dest, Imm32(0x80000000));
+ }
+
+ void zeroDouble(FPRegisterID srcDest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.xorpd_rr(srcDest, srcDest);
+ }
+
+
+ // 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);
+ }
+
+
+ // 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);
+ }
+
+#if PLATFORM(X86_64)
+ 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 (src != dest)
+ m_assembler.movq_rr(src, dest);
+ }
+
+ void move(ImmPtr imm, RegisterID dest)
+ {
+ 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);
+ }
+
+ void swap(RegisterID reg1, RegisterID reg2)
+ {
+ m_assembler.xchgq_rr(reg1, reg2);
+ }
+
+ void signExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.movsxd_rr(src, dest);
+ }
+
+ void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.movl_rr(src, dest);
+ }
+#else
+ void move(RegisterID src, RegisterID dest)
+ {
+ if (src != dest)
+ m_assembler.movl_rr(src, dest);
+ }
+
+ void move(ImmPtr imm, RegisterID dest)
+ {
+ m_assembler.movl_i32r(imm.asIntptr(), dest);
+ }
+
+ void swap(RegisterID reg1, RegisterID reg2)
+ {
+ if (reg1 != reg2)
+ m_assembler.xchgl_rr(reg1, reg2);
+ }
+
+ void signExtend32ToPtr(RegisterID src, RegisterID dest)
+ {
+ move(src, dest);
+ }
+
+ void zeroExtend32ToPtr(RegisterID src, RegisterID 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.
+
+public:
+ Jump branch32(Condition cond, RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpl_rr(right, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, RegisterID left, Imm32 right)
+ {
+ if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+ m_assembler.testl_rr(left, left);
+ else
+ m_assembler.cmpl_ir(right.m_value, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, RegisterID left, Address right)
+ {
+ m_assembler.cmpl_mr(right.offset, right.base, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, Address left, RegisterID right)
+ {
+ m_assembler.cmpl_rm(right, left.offset, left.base);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, Address left, Imm32 right)
+ {
+ m_assembler.cmpl_im(right.m_value, left.offset, left.base);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+ {
+ m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+ {
+ m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+ {
+ ASSERT(!(right.m_value & 0xFFFF0000));
+
+ m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ m_assembler.testl_rr(reg, mask);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ // 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+ {
+ ASSERT((cond == Zero) || (cond == NonZero));
+ 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump jump()
+ {
+ return Jump(m_assembler.jmp());
+ }
+
+ 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 branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ add32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ add32(imm, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchAdd32(Condition cond, Imm32 src, Address dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ add32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchAdd32(Condition cond, RegisterID src, Address dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ add32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchAdd32(Condition cond, Address src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ add32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT(cond == Overflow);
+ mul32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchMul32(Condition cond, Address src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ mul32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ ASSERT(cond == Overflow);
+ mul32(imm, src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ sub32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ sub32(imm, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSub32(Condition cond, Imm32 imm, Address dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ sub32(imm, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSub32(Condition cond, RegisterID src, Address dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ sub32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSub32(Condition cond, Address src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ sub32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+ or32(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+
+ // Miscellaneous operations:
+
+ void breakpoint()
+ {
+ m_assembler.int3();
+ }
+
+ Call nearCall()
+ {
+ return Call(m_assembler.call(), Call::LinkableNear);
+ }
+
+ Call call(RegisterID target)
+ {
+ return Call(m_assembler.call(target), Call::None);
+ }
+
+ void call(Address address)
+ {
+ m_assembler.call_m(address.offset, address.base);
+ }
+
+ void ret()
+ {
+ m_assembler.ret();
+ }
+
+ void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+ {
+ m_assembler.cmpl_rr(right, left);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ }
+
+ void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
+ {
+ m_assembler.cmpl_mr(left.offset, left.base, right);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ }
+
+ void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+ {
+ if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+ m_assembler.testl_rr(left, left);
+ else
+ m_assembler.cmpl_ir(right.m_value, left);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ }
+
+ void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+ {
+ m_assembler.cmpl_rr(right, left);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+
+ void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+ {
+ if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+ m_assembler.testl_rr(left, left);
+ else
+ m_assembler.cmpl_ir(right.m_value, left);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+
+ // 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 setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+ {
+ 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);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ }
+
+ void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+ {
+ 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);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+
+protected:
+ X86Assembler::Condition x86Condition(Condition cond)
+ {
+ return static_cast<X86Assembler::Condition>(cond);
+ }
+
+ X86Assembler::Condition x86Condition(DoubleCondition cond)
+ {
+ return static_cast<X86Assembler::Condition>(cond);
+ }
+
+private:
+ // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
+ // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
+ friend class MacroAssemblerX86;
+
+#if PLATFORM(X86)
+#if PLATFORM(MAC)
+
+ // All X86 Macs are guaranteed to support at least SSE2,
+ static bool isSSE2Present()
+ {
+ return true;
+ }
+
+#else // PLATFORM(MAC)
+
+ enum SSE2CheckState {
+ NotCheckedSSE2,
+ HasSSE2,
+ NoSSE2
+ };
+
+ static bool isSSE2Present()
+ {
+ if (s_sse2CheckState == NotCheckedSSE2) {
+ // Default the flags value to zero; if the compiler is
+ // not MSVC or GCC we will read this as SSE2 not present.
+ int flags = 0;
+#if COMPILER(MSVC)
+ _asm {
+ mov eax, 1 // cpuid function 1 gives us the standard feature set
+ cpuid;
+ mov flags, edx;
+ }
+#elif COMPILER(GCC)
+ asm (
+ "movl $0x1, %%eax;"
+ "pushl %%ebx;"
+ "cpuid;"
+ "popl %%ebx;"
+ "movl %%edx, %0;"
+ : "=g" (flags)
+ :
+ : "%eax", "%ecx", "%edx"
+ );
+#endif
+ static const int SSE2FeatureBit = 1 << 26;
+ s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
+ }
+ // Only check once.
+ ASSERT(s_sse2CheckState != NotCheckedSSE2);
+
+ return s_sse2CheckState == HasSSE2;
+ }
+
+ static SSE2CheckState s_sse2CheckState;
+
+#endif // PLATFORM(MAC)
+#elif !defined(NDEBUG) // PLATFORM(X86)
+
+ // On x86-64 we should never be checking for SSE2 in a non-debug build,
+ // but non debug add this method to keep the asserts above happy.
+ static bool isSSE2Present()
+ {
+ return true;
+ }
+
+#endif
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerX86Common_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 MacroAssemblerX86_64_h
+#define MacroAssemblerX86_64_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && PLATFORM(X86_64)
+
+#include "MacroAssemblerX86Common.h"
+
+#define REPTACH_OFFSET_CALL_R11 3
+
+namespace JSC {
+
+class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
+protected:
+ static const X86::RegisterID scratchRegister = X86::r11;
+
+public:
+ static const Scale ScalePtr = TimesEight;
+
+ using MacroAssemblerX86Common::add32;
+ using MacroAssemblerX86Common::and32;
+ using MacroAssemblerX86Common::or32;
+ using MacroAssemblerX86Common::sub32;
+ using MacroAssemblerX86Common::load32;
+ using MacroAssemblerX86Common::store32;
+ using MacroAssemblerX86Common::call;
+ using MacroAssemblerX86Common::loadDouble;
+ using MacroAssemblerX86Common::convertInt32ToDouble;
+
+ void add32(Imm32 imm, AbsoluteAddress address)
+ {
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ add32(imm, Address(scratchRegister));
+ }
+
+ void and32(Imm32 imm, AbsoluteAddress address)
+ {
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ and32(imm, Address(scratchRegister));
+ }
+
+ void or32(Imm32 imm, AbsoluteAddress address)
+ {
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ or32(imm, Address(scratchRegister));
+ }
+
+ void sub32(Imm32 imm, AbsoluteAddress address)
+ {
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ sub32(imm, Address(scratchRegister));
+ }
+
+ void load32(void* address, RegisterID dest)
+ {
+ if (dest == X86::eax)
+ m_assembler.movl_mEAX(address);
+ else {
+ move(X86::eax, dest);
+ m_assembler.movl_mEAX(address);
+ swap(X86::eax, dest);
+ }
+ }
+
+ void loadDouble(void* address, FPRegisterID dest)
+ {
+ move(ImmPtr(address), scratchRegister);
+ loadDouble(scratchRegister, dest);
+ }
+
+ void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+ {
+ move(Imm32(*static_cast<int32_t*>(src.m_ptr)), scratchRegister);
+ m_assembler.cvtsi2sd_rr(scratchRegister, dest);
+ }
+
+ void store32(Imm32 imm, void* address)
+ {
+ move(X86::eax, scratchRegister);
+ move(imm, X86::eax);
+ m_assembler.movl_EAXm(address);
+ move(scratchRegister, X86::eax);
+ }
+
+ Call call()
+ {
+ DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+ Call result = Call(m_assembler.call(scratchRegister), Call::Linkable);
+ ASSERT(differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
+ return result;
+ }
+
+ Call tailRecursiveCall()
+ {
+ DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+ Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
+ ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
+ return Call::fromTailJump(newJump);
+ }
+
+ Call makeTailRecursiveCall(Jump oldJump)
+ {
+ oldJump.link(this);
+ DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+ Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
+ ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
+ return Call::fromTailJump(newJump);
+ }
+
+
+ void addPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.addq_rr(src, dest);
+ }
+
+ void addPtr(Imm32 imm, RegisterID srcDest)
+ {
+ m_assembler.addq_ir(imm.m_value, srcDest);
+ }
+
+ void addPtr(ImmPtr imm, RegisterID dest)
+ {
+ move(imm, scratchRegister);
+ m_assembler.addq_rr(scratchRegister, dest);
+ }
+
+ void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ m_assembler.leaq_mr(imm.m_value, src, dest);
+ }
+
+ void addPtr(Imm32 imm, Address address)
+ {
+ m_assembler.addq_im(imm.m_value, address.offset, address.base);
+ }
+
+ void addPtr(Imm32 imm, AbsoluteAddress address)
+ {
+ move(ImmPtr(address.m_ptr), scratchRegister);
+ addPtr(imm, Address(scratchRegister));
+ }
+
+ void andPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.andq_rr(src, dest);
+ }
+
+ void andPtr(Imm32 imm, RegisterID srcDest)
+ {
+ m_assembler.andq_ir(imm.m_value, srcDest);
+ }
+
+ void orPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.orq_rr(src, dest);
+ }
+
+ void orPtr(ImmPtr imm, RegisterID dest)
+ {
+ move(imm, scratchRegister);
+ m_assembler.orq_rr(scratchRegister, dest);
+ }
+
+ void orPtr(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.orq_ir(imm.m_value, dest);
+ }
+
+ void rshiftPtr(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.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);
+ }
+
+ void rshiftPtr(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.sarq_i8r(imm.m_value, dest);
+ }
+
+ void subPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.subq_rr(src, dest);
+ }
+
+ void subPtr(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.subq_ir(imm.m_value, dest);
+ }
+
+ void subPtr(ImmPtr imm, RegisterID dest)
+ {
+ move(imm, scratchRegister);
+ m_assembler.subq_rr(scratchRegister, dest);
+ }
+
+ void xorPtr(RegisterID src, RegisterID dest)
+ {
+ m_assembler.xorq_rr(src, dest);
+ }
+
+ void xorPtr(Imm32 imm, RegisterID srcDest)
+ {
+ m_assembler.xorq_ir(imm.m_value, srcDest);
+ }
+
+
+ void loadPtr(ImplicitAddress address, RegisterID dest)
+ {
+ m_assembler.movq_mr(address.offset, address.base, dest);
+ }
+
+ void loadPtr(BaseIndex address, RegisterID dest)
+ {
+ m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest);
+ }
+
+ void loadPtr(void* address, RegisterID dest)
+ {
+ if (dest == X86::eax)
+ m_assembler.movq_mEAX(address);
+ else {
+ move(X86::eax, dest);
+ m_assembler.movq_mEAX(address);
+ swap(X86::eax, dest);
+ }
+ }
+
+ DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
+ {
+ m_assembler.movq_mr_disp32(address.offset, address.base, dest);
+ return DataLabel32(this);
+ }
+
+ void storePtr(RegisterID src, ImplicitAddress address)
+ {
+ m_assembler.movq_rm(src, address.offset, address.base);
+ }
+
+ void storePtr(RegisterID src, BaseIndex address)
+ {
+ m_assembler.movq_rm(src, address.offset, address.base, address.index, address.scale);
+ }
+
+ void storePtr(RegisterID src, void* address)
+ {
+ if (src == X86::eax)
+ m_assembler.movq_EAXm(address);
+ else {
+ swap(X86::eax, src);
+ m_assembler.movq_EAXm(address);
+ swap(X86::eax, src);
+ }
+ }
+
+ void storePtr(ImmPtr imm, ImplicitAddress address)
+ {
+ intptr_t ptr = imm.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(ptr))
+ m_assembler.movq_i32m(static_cast<int>(ptr), address.offset, address.base);
+ else {
+ move(imm, scratchRegister);
+ storePtr(scratchRegister, address);
+ }
+ }
+
+ DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
+ {
+ m_assembler.movq_rm_disp32(src, address.offset, address.base);
+ return DataLabel32(this);
+ }
+
+ void movePtrToDouble(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.movq_rr(src, dest);
+ }
+
+ void moveDoubleToPtr(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.movq_rr(src, dest);
+ }
+
+ void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+ {
+ if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+ m_assembler.testq_rr(left, left);
+ else
+ m_assembler.cmpq_ir(right.m_value, left);
+ m_assembler.setCC_r(x86Condition(cond), dest);
+ m_assembler.movzbl_rr(dest, dest);
+ }
+
+ Jump branchPtr(Condition cond, RegisterID left, RegisterID right)
+ {
+ m_assembler.cmpq_rr(right, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
+ {
+ intptr_t imm = right.asIntptr();
+ if (CAN_SIGN_EXTEND_32_64(imm)) {
+ if (!imm)
+ m_assembler.testq_rr(left, left);
+ else
+ m_assembler.cmpq_ir(imm, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ } else {
+ move(right, scratchRegister);
+ return branchPtr(cond, left, scratchRegister);
+ }
+ }
+
+ Jump branchPtr(Condition cond, RegisterID left, Address right)
+ {
+ m_assembler.cmpq_mr(right.offset, right.base, left);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchPtr(Condition cond, AbsoluteAddress left, RegisterID right)
+ {
+ move(ImmPtr(left.m_ptr), scratchRegister);
+ return branchPtr(cond, Address(scratchRegister), right);
+ }
+
+ Jump branchPtr(Condition cond, Address left, RegisterID right)
+ {
+ m_assembler.cmpq_rm(right, left.offset, left.base);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchPtr(Condition cond, Address left, ImmPtr right)
+ {
+ move(right, scratchRegister);
+ return branchPtr(cond, left, scratchRegister);
+ }
+
+ Jump branchTestPtr(Condition cond, RegisterID reg, RegisterID mask)
+ {
+ m_assembler.testq_rr(reg, mask);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+ {
+ // 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1))
+ {
+ 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+ {
+ 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);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+
+ Jump branchAddPtr(Condition cond, RegisterID src, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ addPtr(src, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest)
+ {
+ ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
+ subPtr(imm, dest);
+ return Jump(m_assembler.jCC(x86Condition(cond)));
+ }
+
+ DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+ {
+ m_assembler.movq_i64r(initialValue.asIntptr(), dest);
+ return DataLabelPtr(this);
+ }
+
+ Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ dataLabel = moveWithPatch(initialRightValue, scratchRegister);
+ return branchPtr(cond, left, scratchRegister);
+ }
+
+ Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+ {
+ dataLabel = moveWithPatch(initialRightValue, scratchRegister);
+ return branchPtr(cond, left, scratchRegister);
+ }
+
+ DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+ {
+ DataLabelPtr label = moveWithPatch(initialValue, scratchRegister);
+ storePtr(scratchRegister, address);
+ return label;
+ }
+
+ Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+ {
+ Label label(this);
+ loadPtr(address, dest);
+ return label;
+ }
+
+ bool supportsFloatingPoint() const { return true; }
+ // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
+ bool supportsFloatingPointTruncate() const { return true; }
+
+private:
+ friend class LinkBuffer;
+ friend class RepatchBuffer;
+
+ static void linkCall(void* code, Call call, FunctionPtr function)
+ {
+ if (!call.isFlagSet(Call::Near))
+ X86Assembler::linkPointer(code, X86Assembler::labelFor(call.m_jmp, -REPTACH_OFFSET_CALL_R11), function.value());
+ else
+ X86Assembler::linkCall(code, call.m_jmp, function.value());
+ }
+
+ static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+ {
+ X86Assembler::repatchPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation(), destination.executableAddress());
+ }
+
+ static void repatchCall(CodeLocationCall call, FunctionPtr destination)
+ {
+ X86Assembler::repatchPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation(), destination.executableAddress());
+ }
+
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerX86_64_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.
+ */
+
+#ifndef RepatchBuffer_h
+#define RepatchBuffer_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include <MacroAssembler.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+// RepatchBuffer:
+//
+// This class is used to modify code after code generation has been completed,
+// and after the code has potentially already been executed. This mechanism is
+// used to apply optimizations to the code.
+//
+class RepatchBuffer {
+ typedef MacroAssemblerCodePtr CodePtr;
+
+public:
+ RepatchBuffer(CodeBlock* codeBlock)
+ {
+ JITCode& code = codeBlock->getJITCode();
+ m_start = code.start();
+ m_size = code.size();
+
+ ExecutableAllocator::makeWritable(m_start, m_size);
+ }
+
+ ~RepatchBuffer()
+ {
+ ExecutableAllocator::makeExecutable(m_start, m_size);
+ }
+
+ void relink(CodeLocationJump jump, CodeLocationLabel destination)
+ {
+ MacroAssembler::repatchJump(jump, destination);
+ }
+
+ void relink(CodeLocationCall call, CodeLocationLabel destination)
+ {
+ MacroAssembler::repatchCall(call, destination);
+ }
+
+ void relink(CodeLocationCall call, FunctionPtr destination)
+ {
+ MacroAssembler::repatchCall(call, destination);
+ }
+
+ void relink(CodeLocationNearCall nearCall, CodePtr destination)
+ {
+ MacroAssembler::repatchNearCall(nearCall, CodeLocationLabel(destination));
+ }
+
+ void relink(CodeLocationNearCall nearCall, CodeLocationLabel destination)
+ {
+ MacroAssembler::repatchNearCall(nearCall, destination);
+ }
+
+ void repatch(CodeLocationDataLabel32 dataLabel32, int32_t value)
+ {
+ MacroAssembler::repatchInt32(dataLabel32, value);
+ }
+
+ void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value)
+ {
+ MacroAssembler::repatchPointer(dataLabelPtr, value);
+ }
+
+ void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+ {
+ MacroAssembler::repatchLoadPtrToLEA(instruction);
+ }
+
+ void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
+ {
+ relink(CodeLocationCall(CodePtr(returnAddress)), label);
+ }
+
+ void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction)
+ {
+ relinkCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction));
+ }
+
+ void relinkCallerToFunction(ReturnAddressPtr returnAddress, FunctionPtr function)
+ {
+ relink(CodeLocationCall(CodePtr(returnAddress)), function);
+ }
+
+ void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
+ {
+ relink(CodeLocationNearCall(CodePtr(returnAddress)), label);
+ }
+
+ void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction)
+ {
+ relinkNearCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction));
+ }
+
+private:
+ void* m_start;
+ size_t m_size;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // RepatchBuffer_h
public:
typedef X86::RegisterID RegisterID;
typedef X86::XMMRegisterID XMMRegisterID;
+ typedef XMMRegisterID FPRegisterID;
+ typedef enum {
+ ConditionO,
+ ConditionNO,
+ ConditionB,
+ ConditionAE,
+ ConditionE,
+ ConditionNE,
+ ConditionBE,
+ ConditionA,
+ ConditionS,
+ ConditionNS,
+ ConditionP,
+ ConditionNP,
+ ConditionL,
+ ConditionGE,
+ ConditionLE,
+ ConditionG,
+
+ ConditionC = ConditionB,
+ ConditionNC = ConditionAE,
+ } Condition;
+
+private:
typedef enum {
OP_ADD_EvGv = 0x01,
OP_ADD_GvEv = 0x03,
OP_OR_GvEv = 0x0B,
OP_2BYTE_ESCAPE = 0x0F,
OP_AND_EvGv = 0x21,
+ OP_AND_GvEv = 0x23,
OP_SUB_EvGv = 0x29,
OP_SUB_GvEv = 0x2B,
PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
OP_XOR_EvGv = 0x31,
+ OP_XOR_GvEv = 0x33,
OP_CMP_EvGv = 0x39,
OP_CMP_GvEv = 0x3B,
#if PLATFORM(X86_64)
OP2_ADDSD_VsdWsd = 0x58,
OP2_MULSD_VsdWsd = 0x59,
OP2_SUBSD_VsdWsd = 0x5C,
+ OP2_DIVSD_VsdWsd = 0x5E,
+ OP2_XORPD_VpdWpd = 0x57,
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_JCC_rel32 = 0x80,
+ OP_SETCC = 0x90,
OP2_IMUL_GvEv = 0xAF,
OP2_MOVZX_GvEb = 0xB6,
OP2_MOVZX_GvEw = 0xB7,
OP2_PEXTRW_GdUdIb = 0xC5,
} TwoByteOpcodeID;
+ TwoByteOpcodeID jccRel32(Condition cond)
+ {
+ return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond);
+ }
+
+ TwoByteOpcodeID setccOpcode(Condition cond)
+ {
+ return (TwoByteOpcodeID)(OP_SETCC + cond);
+ }
+
typedef enum {
GROUP1_OP_ADD = 0,
GROUP1_OP_OR = 1,
+ GROUP1_OP_ADC = 2,
GROUP1_OP_AND = 4,
GROUP1_OP_SUB = 5,
GROUP1_OP_XOR = 6,
GROUP3_OP_TEST = 0,
GROUP3_OP_NOT = 2,
+ GROUP3_OP_NEG = 3,
GROUP3_OP_IDIV = 7,
GROUP5_OP_CALLN = 2,
GROUP11_MOV = 0,
} GroupOpcodeID;
- // Opaque label types
-
-private:
class X86InstructionFormatter;
public:
public:
JmpDst()
: m_offset(-1)
+ , m_used(false)
{
}
+ bool isUsed() const { return m_used; }
+ void used() { m_used = true; }
private:
JmpDst(int offset)
: m_offset(offset)
+ , m_used(false)
{
+ ASSERT(m_offset == offset);
}
- int m_offset;
+ int m_offset : 31;
+ bool m_used : 1;
};
X86Assembler()
// Arithmetic operations:
+#if !PLATFORM(X86_64)
+ void adcl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADC, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
+#endif
+
void addl_rr(RegisterID src, RegisterID dst)
{
m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
}
+ void addl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset);
+ }
+
void addl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
m_formatter.immediate32(imm);
}
}
+
+ void addq_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
#else
void addl_im(int imm, void* addr)
{
m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
}
+ void andl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_AND_GvEv, dst, base, offset);
+ }
+
+ void andl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_AND_EvGv, src, base, offset);
+ }
+
void andl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
}
}
+ void andl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
#if PLATFORM(X86_64)
void andq_rr(RegisterID src, RegisterID dst)
{
m_formatter.immediate32(imm);
}
}
+#else
+ void andl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
#endif
+ void negl_r(RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, dst);
+ }
+
+ void negl_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, base, offset);
+ }
+
void notl_r(RegisterID dst)
{
m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
}
+ void notl_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset);
+ }
+
void orl_rr(RegisterID src, RegisterID dst)
{
m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
}
+ void orl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_OR_EvGv, src, base, offset);
+ }
+
void orl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
}
}
+ void orl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
#if PLATFORM(X86_64)
void orq_rr(RegisterID src, RegisterID dst)
{
m_formatter.immediate32(imm);
}
}
+#else
+ void orl_im(int imm, void* addr)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, addr);
+ m_formatter.immediate32(imm);
+ }
+ }
#endif
void subl_rr(RegisterID src, RegisterID dst)
m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
}
+ void subl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset);
+ }
+
void subl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
}
+ void xorl_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, offset);
+ }
+
+ void xorl_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_XOR_EvGv, src, base, offset);
+ }
+
+ void xorl_im(int imm, int offset, RegisterID base)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
void xorl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
{
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
}
-
+
+ void imull_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset);
+ }
+
void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
{
m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset);
}
+ void cmpq_mr(int offset, RegisterID base, RegisterID src)
+ {
+ m_formatter.oneByteOp64(OP_CMP_GvEv, src, base, offset);
+ }
+
void cmpq_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
}
+ void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
+ m_formatter.immediate16(imm);
+ }
+ }
+
void testl_rr(RegisterID src, RegisterID dst)
{
m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
}
#endif
+ void testw_rr(RegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
+ }
+
void testb_i8r(int imm, RegisterID dst)
{
m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
m_formatter.immediate8(imm);
}
+ void setCC_r(Condition cond, RegisterID dst)
+ {
+ m_formatter.twoByteOp8(setccOpcode(cond), (GroupOpcodeID)0, dst);
+ }
+
void sete_r(RegisterID dst)
{
- m_formatter.twoByteOp8(OP_SETE, (GroupOpcodeID)0, dst);
+ m_formatter.twoByteOp8(setccOpcode(ConditionE), (GroupOpcodeID)0, dst);
}
void setz_r(RegisterID dst)
void setne_r(RegisterID dst)
{
- m_formatter.twoByteOp8(OP_SETNE, (GroupOpcodeID)0, dst);
+ m_formatter.twoByteOp8(setccOpcode(ConditionNE), (GroupOpcodeID)0, dst);
}
void setnz_r(RegisterID dst)
m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
}
+ void movq_EAXm(void* addr)
+ {
+ m_formatter.oneByteOp64(OP_MOV_OvEAX);
+ 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);
m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
}
+ void movq_i32m(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
+ m_formatter.immediate32(imm);
+ }
+
void movq_i64r(int64_t imm, RegisterID dst)
{
m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
#else
+ void movl_rm(RegisterID src, void* addr)
+ {
+ if (src == X86::eax)
+ movl_EAXm(addr);
+ else
+ m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
+ }
+
void movl_mr(void* addr, RegisterID dst)
{
if (dst == X86::eax)
{
m_formatter.oneByteOp(OP_LEA, dst, base, offset);
}
+#if PLATFORM(X86_64)
+ void leaq_mr(int offset, RegisterID base, RegisterID dst)
+ {
+ m_formatter.oneByteOp64(OP_LEA, dst, base, offset);
+ }
+#endif
// Flow control:
m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
return JmpSrc(m_formatter.size());
}
+
+ void call_m(int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, base, offset);
+ }
JmpSrc jmp()
{
return m_formatter.immediateRel32();
}
- void jmp_r(RegisterID dst)
+ // Return a JmpSrc so we have a label to the jump, so we can use this
+ // To make a tail recursive call on x86-64. The MacroAssembler
+ // really shouldn't wrap this as a Jump, since it can't be linked. :-/
+ JmpSrc jmp_r(RegisterID dst)
{
m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
+ return JmpSrc(m_formatter.size());
}
void jmp_m(int offset, RegisterID base)
JmpSrc jne()
{
- m_formatter.twoByteOp(OP2_JNE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionNE));
return m_formatter.immediateRel32();
}
JmpSrc je()
{
- m_formatter.twoByteOp(OP2_JE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionE));
return m_formatter.immediateRel32();
}
+ JmpSrc jz()
+ {
+ return je();
+ }
+
JmpSrc jl()
{
- m_formatter.twoByteOp(OP2_JL_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionL));
return m_formatter.immediateRel32();
}
JmpSrc jb()
{
- m_formatter.twoByteOp(OP2_JB_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionB));
return m_formatter.immediateRel32();
}
JmpSrc jle()
{
- m_formatter.twoByteOp(OP2_JLE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionLE));
return m_formatter.immediateRel32();
}
JmpSrc jbe()
{
- m_formatter.twoByteOp(OP2_JBE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionBE));
return m_formatter.immediateRel32();
}
JmpSrc jge()
{
- m_formatter.twoByteOp(OP2_JGE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionGE));
return m_formatter.immediateRel32();
}
JmpSrc jg()
{
- m_formatter.twoByteOp(OP2_JG_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionG));
return m_formatter.immediateRel32();
}
JmpSrc ja()
{
- m_formatter.twoByteOp(OP2_JA_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionA));
return m_formatter.immediateRel32();
}
JmpSrc jae()
{
- m_formatter.twoByteOp(OP2_JAE_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionAE));
return m_formatter.immediateRel32();
}
JmpSrc jo()
{
- m_formatter.twoByteOp(OP2_JO_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionO));
return m_formatter.immediateRel32();
}
JmpSrc jp()
{
- m_formatter.twoByteOp(OP2_JP_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionP));
return m_formatter.immediateRel32();
}
JmpSrc js()
{
- m_formatter.twoByteOp(OP2_JS_rel32);
+ m_formatter.twoByteOp(jccRel32(ConditionS));
+ return m_formatter.immediateRel32();
+ }
+
+ JmpSrc jCC(Condition cond)
+ {
+ m_formatter.twoByteOp(jccRel32(cond));
return m_formatter.immediateRel32();
}
m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
}
+ void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
+ }
+
+#if !PLATFORM(X86_64)
+ void cvtsi2sd_mr(void* address, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
+ }
+#endif
+
void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
}
+#if !PLATFORM(X86_64)
+ void movsd_mr(void* address, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
+ }
+#endif
+
void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
}
+ void ucomisd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void divsd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+ }
+
+ void divsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
+ }
+
+ void xorpd_rr(XMMRegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_66);
+ m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
+ }
+
// Misc instructions:
void int3()
return JmpDst(m_formatter.size());
}
+ static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
+ {
+ return JmpDst(jump.m_offset + offset);
+ }
+
JmpDst align(int alignment)
{
while (!m_formatter.isAligned(alignment))
}
// Linking & patching:
+ //
+ // 'link' and 'patch' methods are for use on unprotected code - such as the code
+ // within the AssemblerBuffer, and code being patched by the patch buffer. Once
+ // code has been finalized it is (platform support permitting) within a non-
+ // writable region of memory; to modify the code in an execute-only execuable
+ // pool the 'repatch' and 'relink' methods should be used.
- void link(JmpSrc from, JmpDst to)
+ void linkJump(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;
+ ASSERT(to.m_offset != -1);
+
+ char* code = reinterpret_cast<char*>(m_formatter.data());
+ setRel32(code + from.m_offset, code + to.m_offset);
}
- static void patchAddress(void* code, JmpDst position, void* value)
+ static void linkJump(void* code, JmpSrc from, void* to)
{
- ASSERT(position.m_offset != -1);
-
- reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value;
+ ASSERT(from.m_offset != -1);
+
+ setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
}
-
- static void link(void* code, JmpSrc from, void* to)
+
+ static void linkCall(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);
+
+ setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
+ }
+
+ static void linkPointer(void* code, JmpDst where, void* value)
+ {
+ ASSERT(where.m_offset != -1);
+
+ setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
+ }
+
+ static void relinkJump(void* from, void* to)
+ {
+ setRel32(from, to);
+ }
+
+ static void relinkCall(void* from, void* to)
+ {
+ setRel32(from, to);
+ }
+
+ static void repatchInt32(void* where, int32_t value)
+ {
+ setInt32(where, value);
+ }
+
+ static void repatchPointer(void* where, void* value)
+ {
+ setPointer(where, value);
+ }
+
+ static void repatchLoadPtrToLEA(void* where)
+ {
+#if PLATFORM(X86_64)
+ // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
+ // Skip over the prefix byte.
+ where = reinterpret_cast<char*>(where) + 1;
+#endif
+ *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
}
+ static unsigned getCallReturnOffset(JmpSrc call)
+ {
+ ASSERT(call.m_offset >= 0);
+ return call.m_offset;
+ }
+
static void* getRelocatedAddress(void* code, JmpSrc jump)
{
+ ASSERT(jump.m_offset != -1);
+
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
}
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);
private:
+ static void setPointer(void* where, void* value)
+ {
+ reinterpret_cast<void**>(where)[-1] = value;
+ }
+
+ static void setInt32(void* where, int32_t value)
+ {
+ reinterpret_cast<int32_t*>(where)[-1] = value;
+ }
+
+ static void setRel32(void* from, void* to)
+ {
+ intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
+ ASSERT(offset == static_cast<int32_t>(offset));
+
+ setInt32(from, offset);
+ }
+
class X86InstructionFormatter {
static const int maxInstructionSize = 16;
memoryModRM(reg, base, index, scale, offset);
}
+#if !PLATFORM(X86_64)
+ void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address)
+ {
+ m_buffer.ensureSpace(maxInstructionSize);
+ m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+ m_buffer.putByteUnchecked(opcode);
+ memoryModRM(reg, address);
+ }
+#endif
+
#if PLATFORM(X86_64)
// Quad-word-sized operands:
//
m_buffer.putByteUnchecked(imm);
}
+ void immediate16(int imm)
+ {
+ m_buffer.putShortUnchecked(imm);
+ }
+
void immediate32(int imm)
{
m_buffer.putIntUnchecked(imm);
{
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));
+ m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7));
}
void registerModRM(int reg, RegisterID rm)
return result;
}
-static UString valueToSourceString(ExecState* exec, JSValuePtr val)
+static UString valueToSourceString(ExecState* exec, JSValue val)
{
+ if (!val)
+ return "0";
+
if (val.isString()) {
UString result("\"");
result += escapeQuotes(val.toString(exec)) + "\"";
return (UString("r") + UString::from(r)).UTF8String();
}
-static CString constantName(ExecState* exec, int k, JSValuePtr value)
+static CString constantName(ExecState* exec, int k, JSValue value)
{
return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
}
unsigned registerIndex = m_numVars;
size_t i = 0;
do {
- printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());
+ printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).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;
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());
+ case op_init_arguments: {
+ printf("[%4d] init_arguments\n", location);
break;
}
- case op_unexpected_load: {
+ case op_convert_this: {
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());
+ printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
break;
}
case op_new_object: {
}
case op_div: {
printBinaryOp(location, it, "div");
+ ++it;
break;
}
case op_mod: {
}
case op_resolve_global: {
int r0 = (++it)->u.operand;
- JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
+ JSValue scope = JSValue((++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;
}
case op_get_global_var: {
int r0 = (++it)->u.operand;
- JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
+ JSValue scope = JSValue((++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);
+ JSValue scope = JSValue((++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());
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;
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_method_check: {
+ printf("[%4d] op_method_check\n", location);
+ break;
+ }
case op_del_by_id: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
printConditionalJump(begin, it, location, "jneq_null");
break;
}
+ case op_jneq_ptr: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+ break;
+ }
case op_jnless: {
int r0 = (++it)->u.operand;
int r1 = (++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_jnlesseq: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jnlesseq\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;
printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
break;
}
+ case op_call_varargs: {
+ int dst = (++it)->u.operand;
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), registerName(argCount).c_str(), registerOffset);
+ break;
+ }
+ case op_load_varargs: {
+ printUnaryOp(location, it, "load_varargs");
+ break;
+ }
case op_tear_off_activation: {
int r0 = (++it)->u.operand;
printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
break;
}
+ case op_strcat: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int count = (++it)->u.operand;
+ printf("[%4d] op_strcat\t %s, %s, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), count);
+ break;
+ }
+ case op_to_primitive: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] op_to_primitive\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;
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());
+ printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str());
break;
}
case op_jsr: {
#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
macro(regexps) \
macro(functions) \
- macro(unexpectedConstants) \
macro(exceptionHandlers) \
macro(immediateSwitchJumpTables) \
macro(characterSwitchJumpTables) \
#endif
}
+CodeBlock::CodeBlock(ScopeNode* ownerNode)
+ : m_numCalleeRegisters(0)
+ , m_numVars(0)
+ , m_numParameters(0)
+ , m_ownerNode(ownerNode)
+ , m_globalData(0)
+#ifndef NDEBUG
+ , m_instructionCount(0)
+#endif
+ , m_needsFullScopeChain(false)
+ , m_usesEval(false)
+ , m_isNumericCompareFunction(false)
+ , m_codeType(NativeCode)
+ , m_source(0)
+ , m_sourceOffset(0)
+ , m_exceptionInfo(0)
+{
+#if DUMP_CODE_BLOCK_STATISTICS
+ liveCodeBlockSet.add(this);
+#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)
callLinkInfo->callee->removeCaller(callLinkInfo);
}
+ for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
+ if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) {
+ structure->deref();
+ // Both members must be filled at the same time
+ ASSERT(m_methodCallLinkInfos[i].cachedPrototypeStructure);
+ m_methodCallLinkInfos[i].cachedPrototypeStructure->deref();
+ }
+ }
+
+#if ENABLE(JIT_OPTIMIZE_CALL)
unlinkCallers();
#endif
+#endif // !ENABLE(JIT)
+
#if DUMP_CODE_BLOCK_STATISTICS
liveCodeBlockSet.remove(this);
#endif
}
-#if ENABLE(JIT)
+#if ENABLE(JIT_OPTIMIZE_CALL)
void CodeBlock::unlinkCallers()
{
size_t size = m_linkedCallerList.size();
void CodeBlock::derefStructures(Instruction* vPC) const
{
+ ASSERT(m_codeType != NativeCode);
Interpreter* interpreter = m_globalData->interpreter;
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
void CodeBlock::refStructures(Instruction* vPC) const
{
+ ASSERT(m_codeType != NativeCode);
Interpreter* interpreter = m_globalData->interpreter;
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
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)
{
+ ASSERT(m_codeType != NativeCode);
if (m_exceptionInfo)
return;
#if ENABLE(JIT)
JIT::compile(m_globalData, &newCodeBlock);
- ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
+ ASSERT(newFunctionBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size());
#endif
m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
#if ENABLE(JIT)
JIT::compile(m_globalData, &newCodeBlock);
- ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
+ ASSERT(newEvalBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size());
#endif
m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
{
+ ASSERT(m_codeType != NativeCode);
ASSERT(bytecodeOffset < m_instructionCount);
if (!m_rareData)
int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
{
+ ASSERT(m_codeType != NativeCode);
ASSERT(bytecodeOffset < m_instructionCount);
reparseForExceptionInfoIfNecessary(callFrame);
int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
{
+ ASSERT(m_codeType != NativeCode);
ASSERT(bytecodeOffset < m_instructionCount);
reparseForExceptionInfoIfNecessary(callFrame);
bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
{
+ ASSERT(m_codeType != NativeCode);
ASSERT(bytecodeOffset < m_instructionCount);
reparseForExceptionInfoIfNecessary(callFrame);
#if ENABLE(JIT)
bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
{
+ ASSERT(m_codeType != NativeCode);
ASSERT(bytecodeOffset < m_instructionCount);
if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
#if !ENABLE(JIT)
bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
{
+ ASSERT(m_codeType != NativeCode);
if (m_globalResolveInstructions.isEmpty())
return false;
#else
bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
{
+ ASSERT(m_codeType != NativeCode);
if (m_globalResolveInfos.isEmpty())
return false;
#endif
#if ENABLE(JIT)
-void CodeBlock::setJITCode(JITCodeRef& jitCode)
+void CodeBlock::setJITCode(JITCode jitCode)
{
- m_jitCode = jitCode;
+ ASSERT(m_codeType != NativeCode);
+ ownerNode()->setJITCode(jitCode);
#if !ENABLE(OPCODE_SAMPLING)
if (!BytecodeGenerator::dumpsGeneratedCode())
m_instructions.clear();
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();
#include "EvalCodeCache.h"
#include "Instruction.h"
+#include "JITCode.h"
#include "JSGlobalObject.h"
#include "JumpTable.h"
#include "Nodes.h"
#include "RegExp.h"
#include "UString.h"
+#include <wtf/FastAllocBase.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#include "StructureStubInfo.h"
#endif
+// Register numbers used in bytecode operations have different meaning accoring to their ranges:
+// 0x80000000-0xFFFFFFFF Negative indicies from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
+// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
+// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
+static const int FirstConstantRegisterIndex = 0x40000000;
+
namespace JSC {
class ExecState;
- enum CodeType { GlobalCode, EvalCode, FunctionCode };
+ enum CodeType { GlobalCode, EvalCode, FunctionCode, NativeCode };
static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
uint32_t target;
uint32_t scopeDepth;
#if ENABLE(JIT)
- void* nativeCode;
+ CodeLocationLabel 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,
#if ENABLE(JIT)
struct CallLinkInfo {
CallLinkInfo()
- : callReturnLocation(0)
- , hotPathBegin(0)
- , hotPathOther(0)
- , coldPathOther(0)
- , callee(0)
+ : callee(0)
{
}
unsigned bytecodeIndex;
- void* callReturnLocation;
- void* hotPathBegin;
- void* hotPathOther;
- void* coldPathOther;
+ CodeLocationNearCall callReturnLocation;
+ CodeLocationDataLabelPtr hotPathBegin;
+ CodeLocationNearCall hotPathOther;
+ CodeBlock* ownerCodeBlock;
CodeBlock* callee;
unsigned position;
bool isLinked() { return callee; }
};
+ struct MethodCallLinkInfo {
+ MethodCallLinkInfo()
+ : cachedStructure(0)
+ , cachedPrototypeStructure(0)
+ {
+ }
+
+ CodeLocationCall callReturnLocation;
+ CodeLocationDataLabelPtr structureLabel;
+ Structure* cachedStructure;
+ Structure* cachedPrototypeStructure;
+ };
+
struct FunctionRegisterInfo {
FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
: bytecodeOffset(bytecodeOffset)
unsigned bytecodeOffset;
};
- struct PC {
- PC(ptrdiff_t nativePCOffset, unsigned bytecodeIndex)
- : nativePCOffset(nativePCOffset)
+ // This structure is used to map from a call return location
+ // (given as an offset in bytes into the JIT code) back to
+ // the bytecode index of the corresponding bytecode operation.
+ // This is then used to look up the corresponding handler.
+ struct CallReturnOffsetToBytecodeIndex {
+ CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset, unsigned bytecodeIndex)
+ : callReturnOffset(callReturnOffset)
, bytecodeIndex(bytecodeIndex)
{
}
- ptrdiff_t nativePCOffset;
+ unsigned callReturnOffset;
unsigned bytecodeIndex;
};
inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
{
- return structureStubInfo->callReturnLocation;
+ return structureStubInfo->callReturnLocation.executableAddress();
}
inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
{
- return callLinkInfo->callReturnLocation;
+ return callLinkInfo->callReturnLocation.executableAddress();
+ }
+
+ inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo)
+ {
+ return methodCallLinkInfo->callReturnLocation.executableAddress();
}
- inline ptrdiff_t getNativePCOffset(PC* pc)
+ inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc)
{
- return pc->nativePCOffset;
+ return pc->callReturnOffset;
}
// Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
}
#endif
- class CodeBlock {
+ class CodeBlock : public WTF::FastAllocBase {
friend class JIT;
public:
+ CodeBlock(ScopeNode* ownerNode);
CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
~CodeBlock();
void mark();
void refStructures(Instruction* vPC) const;
void derefStructures(Instruction* vPC) const;
-#if ENABLE(JIT)
+#if ENABLE(JIT_OPTIMIZE_CALL)
void unlinkCallers();
#endif
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;
+ return index >= m_numVars;
}
HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
m_linkedCallerList.shrink(lastPos);
}
- StructureStubInfo& getStubInfo(void* returnAddress)
+ StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress)
{
- return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
+ return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value()));
}
- CallLinkInfo& getCallLinkInfo(void* returnAddress)
+ CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
{
- return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
+ return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
}
- unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC)
+ MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress)
+ {
+ return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
+ }
+
+ unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress)
{
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;
+ return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(m_exceptionInfo->m_callReturnIndexVector.begin(), m_exceptionInfo->m_callReturnIndexVector.size(), ownerNode()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex;
}
bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
#endif
#if ENABLE(JIT)
- void setJITCode(JITCodeRef& jitCode);
- void* jitCode() { return m_jitCode.code; }
- ExecutablePool* executablePool() { return m_jitCode.executablePool.get(); }
+ JITCode& getJITCode() { return ownerNode()->generatedJITCode(); }
+ void setJITCode(JITCode);
+ ExecutablePool* executablePool() { return ownerNode()->getExecutablePool(); }
#endif
ScopeNode* ownerNode() const { return m_ownerNode; }
CodeType codeType() const { return m_codeType; }
- SourceProvider* source() const { return m_source.get(); }
- unsigned sourceOffset() const { return m_sourceOffset; }
+ SourceProvider* source() const { ASSERT(m_codeType != NativeCode); return m_source.get(); }
+ unsigned sourceOffset() const { ASSERT(m_codeType != NativeCode); return m_sourceOffset; }
size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
+ void addMethodCallLinkInfos(unsigned n) { m_methodCallLinkInfos.grow(n); }
+ MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
+
void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
#endif
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; }
+ Vector<CallReturnOffsetToBytecodeIndex>& callReturnIndexVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_callReturnIndexVector; }
#endif
// Constant Pool
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]; }
+ Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
+ ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; }
+ ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); }
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(); }
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(); }
SymbolTable& symbolTable() { return m_symbolTable; }
- EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
+ EvalCodeCache& evalCodeCache() { ASSERT(m_codeType != NativeCode); 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;
void createRareDataIfNecessary()
{
+ ASSERT(m_codeType != NativeCode);
if (!m_rareData)
m_rareData.set(new RareData);
}
#ifndef NDEBUG
unsigned m_instructionCount;
#endif
-#if ENABLE(JIT)
- JITCodeRef m_jitCode;
-#endif
int m_thisRegister;
Vector<StructureStubInfo> m_structureStubInfos;
Vector<GlobalResolveInfo> m_globalResolveInfos;
Vector<CallLinkInfo> m_callLinkInfos;
+ Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
Vector<CallLinkInfo*> m_linkedCallerList;
#endif
Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
#if ENABLE(JIT)
- Vector<PC> m_pcVector;
+ Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
#endif
};
OwnPtr<ExceptionInfo> m_exceptionInfo;
// Rare Constants
Vector<RefPtr<FuncDeclNode> > m_functions;
- Vector<JSValuePtr> m_unexpectedConstants;
Vector<RefPtr<RegExp> > m_regexps;
// Jump Tables
int m_baseScopeDepth;
};
+ inline Register& ExecState::r(int index)
+ {
+ CodeBlock* codeBlock = this->codeBlock();
+ if (codeBlock->isConstantRegisterIndex(index))
+ return codeBlock->constantRegister(index);
+ return this[index];
+ }
+
} // namespace JSC
#endif // CodeBlock_h
class EvalCodeCache {
public:
- PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValuePtr& exceptionValue)
+ PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
{
RefPtr<EvalNode> evalNode;
#ifndef Instruction_h
#define Instruction_h
+#include "MacroAssembler.h"
#include "Opcode.h"
#include "Structure.h"
#include <wtf/VectorTraits.h>
-#define POLYMORPHIC_LIST_CACHE_SIZE 4
+#define POLYMORPHIC_LIST_CACHE_SIZE 8
namespace JSC {
+ // *Sigh*, If the JIT is enabled we need to track the stubRountine (of type CodeLocationLabel),
+ // If the JIT is not in use we don't actually need the variable (that said, if the JIT is not in use we don't
+ // curently actually use PolymorphicAccessStructureLists, which we should). Anyway, this seems like the best
+ // solution for now - will need to something smarter if/when we actually want mixed-mode operation.
+#if ENABLE(JIT)
+ typedef CodeLocationLabel PolymorphicAccessStructureListStubRoutineType;
+#else
+ typedef void* PolymorphicAccessStructureListStubRoutineType;
+#endif
+
class JSCell;
class Structure;
class StructureChain;
struct PolymorphicAccessStructureList {
struct PolymorphicStubInfo {
bool isChain;
- void* stubRoutine;
+ PolymorphicAccessStructureListStubRoutineType stubRoutine;
Structure* base;
union {
Structure* proto;
StructureChain* chain;
} u;
- void set(void* _stubRoutine, Structure* _base)
+ void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
{
stubRoutine = _stubRoutine;
base = _base;
isChain = false;
}
- void set(void* _stubRoutine, Structure* _base, Structure* _proto)
+ void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
{
stubRoutine = _stubRoutine;
base = _base;
isChain = false;
}
- void set(void* _stubRoutine, Structure* _base, StructureChain* _chain)
+ void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
{
stubRoutine = _stubRoutine;
base = _base;
}
} list[POLYMORPHIC_LIST_CACHE_SIZE];
- PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase)
+ PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase)
{
list[0].set(stubRoutine, firstBase);
}
- PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, Structure* firstProto)
+ PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
{
list[0].set(stubRoutine, firstBase, firstProto);
}
- PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, StructureChain* firstChain)
+ PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
{
list[0].set(stubRoutine, firstBase, firstChain);
}
#ifndef JumpTable_h
#define JumpTable_h
+#include "MacroAssembler.h"
#include "UString.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
struct OffsetLocation {
int32_t branchOffset;
#if ENABLE(JIT)
- void* ctiOffset;
+ CodeLocationLabel ctiOffset;
#endif
};
typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
StringOffsetTable offsetTable;
#if ENABLE(JIT)
- void* ctiDefault; // FIXME: it should not be necessary to store this.
+ CodeLocationLabel ctiDefault; // FIXME: it should not be necessary to store this.
#endif
inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
}
#if ENABLE(JIT)
- inline void* ctiForValue(UString::Rep* value)
+ inline CodeLocationLabel ctiForValue(UString::Rep* value)
{
StringOffsetTable::const_iterator end = offsetTable.end();
StringOffsetTable::const_iterator loc = offsetTable.find(value);
Vector<int32_t> branchOffsets;
int32_t min;
#if ENABLE(JIT)
- Vector<void*> ctiOffsets;
- void* ctiDefault;
+ Vector<CodeLocationLabel> ctiOffsets;
+ CodeLocationLabel ctiDefault;
#endif
int32_t offsetForValue(int32_t value, int32_t defaultOffset);
}
#if ENABLE(JIT)
- inline void* ctiForValue(int32_t value)
+ inline CodeLocationLabel ctiForValue(int32_t value)
{
if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
return ctiOffsets[value - min];
#define FOR_EACH_OPCODE_ID(macro) \
macro(op_enter, 1) \
macro(op_enter_with_activation, 2) \
+ macro(op_init_arguments, 1) \
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_negate, 3) \
macro(op_add, 5) \
macro(op_mul, 5) \
- macro(op_div, 4) \
+ macro(op_div, 5) \
macro(op_mod, 4) \
macro(op_sub, 5) \
\
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_jfalse, 3) \
macro(op_jeq_null, 3) \
macro(op_jneq_null, 3) \
+ macro(op_jneq_ptr, 4) \
macro(op_jnless, 4) \
+ macro(op_jnlesseq, 4) \
macro(op_jmp_scopes, 3) \
macro(op_loop, 2) \
macro(op_loop_if_true, 3) \
macro(op_new_func_exp, 3) \
macro(op_call, 5) \
macro(op_call_eval, 5) \
+ macro(op_call_varargs, 5) \
+ macro(op_load_varargs, 3) \
macro(op_tear_off_activation, 2) \
macro(op_tear_off_arguments, 1) \
macro(op_ret, 2) \
+ macro(op_method_check, 1) \
\
macro(op_construct, 7) \
macro(op_construct_verify, 3) \
+ macro(op_strcat, 4) \
+ macro(op_to_primitive, 3) \
\
macro(op_get_pnames, 3) \
macro(op_next_pname, 4) \
#define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS);
- #undef OPCODE_ID_SIZES
+ #undef OPCODE_ID_LENGTHS
#define OPCODE_LENGTH(opcode) opcode##_length
#undef VERIFY_OPCODE_ID
#if HAVE(COMPUTED_GOTO)
- typedef void* Opcode;
+ typedef const void* Opcode;
#else
typedef OpcodeID Opcode;
#endif
namespace JSC {
-void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC)
+#if ENABLE(SAMPLING_FLAGS)
+
+void SamplingFlags::sample()
{
- if (!m_samples) {
- m_size = codeBlock->instructions().size();
- m_samples = static_cast<int*>(calloc(m_size, sizeof(int)));
- m_codeBlock = codeBlock;
+ uint32_t mask = 1 << 31;
+ unsigned index;
+
+ for (index = 0; index < 32; ++index) {
+ if (mask & s_flags)
+ break;
+ mask >>= 1;
}
- ++m_sampleCount;
+ s_flagCounts[32 - index]++;
+}
- 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++;
- }
+void SamplingFlags::start()
+{
+ for (unsigned i = 0; i <= 32; ++i)
+ s_flagCounts[i] = 0;
}
+void SamplingFlags::stop()
+{
+ uint64_t total = 0;
+ for (unsigned i = 0; i <= 32; ++i)
+ total += s_flagCounts[i];
+
+ if (total) {
+ printf("\nSamplingFlags: sample counts with flags set: (%lld total)\n", total);
+ for (unsigned i = 0; i <= 32; ++i) {
+ if (s_flagCounts[i])
+ printf(" [ %02d ] : %lld\t\t(%03.2f%%)\n", i, s_flagCounts[i], (100.0 * s_flagCounts[i]) / total);
+ }
+ printf("\n");
+ } else
+ printf("\nSamplingFlags: no samples.\n\n");
+}
+uint64_t SamplingFlags::s_flagCounts[33];
+
+#else
+void SamplingFlags::start() {}
+void SamplingFlags::stop() {}
+#endif
+
+/*
+ Start with flag 16 set.
+ By doing this the monitoring of lower valued flags will be masked out
+ until flag 16 is explictly cleared.
+*/
+uint32_t SamplingFlags::s_flags = 1 << 15;
+
#if PLATFORM(WIN_OS)
return 1000000 / hertz;
}
-void SamplingTool::run()
+
+SamplingTool* SamplingTool::s_samplingTool = 0;
+
+
+bool SamplingThread::s_running = false;
+unsigned SamplingThread::s_hertz = 10000;
+ThreadIdentifier SamplingThread::s_samplingThread;
+
+void* SamplingThread::threadStartFunc(void*)
{
- while (m_running) {
- sleepForMicroseconds(hertz2us(m_hertz));
+ while (s_running) {
+ sleepForMicroseconds(hertz2us(s_hertz));
- Sample sample(m_sample, m_codeBlock);
- ++m_sampleCount;
+#if ENABLE(SAMPLING_FLAGS)
+ SamplingFlags::sample();
+#endif
+#if ENABLE(OPCODE_SAMPLING)
+ SamplingTool::sample();
+#endif
+ }
- if (sample.isNull())
- continue;
+ return 0;
+}
- if (!sample.inHostFunction()) {
- unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode);
- ++m_opcodeSampleCount;
- ++m_opcodeSamples[opcodeID];
+void SamplingThread::start(unsigned hertz)
+{
+ ASSERT(!s_running);
+ s_running = true;
+ s_hertz = hertz;
- if (sample.inCTIFunction())
- m_opcodeSamplesInCTIFunctions[opcodeID]++;
- }
+ s_samplingThread = createThread(threadStartFunc, 0, "JavaScriptCore::Sampler");
+}
+
+void SamplingThread::stop()
+{
+ ASSERT(s_running);
+ s_running = false;
+ waitForThreadCompletion(s_samplingThread, 0);
+}
+
+
+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++;
+ }
+}
+
+void SamplingTool::doRun()
+{
+ Sample sample(m_sample, m_codeBlock);
+ ++m_sampleCount;
+
+ if (sample.isNull())
+ return;
+
+ 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)
+ if (CodeBlock* codeBlock = sample.codeBlock()) {
MutexLocker locker(m_scopeSampleMapMutex);
- ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode());
+ ScopeSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerNode());
ASSERT(record);
- record->sample(sample.codeBlock(), sample.vPC());
-#endif
+ record->sample(codeBlock, sample.vPC());
}
+#endif
}
-void* SamplingTool::threadStartFunc(void* samplingTool)
+void SamplingTool::sample()
{
- reinterpret_cast<SamplingTool*>(samplingTool)->run();
- return 0;
+ s_samplingTool->doRun();
}
void SamplingTool::notifyOfScope(ScopeNode* scope)
{
+#if ENABLE(CODEBLOCK_SAMPLING)
MutexLocker locker(m_scopeSampleMapMutex);
m_scopeSampleMap->set(scope, new ScopeSampleRecord(scope));
+#else
+ UNUSED_PARAM(scope);
+#endif
}
-void SamplingTool::start(unsigned hertz)
-{
- ASSERT(!m_running);
- m_running = true;
- m_hertz = hertz;
-
- m_samplingThread = createThread(threadStartFunc, this, "JavaScriptCore::Sampler");
-}
-
-void SamplingTool::stop()
+void SamplingTool::setup()
{
- ASSERT(m_running);
- m_running = false;
- waitForThreadCompletion(m_samplingThread, 0);
+ s_samplingTool = this;
}
#if ENABLE(OPCODE_SAMPLING)
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);
return (leftSampleInfo->count < rightSampleInfo->count) ? 1 : (leftSampleInfo->count > rightSampleInfo->count) ? -1 : 0;
}
+#if ENABLE(CODEBLOCK_SAMPLING)
+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 compareScopeSampleRecords(const void* left, const void* right)
{
const ScopeSampleRecord* const leftValue = *static_cast<const ScopeSampleRecord* const *>(left);
return (leftValue->m_sampleCount < rightValue->m_sampleCount) ? 1 : (leftValue->m_sampleCount > rightValue->m_sampleCount) ? -1 : 0;
}
+#endif
void SamplingTool::dump(ExecState* exec)
{
printf("\tcti count:\tsamples inside a CTI function called by this opcode\n");
printf("\tcti %% of self:\tcti count / sample count\n");
+#if ENABLE(CODEBLOCK_SAMPLING)
+
// (3) Build and sort 'codeBlockSamples' array.
int scopeCount = m_scopeSampleMap->size();
}
}
}
+#else
+ UNUSED_PARAM(exec);
+#endif
}
#else
#endif
+void AbstractSamplingCounter::dump()
+{
+#if ENABLE(SAMPLING_COUNTERS)
+ if (s_abstractSamplingCounterChain != &s_abstractSamplingCounterChainEnd) {
+ printf("\nSampling Counter Values:\n");
+ for (AbstractSamplingCounter* currCounter = s_abstractSamplingCounterChain; (currCounter != &s_abstractSamplingCounterChainEnd); currCounter = currCounter->m_next)
+ printf("\t%s\t: %lld\n", currCounter->m_name, currCounter->m_counter);
+ printf("\n\n");
+ }
+ s_completed = true;
+#endif
+}
+
+AbstractSamplingCounter AbstractSamplingCounter::s_abstractSamplingCounterChainEnd;
+AbstractSamplingCounter* AbstractSamplingCounter::s_abstractSamplingCounterChain = &s_abstractSamplingCounterChainEnd;
+bool AbstractSamplingCounter::s_completed = false;
+
} // namespace JSC
namespace JSC {
+ class SamplingFlags {
+ friend class JIT;
+ public:
+ static void start();
+ static void stop();
+
+#if ENABLE(SAMPLING_FLAGS)
+ static void setFlag(unsigned flag)
+ {
+ ASSERT(flag >= 1);
+ ASSERT(flag <= 32);
+ s_flags |= 1u << (flag - 1);
+ }
+
+ static void clearFlag(unsigned flag)
+ {
+ ASSERT(flag >= 1);
+ ASSERT(flag <= 32);
+ s_flags &= ~(1u << (flag - 1));
+ }
+
+ static void sample();
+
+ class ScopedFlag {
+ public:
+ ScopedFlag(int flag)
+ : m_flag(flag)
+ {
+ setFlag(flag);
+ }
+
+ ~ScopedFlag()
+ {
+ clearFlag(m_flag);
+ }
+
+ private:
+ int m_flag;
+ };
+
+#endif
+ private:
+ static uint32_t s_flags;
+#if ENABLE(SAMPLING_FLAGS)
+ static uint64_t s_flagCounts[33];
+#endif
+ };
+
class CodeBlock;
class ExecState;
class Interpreter;
typedef WTF::HashMap<ScopeNode*, ScopeSampleRecord*> ScopeSampleRecordMap;
+ class SamplingThread {
+ public:
+ // Sampling thread state.
+ static bool s_running;
+ static unsigned s_hertz;
+ static ThreadIdentifier s_samplingThread;
+
+ static void start(unsigned hertz=10000);
+ static void stop();
+
+ static void* threadStartFunc(void*);
+ };
+
class SamplingTool {
public:
friend class CallRecord;
SamplingTool(Interpreter* interpreter)
: m_interpreter(interpreter)
- , m_running(false)
, m_codeBlock(0)
, m_sample(0)
, m_sampleCount(0)
, m_opcodeSampleCount(0)
+#if ENABLE(CODEBLOCK_SAMPLING)
, m_scopeSampleMap(new ScopeSampleRecordMap())
+#endif
{
memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
~SamplingTool()
{
+#if ENABLE(CODEBLOCK_SAMPLING)
deleteAllValues(*m_scopeSampleMap);
+#endif
}
- void start(unsigned hertz=10000);
- void stop();
+ void setup();
void dump(ExecState*);
void notifyOfScope(ScopeNode* scope);
return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(vPC) | (static_cast<intptr_t>(inCTIFunction) << 1) | static_cast<intptr_t>(inHostFunction));
}
+ static void sample();
+
private:
class Sample {
public:
{
}
- bool isNull() { return !m_sample || !m_codeBlock; }
+ bool isNull() { return !m_sample; }
CodeBlock* codeBlock() { return m_codeBlock; }
Instruction* vPC() { return reinterpret_cast<Instruction*>(m_sample & ~0x3); }
bool inHostFunction() { return m_sample & 0x1; }
intptr_t m_sample;
CodeBlock* m_codeBlock;
};
-
- static void* threadStartFunc(void*);
- void run();
+
+ void doRun();
+ static SamplingTool* s_samplingTool;
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;
unsigned m_opcodeSamples[numOpcodeIDs];
unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs];
+#if ENABLE(CODEBLOCK_SAMPLING)
Mutex m_scopeSampleMapMutex;
OwnPtr<ScopeSampleRecordMap> m_scopeSampleMap;
+#endif
+ };
+
+ // AbstractSamplingCounter:
+ //
+ // Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS).
+ // See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter.
+ class AbstractSamplingCounter {
+ friend class JIT;
+ friend class DeletableSamplingCounter;
+ public:
+ void count(uint32_t count = 1)
+ {
+ m_counter += count;
+ }
+
+ static void dump();
+
+ protected:
+ // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter.
+ void init(const char* name)
+ {
+ m_counter = 0;
+ m_name = name;
+
+ // Set m_next to point to the head of the chain, and inform whatever is
+ // currently at the head that this node will now hold the pointer to it.
+ m_next = s_abstractSamplingCounterChain;
+ s_abstractSamplingCounterChain->m_referer = &m_next;
+ // Add this node to the head of the list.
+ s_abstractSamplingCounterChain = this;
+ m_referer = &s_abstractSamplingCounterChain;
+ }
+
+ int64_t m_counter;
+ const char* m_name;
+ AbstractSamplingCounter* m_next;
+ // This is a pointer to the pointer to this node in the chain; used to
+ // allow fast linked list deletion.
+ AbstractSamplingCounter** m_referer;
+ // Null object used to detect end of static chain.
+ static AbstractSamplingCounter s_abstractSamplingCounterChainEnd;
+ static AbstractSamplingCounter* s_abstractSamplingCounterChain;
+ static bool s_completed;
+ };
+
+#if ENABLE(SAMPLING_COUNTERS)
+ // SamplingCounter:
+ //
+ // This class is suitable and (hopefully!) convenient for cases where a counter is
+ // required within the scope of a single function. It can be instantiated as a
+ // static variable since it contains a constructor but not a destructor (static
+ // variables in WebKit cannot have destructors).
+ //
+ // For example:
+ //
+ // void someFunction()
+ // {
+ // static SamplingCounter countMe("This is my counter. There are many like it, but this one is mine.");
+ // countMe.count();
+ // // ...
+ // }
+ //
+ class SamplingCounter : public AbstractSamplingCounter {
+ public:
+ SamplingCounter(const char* name) { init(name); }
+ };
+
+ // GlobalSamplingCounter:
+ //
+ // This class is suitable for use where a counter is to be declared globally,
+ // since it contains neither a constructor nor destructor. Instead, ensure
+ // that 'name()' is called to provide the counter with a name (and also to
+ // allow it to be printed out on exit).
+ //
+ // GlobalSamplingCounter globalCounter;
+ //
+ // void firstFunction()
+ // {
+ // // Put this within a function that is definitely called!
+ // // (Or alternatively alongside all calls to 'count()').
+ // globalCounter.name("I Name You Destroyer.");
+ // globalCounter.count();
+ // // ...
+ // }
+ //
+ // void secondFunction()
+ // {
+ // globalCounter.count();
+ // // ...
+ // }
+ //
+ class GlobalSamplingCounter : public AbstractSamplingCounter {
+ public:
+ void name(const char* name)
+ {
+ // Global objects should be mapped in zero filled memory, so this should
+ // be a safe (albeit not necessarily threadsafe) check for 'first call'.
+ if (!m_next)
+ init(name);
+ }
+ };
+
+ // DeletableSamplingCounter:
+ //
+ // The above classes (SamplingCounter, GlobalSamplingCounter), are intended for
+ // use within a global or static scope, and as such cannot have a destructor.
+ // This means there is no convenient way for them to remove themselves from the
+ // static list of counters, and should an instance of either class be freed
+ // before 'dump()' has walked over the list it will potentially walk over an
+ // invalid pointer.
+ //
+ // This class is intended for use where the counter may possibly be deleted before
+ // the program exits. Should this occur, the counter will print it's value to
+ // stderr, and remove itself from the static list. Example:
+ //
+ // DeletableSamplingCounter* counter = new DeletableSamplingCounter("The Counter With No Name");
+ // counter->count();
+ // delete counter;
+ //
+ class DeletableSamplingCounter : public AbstractSamplingCounter {
+ public:
+ DeletableSamplingCounter(const char* name) { init(name); }
+
+ ~DeletableSamplingCounter()
+ {
+ if (!s_completed)
+ fprintf(stderr, "DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
+ // Our m_referer pointer should know where the pointer to this node is,
+ // and m_next should know that this node is the previous node in the list.
+ ASSERT(*m_referer == this);
+ ASSERT(m_next->m_referer == &m_next);
+ // Remove this node from the list, and inform m_next that we have done so.
+ m_next->m_referer = m_referer;
+ *m_referer = m_next;
+ }
};
+#endif
} // namespace JSC
#ifndef StructureStubInfo_h
#define StructureStubInfo_h
+#if ENABLE(JIT)
+
#include "Instruction.h"
+#include "MacroAssembler.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)
{
}
} putByIdReplace;
} u;
- void* stubRoutine;
- void* callReturnLocation;
- void* hotPathBegin;
+ CodeLocationLabel stubRoutine;
+ CodeLocationCall callReturnLocation;
+ CodeLocationLabel hotPathBegin;
};
-#endif
} // namespace JSC
+#endif
+
#endif // StructureStubInfo_h
#include "BytecodeGenerator.h"
#include "BatchedTransitionOptimizer.h"
+#include "PrototypeFunction.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include "UString.h"
return result.second;
}
-void BytecodeGenerator::allocateConstants(size_t count)
+void BytecodeGenerator::preserveLastVar()
{
- 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();
+ if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
+ m_lastVar = &m_calleeRegisters.last();
}
BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
, m_baseScopeDepth(0)
, m_codeType(GlobalCode)
, m_nextGlobalIndex(-1)
+ , m_nextConstantOffset(0)
+ , m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
m_nextGlobalIndex -= symbolTable->size();
for (size_t i = 0; i < functionStack.size(); ++i) {
- FuncDeclNode* funcDecl = functionStack[i].get();
+ FuncDeclNode* funcDecl = functionStack[i];
globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
}
if (!globalObject->hasProperty(exec, varStack[i].first))
newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
- allocateConstants(programNode->neededConstants());
+ preserveLastVar();
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();
+ FuncDeclNode* funcDecl = functionStack[i];
globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
}
for (size_t i = 0; i < varStack.size(); ++i) {
globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
}
- allocateConstants(programNode->neededConstants());
+ preserveLastVar();
}
}
, m_dynamicScopeDepth(0)
, m_baseScopeDepth(0)
, m_codeType(FunctionCode)
+ , m_nextConstantOffset(0)
+ , m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
} else
emitOpcode(op_enter);
- if (usesArguments)
- emitOpcode(op_create_arguments);
+ if (usesArguments) {
+ emitOpcode(op_init_arguments);
+
+ // The debugger currently retrieves the arguments object from an activation rather than pulling
+ // it from a call frame. In the long-term it should stop doing that (<rdar://problem/6911886>),
+ // but for now we force eager creation of the arguments object when debugging.
+ if (m_shouldEmitDebugHooks)
+ emitOpcode(op_create_arguments);
+ }
const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
for (size_t i = 0; i < functionStack.size(); ++i) {
- FuncDeclNode* funcDecl = functionStack[i].get();
+ FuncDeclNode* funcDecl = functionStack[i];
const Identifier& ident = funcDecl->m_ident;
m_functions.add(ident.ustring().rep());
emitNewFunction(addVar(ident, false), funcDecl);
for (size_t i = 0; i < parameterCount; ++i)
addParameter(parameters[i]);
- allocateConstants(functionBody->neededConstants());
+ preserveLastVar();
}
BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
, m_dynamicScopeDepth(0)
, m_baseScopeDepth(codeBlock->baseScopeDepth())
, m_codeType(EvalCode)
+ , m_nextConstantOffset(0)
+ , m_globalConstantIndex(0)
, m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
, m_lastOpcodeID(op_end)
, m_emitNodeDepth(0)
codeBlock->setGlobalData(m_globalData);
m_codeBlock->m_numParameters = 1; // Allocate space for "this"
- allocateConstants(evalNode->neededConstants());
+ preserveLastVar();
}
RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
if (entry.isNull())
return 0;
+ if (ident == propertyNames().arguments)
+ createArgumentsIfNecessary();
+
+ return ®isterFor(entry.getIndex());
+}
+
+bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
+{
+ if (ident != propertyNames().arguments)
+ return false;
+
+ if (!shouldOptimizeLocals())
+ return false;
+
+ SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+ if (entry.isNull())
+ return false;
+
+ if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
+ return true;
+
+ return false;
+}
+
+RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
+{
+ ASSERT(willResolveToArguments(propertyNames().arguments));
+
+ SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep());
+ ASSERT(!entry.isNull());
return ®isterFor(entry.getIndex());
}
instructions().append(target->offsetFrom(instructions().size()));
return target;
}
+ } else if (m_lastOpcodeID == op_lesseq) {
+ int dstIndex;
+ int src1Index;
+ int src2Index;
+
+ retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+ if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+ rewindBinaryOp();
+ emitOpcode(op_jnlesseq);
+ instructions().append(src1Index);
+ instructions().append(src2Index);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+ }
} else if (m_lastOpcodeID == op_not) {
int dstIndex;
int srcIndex;
return target;
}
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
+{
+ emitOpcode(op_jneq_ptr);
+ instructions().append(cond->index());
+ instructions().append(m_scopeChain->globalObject()->d()->callFunction);
+ instructions().append(target->offsetFrom(instructions().size()));
+ return target;
+}
+
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
+{
+ emitOpcode(op_jneq_ptr);
+ instructions().append(cond->index());
+ instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
+ 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 result.first->second;
}
-RegisterID* BytecodeGenerator::addConstant(JSValuePtr v)
+RegisterID* BytecodeGenerator::addConstantValue(JSValue 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;
+ int index = m_nextConstantOffset;
- m_codeBlock->addConstantRegister(JSValuePtr(v));
- return &constant;
- }
-
- return ®isterFor(result.first->second);
-}
+ pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
+ if (result.second) {
+ m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
+ ++m_nextConstantOffset;
+ m_codeBlock->addConstantRegister(JSValue(v));
+ } else
+ index = result.first->second;
-unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v)
-{
- return m_codeBlock->addUnexpectedConstant(v);
+ return &m_constantPoolRegisters[index];
}
unsigned BytecodeGenerator::addRegExp(RegExp* r)
instructions().append(src2->index());
if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
- opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) {
+ opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
instructions().append(types.toInt());
- }
return dst;
}
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();
+ && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
+ const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->value();
if (value == "undefined") {
rewindUnaryOp();
emitOpcode(op_is_undefined);
// 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;
+ JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second;
if (!valueInMap)
valueInMap = jsNumber(globalData(), number);
return emitLoad(dst, valueInMap);
JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
if (!stringInMap)
stringInMap = jsOwnedString(globalData(), identifier.ustring());
- return emitLoad(dst, JSValuePtr(stringInMap));
+ return emitLoad(dst, JSValue(stringInMap));
}
-RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v)
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
{
- RegisterID* constantID = addConstant(v);
+ RegisterID* constantID = addConstantValue(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.
return dst;
}
-RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject)
+RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
{
if (globalObject) {
emitOpcode(op_get_global_var);
return dst;
}
-RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject)
+RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
{
if (globalObject) {
emitOpcode(op_put_global_var);
RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
{
- emitOpcode(op_resolve_base);
- instructions().append(dst->index());
- instructions().append(addConstant(property));
- return dst;
+ size_t depth = 0;
+ int index = 0;
+ JSObject* globalObject = 0;
+ findScopedProperty(property, index, depth, false, globalObject);
+ if (!globalObject) {
+ // We can't optimise at all :-(
+ emitOpcode(op_resolve_base);
+ instructions().append(dst->index());
+ instructions().append(addConstant(property));
+ return dst;
+ }
+
+ // Global object is the base
+ return emitLoad(dst, JSValue(globalObject));
}
RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
{
- emitOpcode(op_resolve_with_base);
- instructions().append(baseDst->index());
+ 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_with_base);
+ instructions().append(baseDst->index());
+ instructions().append(propDst->index());
+ instructions().append(addConstant(property));
+ return baseDst;
+ }
+
+ bool forceGlobalResolve = false;
+ if (m_regeneratingForExceptionInfo) {
+#if ENABLE(JIT)
+ forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
+#else
+ forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
+#endif
+ }
+
+ // Global object is the base
+ emitLoad(baseDst, JSValue(globalObject));
+
+ if (index != missingSymbolMarker() && !forceGlobalResolve) {
+ // Directly index the property lookup across multiple scopes.
+ emitGetScopedVar(propDst, depth, index, globalObject);
+ return baseDst;
+ }
+
+#if ENABLE(JIT)
+ m_codeBlock->addGlobalResolveInfo(instructions().size());
+#else
+ m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
+ emitOpcode(op_resolve_global);
instructions().append(propDst->index());
+ instructions().append(globalObject);
instructions().append(addConstant(property));
+ instructions().append(0);
+ instructions().append(0);
return baseDst;
}
-RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
+void BytecodeGenerator::emitMethodCheck()
{
- emitOpcode(op_resolve_func);
- instructions().append(baseDst->index());
- instructions().append(funcDst->index());
- instructions().append(addConstant(property));
- return baseDst;
+ emitOpcode(op_method_check);
}
RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
}
+void BytecodeGenerator::createArgumentsIfNecessary()
+{
+ if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
+ emitOpcode(op_create_arguments);
+}
+
RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
{
+ createArgumentsIfNecessary();
return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
}
// 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()) {
+ for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
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);
return dst;
}
+RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* arguments)
+{
+ ASSERT(argCountDst->index() < arguments->index());
+ emitOpcode(op_load_varargs);
+ instructions().append(argCountDst->index());
+ instructions().append(arguments->index());
+ return argCountDst;
+}
+
+RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+ ASSERT(func->refCount());
+ ASSERT(thisRegister->refCount());
+ ASSERT(dst != func);
+ 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);
+
+ // Emit call.
+ emitOpcode(op_call_varargs);
+ instructions().append(dst->index()); // dst
+ instructions().append(func->index()); // func
+ instructions().append(argCountRegister->index()); // arg count
+ instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
+ if (m_shouldEmitProfileHooks) {
+ emitOpcode(op_profile_did_call);
+ instructions().append(func->index());
+ }
+ return dst;
+}
+
RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
{
if (m_codeBlock->needsFullScopeChain()) {
// 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()) {
+ for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode : 0; n; n = n->m_next) {
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);
return dst;
}
+RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
+{
+ emitOpcode(op_strcat);
+ instructions().append(dst->index());
+ instructions().append(src->index());
+ instructions().append(count);
+
+ return dst;
+}
+
+void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
+{
+ emitOpcode(op_to_primitive);
+ instructions().append(dst->index());
+ instructions().append(src->index());
+}
+
RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
{
ASSERT(scope->isTemporary());
context.isFinallyBlock = false;
m_scopeContextStack.append(context);
m_dynamicScopeDepth++;
+ createArgumentsIfNecessary();
return emitUnaryNoDstOp(op_push_scope, scope);
}
LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
{
// Reclaim free label scopes.
- while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+ //
+ // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
+ // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
+ // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
+ // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
+ // loop condition is a workaround.
+ while (m_labelScopes.size()) {
+ if (m_labelScopes.last().refCount())
+ break;
m_labelScopes.removeLast();
+ }
if (!m_labelScopes.size())
return 0;
emitLabel(nextInsn.get());
}
- // To get here there must be at least one finally block present
- do {
- ASSERT(topScope->isFinallyBlock);
+ while (topScope > bottomScope && topScope->isFinallyBlock) {
emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
--topScope;
- if (!topScope->isFinallyBlock)
- break;
- } while (topScope > bottomScope);
+ }
}
return emitJump(target);
}
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 };
+ HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
#else
HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
#endif
return targetRegister;
}
-RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message)
+RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message)
{
emitOpcode(op_new_error);
instructions().append(dst->index());
instructions().append(static_cast<int>(type));
- instructions().append(addUnexpectedConstant(message));
+ instructions().append(addConstantValue(message)->index());
return dst;
}
emitOpcode(op_jsr);
instructions().append(retAddrDst->index());
instructions().append(finally->offsetFrom(instructions().size()));
+ emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
return finally;
}
m_scopeContextStack.append(context);
m_dynamicScopeDepth++;
+ createArgumentsIfNecessary();
+
emitOpcode(op_push_new_scope);
instructions().append(dst->index());
instructions().append(addConstant(property));
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);
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);
}
}
#include "LabelScope.h"
#include "Interpreter.h"
#include "RegisterID.h"
-#include "SegmentedVector.h"
#include "SymbolTable.h"
#include "Debugger.h"
#include "Nodes.h"
+#include <wtf/FastAllocBase.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/SegmentedVector.h>
#include <wtf/Vector.h>
namespace JSC {
FinallyContext finallyContext;
};
- class BytecodeGenerator {
+ class BytecodeGenerator : public WTF::FastAllocBase {
public:
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
// such register exists. Registers returned by registerFor do not
// require explicit reference counting.
RegisterID* registerFor(const Identifier&);
+
+ bool willResolveToArguments(const Identifier&);
+ RegisterID* uncheckedRegisterForArguments();
// Behaves as registerFor does, but ignores dynamic scope as
// dynamic scope should not interfere with const initialisation
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* emitLoad(RegisterID* dst, JSValue);
RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
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* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue globalObject);
+ RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue 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);
+
+ void emitMethodCheck();
RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
RegisterID* emitPutById(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* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCount, unsigned divot, unsigned startOffset, unsigned endOffset);
+ RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* args);
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);
+ RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
+ void emitToPrimitive(RegisterID* dst, RegisterID* src);
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> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
+ PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
- RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message);
+ RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message);
void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value);
RegisterID* emitPushScope(RegisterID* scope);
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;
+ typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
struct IdentifierMapIndexHashTraits {
typedef int TraitType;
};
typedef HashMap<RefPtr<UString::Rep>, int, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, IdentifierMapIndexHashTraits> IdentifierMap;
- typedef HashMap<double, JSValuePtr> NumberMap;
+ typedef HashMap<double, JSValue> 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();
RegisterID* addParameter(const Identifier&);
- void allocateConstants(size_t);
+ void preserveLastVar();
RegisterID& registerFor(int index)
{
unsigned addConstant(FuncDeclNode*);
unsigned addConstant(FuncExprNode*);
unsigned addConstant(const Identifier&);
- RegisterID* addConstant(JSValuePtr);
- unsigned addUnexpectedConstant(JSValuePtr);
+ RegisterID* addConstantValue(JSValue);
unsigned addRegExp(RegExp*);
Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
RegisterID* emitThrowExpressionTooDeepException();
+ void createArgumentsIfNecessary();
+
bool m_shouldEmitDebugHooks;
bool m_shouldEmitProfileHooks;
ScopeNode* m_scopeNode;
CodeBlock* m_codeBlock;
+ // Some of these objects keep pointers to one another. They are arranged
+ // to ensure a sane destruction order that avoids references to freed memory.
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;
+ WTF::SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
+ WTF::SegmentedVector<RegisterID, 32> m_calleeRegisters;
+ WTF::SegmentedVector<RegisterID, 32> m_parameters;
+ WTF::SegmentedVector<RegisterID, 32> m_globals;
+ WTF::SegmentedVector<Label, 32> m_labels;
+ WTF::SegmentedVector<LabelScope, 8> m_labelScopes;
+ RefPtr<RegisterID> m_lastVar;
int m_finallyDepth;
int m_dynamicScopeDepth;
int m_baseScopeDepth;
int m_nextGlobalIndex;
int m_nextParameterIndex;
- int m_nextConstantIndex;
+ int m_firstConstantIndex;
+ int m_nextConstantOffset;
+ unsigned m_globalConstantIndex;
int m_globalVarStorageOffset;
bool m_regeneratingForExceptionInfo;
CodeBlock* m_codeBlockBeingRegeneratedFrom;
- static const unsigned s_maxEmitNodeDepth = 10000;
+ static const unsigned s_maxEmitNodeDepth = 5000;
};
}
+++ /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
#include <wtf/Platform.h>
+#if PLATFORM(WIN_OS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
+#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
+#define JS_EXPORTDATA __declspec(dllexport)
+#else
+#define JS_EXPORTDATA __declspec(dllimport)
+#endif
+#else
+#define JS_EXPORTDATA
+#endif
+
#if PLATFORM(WIN_OS)
// If we don't define these, they get defined in windef.h.
#define max max
#define min min
-#if !COMPILER(MSVC7) && !PLATFORM(WIN_CE)
+#if !COMPILER(MSVC7) && !PLATFORM(WINCE)
// 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
}
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 "extern JSC_CONST_HASHTABLE HashTable $name =\n";
print " \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n";
- print "#endif\n\n";
print "} // namespace\n";
}
globalObject->setDebugger(0);
}
-JSValuePtr evaluateInGlobalCallFrame(const UString& script, JSValuePtr& exception, JSGlobalObject* globalObject)
+JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
{
CallFrame* globalCallFrame = globalObject->globalExec();
virtual ~Debugger();
void attach(JSGlobalObject*);
- void detach(JSGlobalObject*);
+ virtual void detach(JSGlobalObject*);
virtual void sourceParsed(ExecState*, const SourceCode&, int errorLine, const UString& errorMsg) = 0;
virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
// This method exists only for backwards compatibility with existing
// WebScriptDebugger clients
- JSValuePtr evaluateInGlobalCallFrame(const UString&, JSValuePtr& exception, JSGlobalObject*);
+ JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
} // namespace JSC
return m_activation->getOwnPropertySlot(exec, propertyName, slot);
}
-void DebuggerActivation::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void DebuggerActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
m_activation->put(exec, propertyName, value, slot);
}
-void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
m_activation->putWithAttributes(exec, propertyName, value, attributes);
}
m_activation->defineSetter(exec, propertyName, setterFunction);
}
-JSValuePtr DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
+JSValue DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
{
return m_activation->lookupGetter(exec, propertyName);
}
-JSValuePtr DebuggerActivation::lookupSetter(ExecState* exec, const Identifier& propertyName)
+JSValue DebuggerActivation::lookupSetter(ExecState* exec, const Identifier& propertyName)
{
return m_activation->lookupSetter(exec, propertyName);
}
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 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, 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);
+ virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
+ virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
return 0;
return &function->name(&m_callFrame->globalData());
}
+
+UString DebuggerCallFrame::calculatedFunctionName() const
+{
+ if (!m_callFrame->codeBlock())
+ return 0;
+
+ JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
+ if (!function)
+ return 0;
+ return function->calculatedDisplayName(&m_callFrame->globalData());
+}
DebuggerCallFrame::Type DebuggerCallFrame::type() const
{
return asObject(m_callFrame->thisValue());
}
-JSValuePtr DebuggerCallFrame::evaluate(const UString& script, JSValuePtr& exception) const
+JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) const
{
if (!m_callFrame->codeBlock())
- return noValue();
+ return JSValue();
int errLine;
UString errMsg;
DebuggerCallFrame(CallFrame* callFrame)
: m_callFrame(callFrame)
- , m_exception(noValue())
{
}
- DebuggerCallFrame(CallFrame* callFrame, JSValuePtr exception)
+ DebuggerCallFrame(CallFrame* callFrame, JSValue 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;
+ UString calculatedFunctionName() const;
Type type() const;
JSObject* thisObject() const;
- JSValuePtr evaluate(const UString&, JSValuePtr& exception) const;
- JSValuePtr exception() const { return m_exception; }
+ JSValue evaluate(const UString&, JSValue& exception) const;
+ JSValue exception() const { return m_exception; }
private:
CallFrame* m_callFrame;
- JSValuePtr m_exception;
+ JSValue m_exception;
};
} // namespace JSC
--- /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 CachedCall_h
+#define CachedCall_h
+
+#include "CallFrameClosure.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Interpreter.h"
+
+namespace JSC {
+ class CachedCall : Noncopyable {
+ public:
+ CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
+ : m_valid(false)
+ , m_interpreter(callFrame->interpreter())
+ , m_exception(exception)
+ , m_globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : function->scope().node()->globalObject())
+ {
+ m_closure = m_interpreter->prepareForRepeatCall(function->body(), callFrame, function, argCount, function->scope().node(), exception);
+ m_valid = !*exception;
+ }
+
+ JSValue call()
+ {
+ ASSERT(m_valid);
+ return m_interpreter->execute(m_closure, m_exception);
+ }
+ void setThis(JSValue v) { m_closure.setArgument(0, v); }
+ void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
+ CallFrame* newCallFrame() { return m_closure.newCallFrame; }
+ ~CachedCall()
+ {
+ if (m_valid)
+ m_interpreter->endRepeatCall(m_closure);
+ }
+
+ private:
+ bool m_valid;
+ Interpreter* m_interpreter;
+ JSValue* m_exception;
+ DynamicGlobalObjectScope m_globalObjectScope;
+ CallFrameClosure m_closure;
+ };
+}
+
+#endif
#include "CallFrame.h"
#include "CodeBlock.h"
+#include "Interpreter.h"
namespace JSC {
-JSValuePtr CallFrame::thisValue()
+JSValue CallFrame::thisValue()
{
- return this[codeBlock()->thisRegister()].jsValue(this);
+ return this[codeBlock()->thisRegister()].jsValue();
}
+#ifndef NDEBUG
+void CallFrame::dumpCaller()
+{
+ int signedLineNumber;
+ intptr_t sourceID;
+ UString urlString;
+ JSValue function;
+
+ interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
+ printf("Callpoint => %s:%d\n", urlString.ascii(), signedLineNumber);
+}
+#endif
+
}
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(); }
+ int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
- JSValuePtr thisValue();
+ JSValue thisValue();
// Global object in which execution began.
JSGlobalObject* dynamicGlobalObject();
// 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; }
+ void setException(JSValue exception) { globalData().exception = exception; }
+ void clearException() { globalData().exception = JSValue(); }
+ JSValue exception() const { return globalData().exception; }
+ JSValue* exceptionSlot() { return &globalData().exception; }
bool hadException() const { return globalData().exception; }
const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
- const ArgList& emptyList() const { return *globalData().emptyList; }
+ const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; }
Interpreter* interpreter() { return globalData().interpreter; }
Heap* heap() { return &globalData().heap; }
-
+#ifndef NDEBUG
+ void dumpCaller();
+#endif
static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
+ static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; }
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; }
+ void setCalleeArguments(JSValue arguments) { static_cast<Register*>(this)[RegisterFile::OptionalCalleeArguments] = arguments; }
+ void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
+ void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
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;
+ static_cast<Register*>(this)[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
+ static_cast<Register*>(this)[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister);
setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
setCallee(function);
- setCalleeArguments(0);
+ setCalleeArguments(JSValue());
}
- static const intptr_t HostCallFrameFlag = 1;
+ // Read a register from the codeframe (or constant from the CodeBlock).
+ inline Register& r(int);
static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
+ int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
+
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); }
+ private:
+ void setArgumentCount(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
+ void setCallee(JSFunction* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = callee; }
+ void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
+
+ static const intptr_t HostCallFrameFlag = 1;
+
ExecState();
~ExecState();
};
--- /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 CallFrameClosure_h
+#define CallFrameClosure_h
+
+namespace JSC {
+
+struct CallFrameClosure {
+ CallFrame* oldCallFrame;
+ CallFrame* newCallFrame;
+ JSFunction* function;
+ FunctionBodyNode* functionBody;
+ JSGlobalData* globalData;
+ Register* oldEnd;
+ ScopeChainNode* scopeChain;
+ int expectedParams;
+ int providedParams;
+
+ void setArgument(int arg, JSValue value)
+ {
+ if (arg < expectedParams)
+ newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams] = value;
+ else
+ newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
+ }
+ void resetCallFrame()
+ {
+ newCallFrame->setScopeChain(scopeChain);
+ newCallFrame->setCalleeArguments(JSValue());
+ for (int i = providedParams; i < expectedParams; ++i)
+ newCallFrame[i - RegisterFile::CallFrameHeaderSize - expectedParams] = jsUndefined();
+ }
+};
+
+}
+
+#endif
#include "Arguments.h"
#include "BatchedTransitionOptimizer.h"
+#include "CallFrame.h"
+#include "CallFrameClosure.h"
#include "CodeBlock.h"
+#include "Collector.h"
+#include "Debugger.h"
#include "DebuggerCallFrame.h"
#include "EvalCodeCache.h"
#include "ExceptionHelpers.h"
-#include "CallFrame.h"
#include "GlobalEvalFunction.h"
#include "JSActivation.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
+#include "LiteralParser.h"
#include "JSStaticScopeObject.h"
#include "JSString.h"
#include "ObjectPrototype.h"
+#include "Operations.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>
+#include <wtf/Threading.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);
+ return codeBlock->getBytecodeIndex(callFrame, ReturnAddressPtr(pc));
#else
UNUSED_PARAM(callFrame);
return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
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)
+#if USE(INTERPRETER)
+NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = (vPC + 1)->u.operand;
int property = (vPC + 2)->u.operand;
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame->r(dst) = JSValue(result);
return true;
}
} while (++iter != end);
return false;
}
-NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
CodeBlock* codeBlock = callFrame->codeBlock();
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame->r(dst) = JSValue(result);
return true;
}
} while (++iter != end);
return false;
}
-NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = (vPC + 1)->u.operand;
JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
int offset = (vPC + 5)->u.operand;
if (structure == globalObject->structure()) {
- callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset));
+ callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
return true;
}
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() && slot.slotBase() == globalObject) {
+ JSValue result = slot.getValue(callFrame, ident);
+ if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
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);
+ callFrame->r(dst) = JSValue(result);
return true;
}
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame->r(dst) = JSValue(result);
return true;
}
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()));
+ callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
}
-NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int baseDst = (vPC + 1)->u.operand;
int propDst = (vPC + 2)->u.operand;
base = *iter;
PropertySlot slot(base);
if (base->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[propDst] = JSValuePtr(result);
- callFrame[baseDst] = JSValuePtr(base);
+ callFrame->r(propDst) = JSValue(result);
+ callFrame->r(baseDst) = JSValue(base);
return true;
}
++iter;
return false;
}
-NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int baseDst = (vPC + 1)->u.operand;
int funcDst = (vPC + 2)->u.operand;
// 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);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[baseDst] = JSValuePtr(thisObj);
- callFrame[funcDst] = JSValuePtr(result);
+ callFrame->r(baseDst) = JSValue(thisObj);
+ callFrame->r(funcDst) = JSValue(result);
return true;
}
++iter;
return false;
}
+#endif // USE(INTERPRETER)
+
ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
{
Register* r = callFrame->registers();
return CallFrame::create(r);
}
-static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData)
+#if USE(INTERPRETER)
+static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
{
if (value.isObject())
return false;
- exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+ exceptionData = createInvalidParamError(callFrame, "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)
+static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
+{
+ if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
+ return false;
+ exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+ return true;
+}
+#endif
+
+NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
{
if (argc < 2)
return jsUndefined();
- JSValuePtr program = argv[1].jsValue(callFrame);
+ JSValue program = argv[1].jsValue();
if (!program.isString())
return program;
UString programSource = asString(program)->value();
+ LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
+ if (JSValue parsedObject = preparser.tryLiteralParse())
+ return parsedObject;
+
+
ScopeChainNode* scopeChain = callFrame->scopeChain();
CodeBlock* codeBlock = callFrame->codeBlock();
RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
- JSValuePtr result = jsUndefined();
+ JSValue result = jsUndefined();
if (evalNode)
result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
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();
+#if HAVE(COMPUTED_GOTO)
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()
-{
+ for (int i = 0; i < numOpcodeIDs; ++i)
+ m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
+#endif // HAVE(COMPUTED_GOTO)
}
#ifndef NDEBUG
void Interpreter::dumpRegisters(CallFrame* callFrame)
{
printf("Register frame: \n\n");
- printf("----------------------------------------------------\n");
- printf(" use | address | value \n");
- printf("----------------------------------------------------\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;
+ JSValue v;
if (codeBlock->codeType() == GlobalCode) {
it = registerFile->lastGlobal();
end = it + registerFile->numGlobals();
while (it != end) {
- printf("[global var] | %10p | %10p \n", it, (*it).v());
+ v = (*it).jsValue();
+#if USE(JSVALUE32_64)
+ printf("[global var] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
+#else
+ printf("[global var] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
+#endif
++it;
}
- printf("----------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------------\n");
}
it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
- printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
+ v = (*it).jsValue();
+#if USE(JSVALUE32_64)
+ printf("[this] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
+#else
+ printf("[this] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
+#endif
end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
if (it != end) {
do {
- printf("[param] | %10p | %10p \n", it, (*it).v());
+ v = (*it).jsValue();
+#if USE(JSVALUE32_64)
+ printf("[param] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
+#else
+ printf("[param] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
+#endif
++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");
+ printf("-----------------------------------------------------------------------------\n");
+ printf("[CodeBlock] | %10p | %p \n", it, (*it).codeBlock()); ++it;
+ printf("[ScopeChain] | %10p | %p \n", it, (*it).scopeChain()); ++it;
+ printf("[CallerRegisters] | %10p | %d \n", it, (*it).i()); ++it;
+ printf("[ReturnPC] | %10p | %p \n", it, (*it).vPC()); ++it;
+ printf("[ReturnValueRegister] | %10p | %d \n", it, (*it).i()); ++it;
+ printf("[ArgumentCount] | %10p | %d \n", it, (*it).i()); ++it;
+ printf("[Callee] | %10p | %p \n", it, (*it).function()); ++it;
+ printf("[OptionalCalleeArguments] | %10p | %p \n", it, (*it).arguments()); ++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());
+ v = (*it).jsValue();
+#if USE(JSVALUE32_64)
+ printf("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+#else
+ printf("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+#endif
++it;
++registerCount;
} while (it != end);
}
- printf("----------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------------\n");
- end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars;
+ end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
if (it != end) {
do {
- printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
+ v = (*it).jsValue();
+#if USE(JSVALUE32_64)
+ printf("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+#else
+ printf("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+#endif
++it;
++registerCount;
} while (it != end);
}
- printf("----------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------------\n");
}
#endif
#endif
}
-NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
+NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
{
CodeBlock* oldCodeBlock = codeBlock;
ScopeChainNode* scopeChain = callFrame->scopeChain();
return true;
}
-NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
+NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
{
// Set up the exception object
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));
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 2].u.operand).jsValue());
else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
- profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 10].u.operand).jsValue());
#else
int functionRegisterIndex;
if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
- profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));
+ profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
#endif
}
return handler;
}
-JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception)
+JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
globalObject->copyGlobalsTo(m_registerFile);
CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
- newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
if (codeBlock->needsFullScopeChain())
if (*profiler)
(*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
- JSValuePtr result;
+ JSValue 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);
+ result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
return result;
}
-JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception)
+JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
Register* oldEnd = m_registerFile.end();
CallFrame* newCallFrame = CallFrame::create(oldEnd);
size_t dst = 0;
- newCallFrame[0] = JSValuePtr(thisObj);
+ newCallFrame->r(0) = JSValue(thisObj);
ArgList::const_iterator end = args.end();
for (ArgList::const_iterator it = args.begin(); it != end; ++it)
- newCallFrame[++dst] = *it;
+ newCallFrame->r(++dst) = *it;
CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
if (*profiler)
(*profiler)->willExecute(callFrame, function);
- JSValuePtr result;
+ JSValue 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);
+ result = functionBodyNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
return result;
}
-JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
+{
+ ASSERT(!scopeChain->globalData->exception);
+
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return CallFrameClosure();
+ }
+ }
+
+ Register* oldEnd = m_registerFile.end();
+ int argc = 1 + argCount; // implicit "this" parameter
+
+ if (!m_registerFile.grow(oldEnd + argc)) {
+ *exception = createStackOverflowError(callFrame);
+ return CallFrameClosure();
+ }
+
+ CallFrame* newCallFrame = CallFrame::create(oldEnd);
+ size_t dst = 0;
+ for (int i = 0; i < argc; ++i)
+ newCallFrame->r(++dst) = jsUndefined();
+
+ 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 CallFrameClosure();
+ }
+ // a 0 codeBlock indicates a built-in caller
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
+#if ENABLE(JIT)
+ functionBodyNode->jitCode(scopeChain);
+#endif
+
+ CallFrameClosure result = { callFrame, newCallFrame, function, functionBodyNode, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
+ return result;
+}
+
+JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
+{
+ closure.resetCallFrame();
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (*profiler)
+ (*profiler)->willExecute(closure.oldCallFrame, closure.function);
+
+ JSValue result;
+ {
+ SamplingTool::CallRecord callRecord(m_sampler);
+
+ m_reentryDepth++;
+#if ENABLE(JIT)
+ result = closure.functionBody->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+#else
+ result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+#endif
+ m_reentryDepth--;
+ }
+
+ if (*profiler)
+ (*profiler)->didExecute(closure.oldCallFrame, closure.function);
+ return result;
+}
+
+void Interpreter::endRepeatCall(CallFrameClosure& closure)
+{
+ m_registerFile.shrink(closure.oldEnd);
+}
+
+JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* 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)
+JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
// a 0 codeBlock indicates a built-in caller
- newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
if (codeBlock->needsFullScopeChain())
if (*profiler)
(*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
- JSValuePtr result;
+ JSValue 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);
+ result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
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;
-}
-
+#if USE(INTERPRETER)
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);
+ JSValue value = callFrame->r((++vPC)->u.operand).jsValue();
JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
- callFrame[dst] = JSValuePtr(scope);
+ callFrame->r(dst) = JSValue(scope);
return callFrame->scopeChain()->push(scope);
}
-NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot)
+NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
{
// Recursive invocation may already have specialized this instruction.
if (vPC[0].u.opcode != getOpcode(op_put_by_id))
JSCell* baseCell = asCell(baseValue);
Structure* structure = baseCell->structure();
- if (structure->isDictionary()) {
+ if (structure->isUncacheableDictionary()) {
vPC[0] = getOpcode(op_put_by_id_generic);
return;
}
return;
}
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
// Structure transition, cache transition info
if (slot.type() == PutPropertySlot::NewProperty) {
+ if (structure->isDictionary()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
vPC[0] = getOpcode(op_put_by_id_transition);
vPC[4] = structure->previousID();
vPC[5] = structure;
- vPC[6] = structure->prototypeChain(callFrame);
+ vPC[6] = protoChain;
vPC[7] = slot.cachedOffset();
codeBlock->refStructures(vPC);
return;
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)
+NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue 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;
}
- if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
+ JSGlobalData* globalData = &callFrame->globalData();
+ if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
vPC[0] = getOpcode(op_get_array_length);
return;
}
- if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
+ if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
vPC[0] = getOpcode(op_get_string_length);
return;
}
Structure* structure = asCell(baseValue)->structure();
- if (structure->isDictionary()) {
+ if (structure->isUncacheableDictionary()) {
vPC[0] = getOpcode(op_get_by_id_generic);
return;
}
return;
}
+ if (structure->isDictionary()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
ASSERT(slot.slotBase().isObject());
JSObject* baseObject = asObject(slot.slotBase());
+ size_t offset = slot.cachedOffset();
// 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()));
+ if (baseObject->structure()->isDictionary()) {
+ baseObject->flattenDictionaryObject();
+ offset = baseObject->structure()->get(propertyName);
+ }
+
+ ASSERT(!baseObject->structure()->isUncacheableDictionary());
vPC[0] = getOpcode(op_get_by_id_proto);
vPC[5] = baseObject->structure();
- vPC[6] = slot.cachedOffset();
+ vPC[6] = offset;
codeBlock->refStructures(vPC);
return;
}
- size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
+ size_t offset = slot.cachedOffset();
+ size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
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);
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
+ vPC[0] = getOpcode(op_get_by_id_chain);
+ vPC[4] = structure;
+ vPC[5] = protoChain;
vPC[6] = count;
- vPC[7] = slot.cachedOffset();
+ vPC[7] = offset;
codeBlock->refStructures(vPC);
}
vPC[4] = 0;
}
-JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception)
+#endif // USE(INTERPRETER)
+
+JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* 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 (UNLIKELY(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);
+ #define LIST_OPCODE_LABEL(id, length) &&id,
+ static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
+ for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i)
+ m_opcodeTable[i] = labels[i];
+ #undef LIST_OPCODE_LABEL
#endif // HAVE(COMPUTED_GOTO)
- return noValue();
+ return JSValue();
}
#if ENABLE(JIT)
- // Currently with CTI enabled we never interpret functions
+ // Mixing Interpreter + JIT is not supported.
ASSERT_NOT_REACHED();
#endif
+#if !USE(INTERPRETER)
+ UNUSED_PARAM(registerFile);
+ UNUSED_PARAM(callFrame);
+ UNUSED_PARAM(exception);
+ return JSValue();
+#else
JSGlobalData* globalData = &callFrame->globalData();
- JSValuePtr exceptionValue = noValue();
+ JSValue exceptionValue;
HandlerInfo* handler = 0;
Instruction* vPC = callFrame->codeBlock()->instructions().begin();
Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
- unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
+ unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
#define CHECK_FOR_EXCEPTION() \
do { \
- if (UNLIKELY(globalData->exception != noValue())) { \
+ if (UNLIKELY(globalData->exception != JSValue())) { \
exceptionValue = globalData->exception; \
goto vm_throw; \
} \
#define CHECK_FOR_TIMEOUT() \
if (!--tickCount) { \
- if (checkTimeout(callFrame->dynamicGlobalObject())) { \
+ if (globalData->timeoutChecker.didTimeOut(callFrame)) { \
exceptionValue = jsNull(); \
goto vm_throw; \
} \
- tickCount = m_ticksUntilNextTimeoutCheck; \
+ tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \
}
#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)
constructor, and puts the result in register dst.
*/
int dst = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame));
+ callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
++vPC;
NEXT_INSTRUCTION();
int firstArg = (++vPC)->u.operand;
int argCount = (++vPC)->u.operand;
ArgList args(callFrame->registers() + firstArg, argCount);
- callFrame[dst] = JSValuePtr(constructArray(callFrame, args));
+ callFrame->r(dst) = JSValue(constructArray(callFrame, args));
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int regExp = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
+ callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = callFrame[src];
+ callFrame->r(dst) = callFrame->r(src);
++vPC;
NEXT_INSTRUCTION();
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);
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32())
+ callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
else {
- JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
operator, and puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
if (src.isUndefinedOrNull()) {
- callFrame[dst] = jsBoolean(true);
+ callFrame->r(dst) = jsBoolean(true);
++vPC;
NEXT_INSTRUCTION();
}
- callFrame[dst] = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
+ callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
++vPC;
NEXT_INSTRUCTION();
}
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);
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32())
+ callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
else {
- JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
operator, and puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
if (src.isUndefinedOrNull()) {
- callFrame[dst] = jsBoolean(false);
+ callFrame->r(dst) = jsBoolean(false);
++vPC;
NEXT_INSTRUCTION();
}
- callFrame[dst] = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
+ callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
++vPC;
NEXT_INSTRUCTION();
}
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ callFrame->r(dst) = jsBoolean(JSValue::strictEqual(src1, src2));
++vPC;
NEXT_INSTRUCTION();
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(src1, src2));
++vPC;
NEXT_INSTRUCTION();
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
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));
+ JSValue v = callFrame->r(srcDst).jsValue();
+ if (v.isInt32() && v.asInt32() < INT_MAX)
+ callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
else {
- JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
+ JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
CHECK_FOR_EXCEPTION();
- callFrame[srcDst] = result;
+ callFrame->r(srcDst) = result;
}
++vPC;
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));
+ JSValue v = callFrame->r(srcDst).jsValue();
+ if (v.isInt32() && v.asInt32() > INT_MIN)
+ callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
else {
- JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
+ JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
CHECK_FOR_EXCEPTION();
- callFrame[srcDst] = result;
+ callFrame->r(srcDst) = result;
}
++vPC;
*/
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));
+ JSValue v = callFrame->r(srcDst).jsValue();
+ if (v.isInt32() && v.asInt32() < INT_MAX) {
+ callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
+ callFrame->r(dst) = v;
} else {
- JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
- callFrame[dst] = number;
- callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1));
+ callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() + 1);
+ callFrame->r(dst) = number;
}
++vPC;
*/
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));
+ JSValue v = callFrame->r(srcDst).jsValue();
+ if (v.isInt32() && v.asInt32() > INT_MIN) {
+ callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
+ callFrame->r(dst) = v;
} else {
- JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
- callFrame[dst] = number;
- callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1));
+ callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() - 1);
+ callFrame->r(dst) = number;
}
++vPC;
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValuePtr srcVal = callFrame[src].jsValue(callFrame);
+ JSValue srcVal = callFrame->r(src).jsValue();
if (LIKELY(srcVal.isNumber()))
- callFrame[dst] = callFrame[src];
+ callFrame->r(dst) = callFrame->r(src);
else {
- JSValuePtr result = srcVal.toJSNumber(callFrame);
+ JSValue result = srcVal.toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
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));
+ JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src.isInt32() && src.asInt32())
+ callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
+ ++vPC;
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_add) {
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
else {
- JSValuePtr result = jsAdd(callFrame, src1, src2);
+ JSValue result = jsAdd(callFrame, src1, src2);
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
NEXT_INSTRUCTION();
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
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;
+ JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue();
+
+ JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION();
+ callFrame->r(dst) = result;
+
+ vPC += 2;
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_mod) {
remainder in register dst.
*/
int dst = (++vPC)->u.operand;
- int dividend = (++vPC)->u.operand;
- int divisor = (++vPC)->u.operand;
+ JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue();
- 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());
+ if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
+ JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
ASSERT(result);
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
}
- double d = dividendValue.toNumber(callFrame);
- JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame)));
+ // Conversion to double must happen outside the call to fmod since the
+ // order of argument evaluation is not guaranteed.
+ double d1 = dividend.toNumber(callFrame);
+ double d2 = divisor.toNumber(callFrame);
+ JSValue result = jsNumber(callFrame, fmod(d1, d2));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
}
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
NEXT_INSTRUCTION();
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)));
+ JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+
+ if (val.isInt32() && shift.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
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)));
+ JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+
+ if (val.isInt32() && shift.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
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));
+ JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+ if (val.isUInt32() && shift.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
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));
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src1.isInt32() && src2.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
vPC += 2;
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));
+ JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+ if (src.isInt32())
+ callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
else {
- JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
}
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame));
+ JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
int base = vPC[3].u.operand;
int baseProto = vPC[4].u.operand;
- JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
+ JSValue baseVal = callFrame->r(base).jsValue();
- if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+ if (isInvalidParamForInstanceOf(callFrame, 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);
+ bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
+ CHECK_FOR_EXCEPTION();
+ callFrame->r(dst) = jsBoolean(result);
vPC += 5;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame)));
+ callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
++vPC;
NEXT_INSTRUCTION();
*/
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());
+ JSValue v = callFrame->r(src).jsValue();
+ callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean());
+ callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber());
+ callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString());
+ callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame)));
+ callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
++vPC;
NEXT_INSTRUCTION();
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame)));
+ callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
++vPC;
NEXT_INSTRUCTION();
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))
+ JSValue baseVal = callFrame->r(base).jsValue();
+ if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
goto vm_throw;
JSObject* baseObj = asObject(baseVal);
- JSValuePtr propName = callFrame[property].jsValue(callFrame);
+ JSValue propName = callFrame->r(property).jsValue();
uint32_t i;
if (propName.getUInt32(i))
- callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, i));
+ callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
else {
Identifier property(callFrame, propName.toString(callFrame));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, property));
+ callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
}
++vPC;
ASSERT(scope->isGlobalObject());
int index = (++vPC)->u.operand;
- callFrame[dst] = scope->registerAt(index);
+ callFrame->r(dst) = scope->registerAt(index);
++vPC;
NEXT_INSTRUCTION();
}
int index = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
++vPC;
NEXT_INSTRUCTION();
}
ASSERT((*iter)->isVariableObject());
JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
- callFrame[dst] = scope->registerAt(index);
+ callFrame->r(dst) = scope->registerAt(index);
++vPC;
NEXT_INSTRUCTION();
}
ASSERT((*iter)->isVariableObject());
JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
- scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
++vPC;
NEXT_INSTRUCTION();
}
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)
CodeBlock* codeBlock = callFrame->codeBlock();
Identifier& ident = codeBlock->identifier(property);
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ JSValue result = baseValue.get(callFrame, ident, slot);
CHECK_FOR_EXCEPTION();
tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
vPC += 8;
NEXT_INSTRUCTION();
}
op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
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));
+ callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
reverts to op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
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));
+ ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
+ callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
reverts to op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
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));
+ ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+ callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
int property = vPC[3].u.operand;
Identifier& ident = callFrame->codeBlock()->identifier(property);
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ JSValue result = baseValue.get(callFrame, ident, slot);
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
vPC += 8;
NEXT_INSTRUCTION();
}
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- if (LIKELY(isJSArray(baseValue))) {
+ JSValue baseValue = callFrame->r(base).jsValue();
+ if (LIKELY(isJSArray(globalData, baseValue))) {
int dst = vPC[1].u.operand;
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length()));
+ callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
vPC += 8;
NEXT_INSTRUCTION();
}
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- if (LIKELY(isJSString(baseValue))) {
+ JSValue baseValue = callFrame->r(base).jsValue();
+ if (LIKELY(isJSString(globalData, baseValue))) {
int dst = vPC[1].u.operand;
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size()));
+ callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->value().size());
vPC += 8;
NEXT_INSTRUCTION();
}
int value = vPC[3].u.operand;
CodeBlock* codeBlock = callFrame->codeBlock();
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
the register file.
*/
int base = vPC[1].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
RefPtr<Structure>* it = vPC[6].u.structureChain->head();
- JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame);
+ JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
while (!proto.isNull()) {
if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
uncachePutByID(callFrame->codeBlock(), vPC);
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));
+ baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
vPC += 8;
NEXT_INSTRUCTION();
the register file.
*/
int base = vPC[1].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
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));
+ baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
vPC += 8;
NEXT_INSTRUCTION();
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = callFrame->codeBlock()->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
vPC += 8;
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame);
+ JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
Identifier& ident = callFrame->codeBlock()->identifier(property);
- JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
+ JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
}
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
+ JSValue subscript = callFrame->r(property).jsValue();
- JSValuePtr result;
+ JSValue result;
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (isJSArray(baseValue)) {
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSArray(globalData, 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))
+ } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
result = asString(baseValue)->getIndex(&callFrame->globalData(), i);
- else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
+ else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
result = asByteArray(baseValue)->getIndex(callFrame, i);
else
result = baseValue.get(callFrame, i);
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
}
int property = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+ JSValue baseValue = callFrame->r(base).jsValue();
+ JSValue subscript = callFrame->r(property).jsValue();
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (isJSArray(baseValue)) {
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSArray(globalData, baseValue)) {
JSArray* jsArray = asArray(baseValue);
if (jsArray->canSetIndex(i))
- jsArray->setIndex(i, callFrame[value].jsValue(callFrame));
+ jsArray->setIndex(i, callFrame->r(value).jsValue());
else
- jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame));
- } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
+ } else if (isJSByteArray(globalData, 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());
+ JSValue jsValue = callFrame->r(value).jsValue();
+ if (jsValue.isInt32())
+ jsByteArray->setIndex(i, jsValue.asInt32());
else if (jsValue.getNumber(dValue))
jsByteArray->setIndex(i, dValue);
else
baseValue.put(callFrame, i, jsValue);
} else
- baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame));
+ baseValue.put(callFrame, i, callFrame->r(value).jsValue());
} 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);
+ baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
}
}
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw
+ JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
- JSValuePtr result;
+ JSValue subscript = callFrame->r(property).jsValue();
+ JSValue result;
uint32_t i;
if (subscript.getUInt32(i))
result = jsBoolean(baseObj->deleteProperty(callFrame, i));
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
++vPC;
NEXT_INSTRUCTION();
}
unsigned property = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame));
+ callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
++vPC;
NEXT_INSTRUCTION();
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
vPC += target;
CHECK_FOR_TIMEOUT();
NEXT_INSTRUCTION();
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
vPC += target;
NEXT_INSTRUCTION();
}
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
vPC += target;
NEXT_INSTRUCTION();
}
*/
int src = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+ JSValue srcValue = callFrame->r(src).jsValue();
if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
vPC += target;
*/
int src = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+ JSValue srcValue = callFrame->r(src).jsValue();
if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
vPC += target;
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_jneq_ptr) {
+ /* jneq_ptr src(r) ptr(jsCell) target(offset)
+
+ Jumps to offset target from the current instruction, if the value r is equal
+ to ptr, using pointer equality.
+ */
+ int src = (++vPC)->u.operand;
+ JSValue ptr = JSValue((++vPC)->u.jsCell);
+ int target = (++vPC)->u.operand;
+ JSValue srcValue = callFrame->r(src).jsValue();
+ if (srcValue != ptr) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_loop_if_less) {
/* loop_if_less src1(r) src2(r) target(offset)
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);
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
int target = (++vPC)->u.operand;
bool result = jsLess(callFrame, src1, src2);
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);
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
int target = (++vPC)->u.operand;
bool result = jsLessEq(callFrame, src1, src2);
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);
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
int target = (++vPC)->u.operand;
bool result = jsLess(callFrame, src1, src2);
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_jnlesseq) {
+ /* jnlesseq 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 theresult of the comparison is false.
+ */
+ JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
+ JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+ int target = (++vPC)->u.operand;
+
+ bool result = jsLessEq(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)
*/
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);
+ JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
+ if (scrutinee.isInt32())
+ vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
else {
- int32_t value;
- if (scrutinee.numberToInt32(value))
- vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset);
+ double value;
+ int32_t intValue;
+ if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
+ vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
else
vPC += defaultOffset;
}
*/
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
- JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
if (!scrutinee.isString())
vPC += defaultOffset;
else {
*/
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
- JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
if (!scrutinee.isString())
vPC += defaultOffset;
else
int dst = (++vPC)->u.operand;
int func = (++vPC)->u.operand;
- callFrame[dst] = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain());
+ callFrame->r(dst) = JSValue(callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain()));
++vPC;
NEXT_INSTRUCTION();
int dst = (++vPC)->u.operand;
int func = (++vPC)->u.operand;
- callFrame[dst] = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain());
+ callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain()));
++vPC;
NEXT_INSTRUCTION();
int argCount = vPC[3].u.operand;
int registerOffset = vPC[4].u.operand;
- JSValuePtr funcVal = callFrame[func].jsValue(callFrame);
+ JSValue funcVal = callFrame->r(func).jsValue();
Register* newCallFrame = callFrame->registers() + registerOffset;
Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
- JSValuePtr thisValue = argv[0].jsValue(callFrame);
+ JSValue thisValue = argv[0].jsValue();
JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
- JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
+ JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
if (exceptionValue)
goto vm_throw;
- callFrame[dst] = result;
+ callFrame->r(dst) = result;
vPC += 5;
NEXT_INSTRUCTION();
int argCount = vPC[3].u.operand;
int registerOffset = vPC[4].u.operand;
- JSValuePtr v = callFrame[func].jsValue(callFrame);
+ JSValue v = callFrame->r(func).jsValue();
CallData callData;
CallType callType = v.getCallData(callData);
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);
+ JSValue thisValue = thisRegister->jsValue();
if (thisValue == jsNull())
thisValue = callFrame->globalThisValue();
- JSValuePtr returnValue;
+ JSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(m_sampler);
returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame->r(dst) = returnValue;
vPC += 5;
NEXT_INSTRUCTION();
exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
goto vm_throw;
}
+ DEFINE_OPCODE(op_load_varargs) {
+ int argCountDst = (++vPC)->u.operand;
+ int argsOffset = (++vPC)->u.operand;
+
+ JSValue arguments = callFrame->r(argsOffset).jsValue();
+ int32_t argCount = 0;
+ if (!arguments) {
+ argCount = (uint32_t)(callFrame->argumentCount()) - 1;
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ int32_t expectedParams = callFrame->callee()->body()->parameterCount();
+ int32_t inplaceArgs = min(argCount, expectedParams);
+ int32_t i = 0;
+ Register* argStore = callFrame->registers() + argsOffset;
+
+ // First step is to copy the "expected" parameters from their normal location relative to the callframe
+ for (; i < inplaceArgs; i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
+ // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
+ for (; i < argCount; i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
+ } else if (!arguments.isUndefinedOrNull()) {
+ if (!arguments.isObject()) {
+ exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ if (asObject(arguments)->classInfo() == &Arguments::info) {
+ Arguments* args = asArguments(arguments);
+ argCount = args->numProvidedArguments(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (isJSArray(&callFrame->globalData(), arguments)) {
+ JSArray* array = asArray(arguments);
+ argCount = array->length();
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (asObject(arguments)->inherits(&JSArray::info)) {
+ JSObject* argObject = asObject(arguments);
+ argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ Register* argsBuffer = callFrame->registers() + argsOffset;
+ for (int32_t i = 0; i < argCount; ++i) {
+ argsBuffer[i] = asObject(arguments)->get(callFrame, i);
+ CHECK_FOR_EXCEPTION();
+ }
+ } else {
+ if (!arguments.isObject()) {
+ exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ }
+ }
+ CHECK_FOR_EXCEPTION();
+ callFrame->r(argCountDst) = Register::withInt(argCount + 1);
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_call_varargs) {
+ /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n)
+
+ Perform a function call with a dynamic set of arguments.
+
+ registerOffset is the distance the callFrame pointer should move
+ before the VM initializes the new call frame's header, excluding
+ space for arguments.
+
+ dst is where op_ret should store its result.
+ */
+
+ int dst = vPC[1].u.operand;
+ int func = vPC[2].u.operand;
+ int argCountReg = vPC[3].u.operand;
+ int registerOffset = vPC[4].u.operand;
+
+ JSValue v = callFrame->r(func).jsValue();
+ int argCount = callFrame->r(argCountReg).i();
+ registerOffset += argCount;
+ 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.
+ JSValue thisValue = thisRegister->jsValue();
+ if (thisValue == jsNull())
+ thisValue = callFrame->globalThisValue();
+
+ JSValue returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(m_sampler);
+ returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
+ }
+ CHECK_FOR_EXCEPTION();
+
+ callFrame->r(dst) = 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)
int src = (++vPC)->u.operand;
ASSERT(callFrame->codeBlock()->needsFullScopeChain());
- asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments());
+ asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
++vPC;
NEXT_INSTRUCTION();
ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
- callFrame->optionalCalleeArguments()->copyRegisters();
+ if (callFrame->optionalCalleeArguments())
+ callFrame->optionalCalleeArguments()->copyRegisters();
++vPC;
NEXT_INSTRUCTION();
if (callFrame->codeBlock()->needsFullScopeChain())
callFrame->scopeChain()->deref();
- JSValuePtr returnValue = callFrame[result].jsValue(callFrame);
+ JSValue returnValue = callFrame->r(result).jsValue();
vPC = callFrame->returnPC();
int dst = callFrame->returnValueRegister();
if (callFrame->hasHostCallFrameFlag())
return returnValue;
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame->r(dst) = returnValue;
NEXT_INSTRUCTION();
}
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);
+ callFrame->r(i) = jsUndefined();
++vPC;
NEXT_INSTRUCTION();
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);
+ callFrame->r(i) = jsUndefined();
int dst = (++vPC)->u.operand;
JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode()));
- callFrame[dst] = activation;
+ callFrame->r(dst) = JSValue(activation);
callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
++vPC;
*/
int thisRegister = (++vPC)->u.operand;
- JSValuePtr thisVal = callFrame[thisRegister].getJSValue();
+ JSValue thisVal = callFrame->r(thisRegister).jsValue();
if (thisVal.needsThisConversion())
- callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame));
+ callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
++vPC;
NEXT_INSTRUCTION();
}
- DEFINE_OPCODE(op_create_arguments) {
+ DEFINE_OPCODE(op_init_arguments) {
/* create_arguments
- Creates the 'arguments' object and places it in both the
- 'arguments' call frame slot and the local 'arguments'
- register.
+ Initialises the arguments object reference to null to ensure
+ we can correctly detect that we need to create it later (or
+ avoid creating it altogether).
This opcode should only be used at the beginning of a code
block.
- */
+ */
+ callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_create_arguments) {
+ /* create_arguments
- Arguments* arguments = new (globalData) Arguments(callFrame);
- callFrame->setCalleeArguments(arguments);
- callFrame[RegisterFile::ArgumentsRegister] = arguments;
+ Creates the 'arguments' object and places it in both the
+ 'arguments' call frame slot and the local 'arguments'
+ register, if it has not already been initialised.
+ */
+ if (!callFrame->r(RegisterFile::ArgumentsRegister).jsValue()) {
+ Arguments* arguments = new (globalData) Arguments(callFrame);
+ callFrame->setCalleeArguments(arguments);
+ callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
+ }
++vPC;
NEXT_INSTRUCTION();
}
int proto = vPC[5].u.operand;
int thisRegister = vPC[6].u.operand;
- JSValuePtr v = callFrame[func].jsValue(callFrame);
+ JSValue v = callFrame->r(func).jsValue();
ConstructData constructData;
ConstructType constructType = v.getConstructData(constructData);
CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
Structure* structure;
- JSValuePtr prototype = callFrame[proto].jsValue(callFrame);
+ JSValue prototype = callFrame->r(proto).jsValue();
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->r(thisRegister) = JSValue(newObject); // "this" value
CallFrame* previousCallFrame = callFrame;
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
- JSValuePtr returnValue;
+ JSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(m_sampler);
returnValue = constructData.native.function(newCallFrame, asObject(v), args);
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame->r(dst) = JSValue(returnValue);
vPC += 7;
NEXT_INSTRUCTION();
the object in register override to register dst.
*/
- int dst = vPC[1].u.operand;;
- if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) {
+ int dst = vPC[1].u.operand;
+ if (LIKELY(callFrame->r(dst).jsValue().isObject())) {
vPC += 3;
NEXT_INSTRUCTION();
}
int override = vPC[2].u.operand;
- callFrame[dst] = callFrame[override];
+ callFrame->r(dst) = callFrame->r(override);
vPC += 3;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_strcat) {
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ int count = (++vPC)->u.operand;
+
+ callFrame->r(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
+ ++vPC;
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_to_primitive) {
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+
+ callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
+ ++vPC;
+
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_push_scope) {
/* push_scope scope(r)
are replaced by the result of toObject conversion of the scope.
*/
int scope = (++vPC)->u.operand;
- JSValuePtr v = callFrame[scope].jsValue(callFrame);
+ JSValue v = callFrame->r(scope).jsValue();
JSObject* o = v.toObject(callFrame);
CHECK_FOR_EXCEPTION();
- callFrame[scope] = JSValuePtr(o);
+ callFrame->r(scope) = JSValue(o);
callFrame->setScopeChain(callFrame->scopeChain()->push(o));
++vPC;
int dst = (++vPC)->u.operand;
int base = (++vPC)->u.operand;
- callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame));
+ callFrame->r(dst) = JSPropertyNameIterator::create(callFrame, callFrame->r(base).jsValue());
++vPC;
NEXT_INSTRUCTION();
}
int iter = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator();
- if (JSValuePtr temp = it->next(callFrame)) {
+ JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
+ if (JSValue temp = it->next(callFrame)) {
CHECK_FOR_TIMEOUT();
- callFrame[dst] = JSValuePtr(temp);
+ callFrame->r(dst) = JSValue(temp);
vPC += target;
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_catch) {
/* catch ex(r)
- Retrieves the VMs current exception and puts it in register
+ Retrieves the VM's 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();
+ callFrame->r(ex) = exceptionValue;
+ exceptionValue = JSValue();
++vPC;
NEXT_INSTRUCTION();
*/
int ex = (++vPC)->u.operand;
- exceptionValue = callFrame[ex].jsValue(callFrame);
+ exceptionValue = callFrame->r(ex).jsValue();
handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
if (!handler) {
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)
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()));
+ callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
++vPC;
NEXT_INSTRUCTION();
scopeChain->deref();
}
int result = (++vPC)->u.operand;
- return callFrame[result].jsValue(callFrame);
+ return callFrame->r(result).jsValue();
}
DEFINE_OPCODE(op_put_getter) {
/* put_getter base(r) property(id) function(r)
int property = (++vPC)->u.operand;
int function = (++vPC)->u.operand;
- ASSERT(callFrame[base].jsValue(callFrame).isObject());
- JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ ASSERT(callFrame->r(base).jsValue().isObject());
+ JSObject* baseObj = asObject(callFrame->r(base).jsValue());
Identifier& ident = callFrame->codeBlock()->identifier(property);
- ASSERT(callFrame[function].jsValue(callFrame).isObject());
- baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+ ASSERT(callFrame->r(function).jsValue().isObject());
+ baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
++vPC;
NEXT_INSTRUCTION();
int property = (++vPC)->u.operand;
int function = (++vPC)->u.operand;
- ASSERT(callFrame[base].jsValue(callFrame).isObject());
- JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ ASSERT(callFrame->r(base).jsValue().isObject());
+ JSObject* baseObj = asObject(callFrame->r(base).jsValue());
Identifier& ident = callFrame->codeBlock()->identifier(property);
- ASSERT(callFrame[function].jsValue(callFrame).isObject());
- baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+ ASSERT(callFrame->r(function).jsValue().isObject());
+ baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_method_check) {
+ vPC++;
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_jsr) {
/* jsr retAddrDst(r) target(offset)
*/
int retAddrDst = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- callFrame[retAddrDst] = vPC + 1;
+ callFrame->r(retAddrDst) = vPC + 1;
vPC += target;
NEXT_INSTRUCTION();
register, not as an immediate.
*/
int retAddrSrc = (++vPC)->u.operand;
- vPC = callFrame[retAddrSrc].vPC();
+ vPC = callFrame->r(retAddrSrc).vPC();
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_debug) {
int function = vPC[1].u.operand;
if (*enabledProfilerReference)
- (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame));
+ (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
vPC += 2;
NEXT_INSTRUCTION();
int function = vPC[1].u.operand;
if (*enabledProfilerReference)
- (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame));
+ (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
vPC += 2;
NEXT_INSTRUCTION();
}
vm_throw: {
- globalData->exception = noValue();
+ globalData->exception = JSValue();
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)
#if !HAVE(COMPUTED_GOTO)
} // iterator loop ends
#endif
+#endif // USE(INTERPRETER)
#undef NEXT_INSTRUCTION
#undef DEFINE_OPCODE
#undef CHECK_FOR_EXCEPTION
#undef CHECK_FOR_TIMEOUT
}
-JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
{
CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
if (!functionCallFrame)
ASSERT(codeBlock->codeType() == FunctionCode);
SymbolTable& symbolTable = codeBlock->symbolTable();
int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
- return functionCallFrame[argumentsIndex].jsValue(callFrame);
+ if (!functionCallFrame->r(argumentsIndex).jsValue()) {
+ Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
+ functionCallFrame->setCalleeArguments(arguments);
+ functionCallFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
+ }
+ return functionCallFrame->r(argumentsIndex).jsValue();
}
Arguments* arguments = functionCallFrame->optionalCalleeArguments();
return arguments;
}
-JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
+JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
{
CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
if (!functionCallFrame)
if (callerFrame->hasHostCallFrameFlag())
return jsNull();
- JSValuePtr caller = callerFrame->callee();
+ JSValue caller = callerFrame->callee();
if (!caller)
return jsNull();
return caller;
}
-void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const
+void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
{
- function = noValue();
+ function = JSValue();
lineNumber = -1;
sourceURL = UString();
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() && slot.slotBase() == globalObject) {
- 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
#define Interpreter_h
#include "ArgList.h"
+#include "FastAllocBase.h"
+#include "HashMap.h"
#include "JSCell.h"
#include "JSValue.h"
+#include "JSObject.h"
#include "Opcode.h"
#include "RegisterFile.h"
-#include <wtf/HashMap.h>
namespace JSC {
class FunctionBodyNode;
class Instruction;
class InternalFunction;
- class AssemblerBuffer;
class JSFunction;
class JSGlobalObject;
class ProgramNode;
class Register;
class ScopeChainNode;
class SamplingTool;
+ struct CallFrameClosure;
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,
// We use a smaller reentrancy limit on iPhone because of the high amount of
// stack space required on the web thread.
- enum { MaxReentryDepth = 100 };
+ enum { MaxMainThreadReentryDepth = 100, MaxSecondaryThreadReentryDepth = 32 };
- class Interpreter {
+ class Interpreter : public FastAllocBase {
friend class JIT;
+ friend class CachedCall;
public:
Interpreter();
- ~Interpreter();
- void initialize(JSGlobalData*);
-
RegisterFile& registerFile() { return m_registerFile; }
Opcode getOpcode(OpcodeID id)
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);
+ JSValue execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
+ JSValue execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
+ JSValue execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
- JSValuePtr retrieveArguments(CallFrame*, JSFunction*) const;
- JSValuePtr retrieveCaller(CallFrame*, InternalFunction*) const;
- void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const;
+ JSValue retrieveArguments(CallFrame*, JSFunction*) const;
+ JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
+ void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& 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; }
+ NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
+ NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
+ NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
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);
+ CallFrameClosure prepareForRepeatCall(FunctionBodyNode*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
+ void endRepeatCall(CallFrameClosure&);
+ JSValue execute(CallFrameClosure&, JSValue* exception);
- NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
+ JSValue execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
- NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
- NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
- NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+#if USE(INTERPRETER)
+ NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
- NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValue& 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);
+ void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
+ void uncacheGetByID(CodeBlock*, Instruction* vPC);
+ void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
+ void uncachePutByID(CodeBlock*, Instruction* vPC);
+#endif
+
+ NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
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);
+ JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue* 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
#define Register_h
#include "JSValue.h"
+#include <wtf/Assertions.h>
+#include <wtf/FastAllocBase.h>
#include <wtf/VectorTraits.h>
namespace JSC {
typedef ExecState CallFrame;
- class Register {
+ class Register : public WTF::FastAllocBase {
public:
Register();
- Register(JSValuePtr);
- JSValuePtr jsValue(CallFrame*) const;
- JSValuePtr getJSValue() const;
+ Register(const JSValue&);
+ Register& operator=(const JSValue&);
+ JSValue jsValue() 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;
-
+ Register& operator=(JSActivation*);
+ Register& operator=(CallFrame*);
+ Register& operator=(CodeBlock*);
+ Register& operator=(JSFunction*);
+ Register& operator=(JSPropertyNameIterator*);
+ Register& operator=(ScopeChainNode*);
+ Register& operator=(Instruction*);
+
+ int32_t i() const;
JSActivation* activation() const;
Arguments* arguments() const;
CallFrame* callFrame() const;
ScopeChainNode* scopeChain() const;
Instruction* vPC() const;
+ static Register withInt(int32_t i)
+ {
+ Register r;
+ r.u.i = i;
+ return r;
+ }
+
+ private:
union {
- intptr_t i;
- void* v;
- JSValueEncodedAsPointer* value;
+ int32_t i;
+ EncodedJSValue value;
JSActivation* activation;
- Arguments* arguments;
CallFrame* callFrame;
CodeBlock* codeBlock;
JSFunction* function;
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());
+ *this = JSValue();
#endif
}
- ALWAYS_INLINE Register::Register(JSValuePtr v)
+ ALWAYS_INLINE Register::Register(const JSValue& v)
{
- SET_TYPE(ValueType);
- u.value = JSValuePtr::encode(v);
+ u.value = JSValue::encode(v);
}
- // This function is scaffolding for legacy clients. It will eventually go away.
- ALWAYS_INLINE JSValuePtr Register::jsValue(CallFrame*) const
+ ALWAYS_INLINE Register& Register::operator=(const JSValue& v)
{
- // 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);
+#if ENABLE(JSC_ZOMBIES)
+ ASSERT(!v.isZombie());
+#endif
+ u.value = JSValue::encode(v);
+ return *this;
}
-
- ALWAYS_INLINE JSValuePtr Register::getJSValue() const
+
+ ALWAYS_INLINE JSValue Register::jsValue() const
{
- ASSERT_TYPE(JSValueType);
- return JSValuePtr::decode(u.value);
+ return JSValue::decode(u.value);
}
ALWAYS_INLINE bool Register::marked() const
{
- return getJSValue().marked();
+ return jsValue().marked();
}
ALWAYS_INLINE void Register::mark()
{
- getJSValue().mark();
+ jsValue().mark();
}
// Interpreter functions
- ALWAYS_INLINE Register::Register(Arguments* arguments)
- {
- SET_TYPE(ArgumentsType);
- u.arguments = arguments;
- }
-
- ALWAYS_INLINE Register::Register(JSActivation* activation)
+ ALWAYS_INLINE Register& Register::operator=(JSActivation* activation)
{
- SET_TYPE(ActivationType);
u.activation = activation;
+ return *this;
}
- ALWAYS_INLINE Register::Register(CallFrame* callFrame)
+ ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame)
{
- SET_TYPE(CallFrameType);
u.callFrame = callFrame;
+ return *this;
}
- ALWAYS_INLINE Register::Register(CodeBlock* codeBlock)
+ ALWAYS_INLINE Register& Register::operator=(CodeBlock* codeBlock)
{
- SET_TYPE(CodeBlockType);
u.codeBlock = codeBlock;
+ return *this;
}
- ALWAYS_INLINE Register::Register(JSFunction* function)
+ ALWAYS_INLINE Register& Register::operator=(JSFunction* function)
{
- SET_TYPE(FunctionType);
u.function = function;
+ return *this;
}
- ALWAYS_INLINE Register::Register(Instruction* vPC)
+ ALWAYS_INLINE Register& Register::operator=(Instruction* vPC)
{
- SET_TYPE(InstructionType);
u.vPC = vPC;
+ return *this;
}
- ALWAYS_INLINE Register::Register(ScopeChainNode* scopeChain)
+ ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
{
- SET_TYPE(ScopeChainNodeType);
u.scopeChain = scopeChain;
+ return *this;
}
- ALWAYS_INLINE Register::Register(JSPropertyNameIterator* propertyNameIterator)
+ ALWAYS_INLINE Register& Register::operator=(JSPropertyNameIterator* propertyNameIterator)
{
- SET_TYPE(PropertyNameIteratorType);
u.propertyNameIterator = propertyNameIterator;
+ return *this;
}
- ALWAYS_INLINE Register::Register(intptr_t i)
- {
- SET_TYPE(IntType);
- u.i = i;
- }
-
- ALWAYS_INLINE intptr_t Register::i() const
+ ALWAYS_INLINE int32_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 {
#endif
}
+void RegisterFile::releaseExcessCapacity()
+{
+#if HAVE(MMAP) && HAVE(MADV_FREE) && !HAVE(VIRTUALALLOC)
+ while (madvise(m_start, (m_max - m_start) * sizeof(Register), MADV_FREE) == -1 && errno == EAGAIN) { }
+#elif HAVE(VIRTUALALLOC)
+ VirtualFree(m_start, (m_max - m_start) * sizeof(Register), MEM_DECOMMIT);
+ m_commitEnd = m_start;
+#endif
+ m_maxUsed = m_start;
+}
+
} // namespace JSC
#ifndef RegisterFile_h
#define RegisterFile_h
-#include "Register.h"
#include "Collector.h"
+#include "ExecutableAllocator.h"
+#include "Register.h"
#include <wtf/Noncopyable.h>
+#include <wtf/VMTags.h>
#if HAVE(MMAP)
#include <errno.h>
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;
- }
+ static const size_t commitSize = 1 << 14;
+ // Allow 8k of excess registers before we start trying to reap the registerfile
+ static const ptrdiff_t maxExcessCapacity = 8 * 1024;
+ RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals);
~RegisterFile();
Register* start() const { return 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;
- }
+ bool grow(Register* newEnd);
+ void shrink(Register* newEnd);
void setNumGlobals(size_t numGlobals) { m_numGlobals = numGlobals; }
int numGlobals() const { return m_numGlobals; }
void markCallFrames(Heap* heap) { heap->markConservatively(m_start, m_end); }
private:
+ void releaseExcessCapacity();
size_t m_numGlobals;
const size_t m_maxGlobals;
Register* m_start;
Register* m_end;
Register* m_max;
Register* m_buffer;
+ Register* m_maxUsed;
+
#if HAVE(VIRTUALALLOC)
- Register* m_maxCommitted;
+ Register* m_commitEnd;
#endif
JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file.
};
+ // FIXME: Add a generic getpagesize() to WTF, then move this function to WTF as well.
+ inline bool isPageAligned(size_t size) { return size != 0 && size % (8 * 1024) == 0; }
+
+ inline RegisterFile::RegisterFile(size_t capacity, size_t maxGlobals)
+ : m_numGlobals(0)
+ , m_maxGlobals(maxGlobals)
+ , m_start(0)
+ , m_end(0)
+ , m_max(0)
+ , m_buffer(0)
+ , m_globalObject(0)
+ {
+ // Verify that our values will play nice with mmap and VirtualAlloc.
+ ASSERT(isPageAligned(maxGlobals));
+ ASSERT(isPageAligned(capacity));
+
+ 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, VM_TAG_FOR_REGISTERFILE_MEMORY, 0));
+ if (m_buffer == MAP_FAILED) {
+#if PLATFORM(WINCE)
+ fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
+#else
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+#endif
+ CRASH();
+ }
+ #elif HAVE(VIRTUALALLOC)
+ m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE));
+ if (!m_buffer) {
+#if PLATFORM(WINCE)
+ fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
+#else
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+#endif
+ CRASH();
+ }
+ size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize);
+ void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE);
+ if (commitCheck != m_buffer) {
+#if PLATFORM(WINCE)
+ fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
+#else
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+#endif
+ CRASH();
+ }
+ m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize);
+ #else
+ #error "Don't know how to reserve virtual memory on this platform."
+ #endif
+ m_start = m_buffer + maxGlobals;
+ m_end = m_start;
+ m_maxUsed = m_end;
+ m_max = m_start + capacity;
+ }
+
+ inline void RegisterFile::shrink(Register* newEnd)
+ {
+ if (newEnd >= m_end)
+ return;
+ m_end = newEnd;
+ if (m_end == m_start && (m_maxUsed - m_start) > maxExcessCapacity)
+ releaseExcessCapacity();
+ }
+
+ inline bool RegisterFile::grow(Register* newEnd)
+ {
+ if (newEnd < m_end)
+ return true;
+
+ if (newEnd > m_max)
+ return false;
+
+#if !HAVE(MMAP) && HAVE(VIRTUALALLOC)
+ if (newEnd > m_commitEnd) {
+ size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
+ if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) {
+#if PLATFORM(WINCE)
+ fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
+#else
+ fprintf(stderr, "Could not allocate register file: %d\n", errno);
+#endif
+ CRASH();
+ }
+ m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_commitEnd) + size);
+ }
+#endif
+
+ if (newEnd > m_maxUsed)
+ m_maxUsed = newEnd;
+
+ m_end = newEnd;
+ return true;
+ }
+
} // namespace JSC
#endif // RegisterFile_h
#ifndef ExecutableAllocator_h
#define ExecutableAllocator_h
-#if ENABLE(ASSEMBLER)
-
+#include <limits>
#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/UnusedParam.h>
#include <wtf/Vector.h>
-#include <limits>
+#include <libkern/OSCacheControl.h>
+#include <sys/mman.h>
#define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+#define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE)
+#define PROTECTION_FLAGS_RX (PROT_READ | PROT_EXEC)
+#define INITIAL_PROTECTION_FLAGS PROTECTION_FLAGS_RX
+#else
+#define INITIAL_PROTECTION_FLAGS (PROT_READ | PROT_WRITE | PROT_EXEC)
+#endif
+
+namespace JSC {
+
+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;
+}
+
+}
+
+#if ENABLE(ASSEMBLER)
+
namespace JSC {
class ExecutablePool : public RefCounted<ExecutablePool> {
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);
};
class ExecutableAllocator {
+ enum ProtectionSeting { Writable, Executable };
+
public:
static size_t pageSize;
ExecutableAllocator()
return pool.release();
}
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+ static void makeWritable(void* start, size_t size)
+ {
+ reprotectRegion(start, size, Writable);
+ }
+
+ static void makeExecutable(void* start, size_t size)
+ {
+ reprotectRegion(start, size, Executable);
+ }
+#else
+ static void makeWritable(void*, size_t) {}
+ static void makeExecutable(void*, size_t) {}
+#endif
+
+
+#if PLATFORM(X86) || PLATFORM(X86_64)
+ static void cacheFlush(void*, size_t)
+ {
+ }
+#elif PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
+ static void cacheFlush(void* code, size_t size)
+ {
+ sys_dcache_flush(code, size);
+ sys_icache_invalidate(code, size);
+ }
+#else
+#error "ExecutableAllocator::cacheFlush not implemented on this platform."
+#endif
+
private:
+
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+ static void reprotectRegion(void*, size_t, ProtectionSeting);
+#endif
+
RefPtr<ExecutablePool> m_smallAllocationPool;
static void intializePageSize();
};
}
}
-
#endif // ENABLE(ASSEMBLER)
#endif // !defined(ExecutableAllocator)
--- /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 "ExecutableAllocator.h"
+
+#include <errno.h>
+
+#if ENABLE(ASSEMBLER) && PLATFORM(MAC) && PLATFORM(X86_64)
+
+#include "TCSpinLock.h"
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <wtf/AVLTree.h>
+#include <wtf/VMTags.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+#define TWO_GB (2u * 1024u * 1024u * 1024u)
+#define SIXTEEN_MB (16u * 1024u * 1024u)
+
+// FreeListEntry describes a free chunk of memory, stored in the freeList.
+struct FreeListEntry {
+ FreeListEntry(void* pointer, size_t size)
+ : pointer(pointer)
+ , size(size)
+ , nextEntry(0)
+ , less(0)
+ , greater(0)
+ , balanceFactor(0)
+ {
+ }
+
+ // All entries of the same size share a single entry
+ // in the AVLTree, and are linked together in a linked
+ // list, using nextEntry.
+ void* pointer;
+ size_t size;
+ FreeListEntry* nextEntry;
+
+ // These fields are used by AVLTree.
+ FreeListEntry* less;
+ FreeListEntry* greater;
+ int balanceFactor;
+};
+
+// Abstractor class for use in AVLTree.
+// Nodes in the AVLTree are of type FreeListEntry, keyed on
+// (and thus sorted by) their size.
+struct AVLTreeAbstractorForFreeList {
+ typedef FreeListEntry* handle;
+ typedef int32_t size;
+ typedef size_t key;
+
+ handle get_less(handle h) { return h->less; }
+ void set_less(handle h, handle lh) { h->less = lh; }
+ handle get_greater(handle h) { return h->greater; }
+ void set_greater(handle h, handle gh) { h->greater = gh; }
+ int get_balance_factor(handle h) { return h->balanceFactor; }
+ void set_balance_factor(handle h, int bf) { h->balanceFactor = bf; }
+
+ static handle null() { return 0; }
+
+ int compare_key_key(key va, key vb) { return va - vb; }
+ int compare_key_node(key k, handle h) { return compare_key_key(k, h->size); }
+ int compare_node_node(handle h1, handle h2) { return compare_key_key(h1->size, h2->size); }
+};
+
+// Used to reverse sort an array of FreeListEntry pointers.
+static int reverseSortFreeListEntriesByPointer(const void* leftPtr, const void* rightPtr)
+{
+ FreeListEntry* left = *(FreeListEntry**)leftPtr;
+ FreeListEntry* right = *(FreeListEntry**)rightPtr;
+
+ return (intptr_t)(right->pointer) - (intptr_t)(left->pointer);
+}
+
+// Used to reverse sort an array of pointers.
+static int reverseSortCommonSizedAllocations(const void* leftPtr, const void* rightPtr)
+{
+ void* left = *(void**)leftPtr;
+ void* right = *(void**)rightPtr;
+
+ return (intptr_t)right - (intptr_t)left;
+}
+
+class FixedVMPoolAllocator
+{
+ // The free list is stored in a sorted tree.
+ typedef AVLTree<AVLTreeAbstractorForFreeList, 40> SizeSortedFreeTree;
+
+ // Use madvise as apropriate to prevent freed pages from being spilled,
+ // and to attempt to ensure that used memory is reported correctly.
+#if HAVE(MADV_FREE_REUSE)
+ void release(void* position, size_t size)
+ {
+ while (madvise(position, size, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+ }
+
+ void reuse(void* position, size_t size)
+ {
+ while (madvise(position, size, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
+ }
+#elif HAVE(MADV_DONTNEED)
+ void release(void* position, size_t size)
+ {
+ while (madvise(position, size, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
+ }
+
+ void reuse(void*, size_t) {}
+#else
+ void release(void*, size_t) {}
+ void reuse(void*, size_t) {}
+#endif
+
+ // All addition to the free list should go through this method, rather than
+ // calling insert directly, to avoid multiple entries beging added with the
+ // same key. All nodes being added should be singletons, they should not
+ // already be a part of a chain.
+ void addToFreeList(FreeListEntry* entry)
+ {
+ ASSERT(!entry->nextEntry);
+
+ if (entry->size == m_commonSize) {
+ m_commonSizedAllocations.append(entry->pointer);
+ delete entry;
+ } else if (FreeListEntry* entryInFreeList = m_freeList.search(entry->size, m_freeList.EQUAL)) {
+ // m_freeList already contain an entry for this size - insert this node into the chain.
+ entry->nextEntry = entryInFreeList->nextEntry;
+ entryInFreeList->nextEntry = entry;
+ } else
+ m_freeList.insert(entry);
+ }
+
+ // We do not attempt to coalesce addition, which may lead to fragmentation;
+ // instead we periodically perform a sweep to try to coalesce neigboring
+ // entries in m_freeList. Presently this is triggered at the point 16MB
+ // of memory has been released.
+ void coalesceFreeSpace()
+ {
+ Vector<FreeListEntry*> freeListEntries;
+ SizeSortedFreeTree::Iterator iter;
+ iter.start_iter_least(m_freeList);
+
+ // Empty m_freeList into a Vector.
+ for (FreeListEntry* entry; (entry = *iter); ++iter) {
+ // Each entry in m_freeList might correspond to multiple
+ // free chunks of memory (of the same size). Walk the chain
+ // (this is likely of couse only be one entry long!) adding
+ // each entry to the Vector (at reseting the next in chain
+ // pointer to separate each node out).
+ FreeListEntry* next;
+ do {
+ next = entry->nextEntry;
+ entry->nextEntry = 0;
+ freeListEntries.append(entry);
+ } while ((entry = next));
+ }
+ // All entries are now in the Vector; purge the tree.
+ m_freeList.purge();
+
+ // Reverse-sort the freeListEntries and m_commonSizedAllocations Vectors.
+ // We reverse-sort so that we can logically work forwards through memory,
+ // whilst popping items off the end of the Vectors using last() and removeLast().
+ qsort(freeListEntries.begin(), freeListEntries.size(), sizeof(FreeListEntry*), reverseSortFreeListEntriesByPointer);
+ qsort(m_commonSizedAllocations.begin(), m_commonSizedAllocations.size(), sizeof(void*), reverseSortCommonSizedAllocations);
+
+ // The entries from m_commonSizedAllocations that cannot be
+ // coalesced into larger chunks will be temporarily stored here.
+ Vector<void*> newCommonSizedAllocations;
+
+ // Keep processing so long as entries remain in either of the vectors.
+ while (freeListEntries.size() || m_commonSizedAllocations.size()) {
+ // We're going to try to find a FreeListEntry node that we can coalesce onto.
+ FreeListEntry* coalescionEntry = 0;
+
+ // Is the lowest addressed chunk of free memory of common-size, or is it in the free list?
+ if (m_commonSizedAllocations.size() && (!freeListEntries.size() || (m_commonSizedAllocations.last() < freeListEntries.last()->pointer))) {
+ // Pop an item from the m_commonSizedAllocations vector - this is the lowest
+ // addressed free chunk. Find out the begin and end addresses of the memory chunk.
+ void* begin = m_commonSizedAllocations.last();
+ void* end = (void*)((intptr_t)begin + m_commonSize);
+ m_commonSizedAllocations.removeLast();
+
+ // Try to find another free chunk abutting onto the end of the one we have already found.
+ if (freeListEntries.size() && (freeListEntries.last()->pointer == end)) {
+ // There is an existing FreeListEntry for the next chunk of memory!
+ // we can reuse this. Pop it off the end of m_freeList.
+ coalescionEntry = freeListEntries.last();
+ freeListEntries.removeLast();
+ // Update the existing node to include the common-sized chunk that we also found.
+ coalescionEntry->pointer = (void*)((intptr_t)coalescionEntry->pointer - m_commonSize);
+ coalescionEntry->size += m_commonSize;
+ } else if (m_commonSizedAllocations.size() && (m_commonSizedAllocations.last() == end)) {
+ // There is a second common-sized chunk that can be coalesced.
+ // Allocate a new node.
+ m_commonSizedAllocations.removeLast();
+ coalescionEntry = new FreeListEntry(begin, 2 * m_commonSize);
+ } else {
+ // Nope - this poor little guy is all on his own. :-(
+ // Add him into the newCommonSizedAllocations vector for now, we're
+ // going to end up adding him back into the m_commonSizedAllocations
+ // list when we're done.
+ newCommonSizedAllocations.append(begin);
+ continue;
+ }
+ } else {
+ ASSERT(freeListEntries.size());
+ ASSERT(!m_commonSizedAllocations.size() || (freeListEntries.last()->pointer < m_commonSizedAllocations.last()));
+ // The lowest addressed item is from m_freeList; pop it from the Vector.
+ coalescionEntry = freeListEntries.last();
+ freeListEntries.removeLast();
+ }
+
+ // Right, we have a FreeListEntry, we just need check if there is anything else
+ // to coalesce onto the end.
+ ASSERT(coalescionEntry);
+ while (true) {
+ // Calculate the end address of the chunk we have found so far.
+ void* end = (void*)((intptr_t)coalescionEntry->pointer - coalescionEntry->size);
+
+ // Is there another chunk adjacent to the one we already have?
+ if (freeListEntries.size() && (freeListEntries.last()->pointer == end)) {
+ // Yes - another FreeListEntry -pop it from the list.
+ FreeListEntry* coalescee = freeListEntries.last();
+ freeListEntries.removeLast();
+ // Add it's size onto our existing node.
+ coalescionEntry->size += coalescee->size;
+ delete coalescee;
+ } else if (m_commonSizedAllocations.size() && (m_commonSizedAllocations.last() == end)) {
+ // We can coalesce the next common-sized chunk.
+ m_commonSizedAllocations.removeLast();
+ coalescionEntry->size += m_commonSize;
+ } else
+ break; // Nope, nothing to be added - stop here.
+ }
+
+ // We've coalesced everything we can onto the current chunk.
+ // Add it back into m_freeList.
+ addToFreeList(coalescionEntry);
+ }
+
+ // All chunks of free memory larger than m_commonSize should be
+ // back in m_freeList by now. All that remains to be done is to
+ // copy the contents on the newCommonSizedAllocations back into
+ // the m_commonSizedAllocations Vector.
+ ASSERT(m_commonSizedAllocations.size() == 0);
+ m_commonSizedAllocations.append(newCommonSizedAllocations);
+ }
+
+public:
+
+ FixedVMPoolAllocator(size_t commonSize, size_t totalHeapSize)
+ : m_commonSize(commonSize)
+ , m_countFreedSinceLastCoalesce(0)
+ , m_totalHeapSize(totalHeapSize)
+ {
+ // Cook up an address to allocate at, using the following recipe:
+ // 17 bits of zero, stay in userspace kids.
+ // 26 bits of randomness for ASLR.
+ // 21 bits of zero, at least stay aligned within one level of the pagetables.
+ //
+ // But! - as a temporary workaround for some plugin problems (rdar://problem/6812854),
+ // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
+ // 2^24, which should put up somewhere in the middle of usespace (in the address range
+ // 0x200000000000 .. 0x5fffffffffff).
+ intptr_t randomLocation = arc4random() & ((1 << 25) - 1);
+ randomLocation += (1 << 24);
+ randomLocation <<= 21;
+ m_base = mmap(reinterpret_cast<void*>(randomLocation), m_totalHeapSize, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
+ if (!m_base)
+ CRASH();
+
+ // For simplicity, we keep all memory in m_freeList in a 'released' state.
+ // This means that we can simply reuse all memory when allocating, without
+ // worrying about it's previous state, and also makes coalescing m_freeList
+ // simpler since we need not worry about the possibility of coalescing released
+ // chunks with non-released ones.
+ release(m_base, m_totalHeapSize);
+ m_freeList.insert(new FreeListEntry(m_base, m_totalHeapSize));
+ }
+
+ void* alloc(size_t size)
+ {
+ void* result;
+
+ // Freed allocations of the common size are not stored back into the main
+ // m_freeList, but are instead stored in a separate vector. If the request
+ // is for a common sized allocation, check this list.
+ if ((size == m_commonSize) && m_commonSizedAllocations.size()) {
+ result = m_commonSizedAllocations.last();
+ m_commonSizedAllocations.removeLast();
+ } else {
+ // Serach m_freeList for a suitable sized chunk to allocate memory from.
+ FreeListEntry* entry = m_freeList.search(size, m_freeList.GREATER_EQUAL);
+
+ // This would be bad news.
+ if (!entry) {
+ // Errk! Lets take a last-ditch desparation attempt at defragmentation...
+ coalesceFreeSpace();
+ // Did that free up a large enough chunk?
+ entry = m_freeList.search(size, m_freeList.GREATER_EQUAL);
+ // No?... *BOOM!*
+ if (!entry)
+ CRASH();
+ }
+ ASSERT(entry->size != m_commonSize);
+
+ // Remove the entry from m_freeList. But! -
+ // Each entry in the tree may represent a chain of multiple chunks of the
+ // same size, and we only want to remove one on them. So, if this entry
+ // does have a chain, just remove the first-but-one item from the chain.
+ if (FreeListEntry* next = entry->nextEntry) {
+ // We're going to leave 'entry' in the tree; remove 'next' from its chain.
+ entry->nextEntry = next->nextEntry;
+ next->nextEntry = 0;
+ entry = next;
+ } else
+ m_freeList.remove(entry->size);
+
+ // Whoo!, we have a result!
+ ASSERT(entry->size >= size);
+ result = entry->pointer;
+
+ // If the allocation exactly fits the chunk we found in the,
+ // m_freeList then the FreeListEntry node is no longer needed.
+ if (entry->size == size)
+ delete entry;
+ else {
+ // There is memory left over, and it is not of the common size.
+ // We can reuse the existing FreeListEntry node to add this back
+ // into m_freeList.
+ entry->pointer = (void*)((intptr_t)entry->pointer + size);
+ entry->size -= size;
+ addToFreeList(entry);
+ }
+ }
+
+ // Call reuse to report to the operating system that this memory is in use.
+ ASSERT(isWithinVMPool(result, size));
+ reuse(result, size);
+ return result;
+ }
+
+ void free(void* pointer, size_t size)
+ {
+ // Call release to report to the operating system that this
+ // memory is no longer in use, and need not be paged out.
+ ASSERT(isWithinVMPool(pointer, size));
+ release(pointer, size);
+
+ // Common-sized allocations are stored in the m_commonSizedAllocations
+ // vector; all other freed chunks are added to m_freeList.
+ if (size == m_commonSize)
+ m_commonSizedAllocations.append(pointer);
+ else
+ addToFreeList(new FreeListEntry(pointer, size));
+
+ // Do some housekeeping. Every time we reach a point that
+ // 16MB of allocations have been freed, sweep m_freeList
+ // coalescing any neighboring fragments.
+ m_countFreedSinceLastCoalesce += size;
+ if (m_countFreedSinceLastCoalesce >= SIXTEEN_MB) {
+ m_countFreedSinceLastCoalesce = 0;
+ coalesceFreeSpace();
+ }
+ }
+
+private:
+
+#ifndef NDEBUG
+ bool isWithinVMPool(void* pointer, size_t size)
+ {
+ return pointer >= m_base && (reinterpret_cast<char*>(pointer) + size <= reinterpret_cast<char*>(m_base) + m_totalHeapSize);
+ }
+#endif
+
+ // Freed space from the most common sized allocations will be held in this list, ...
+ const size_t m_commonSize;
+ Vector<void*> m_commonSizedAllocations;
+
+ // ... and all other freed allocations are held in m_freeList.
+ SizeSortedFreeTree m_freeList;
+
+ // This is used for housekeeping, to trigger defragmentation of the freed lists.
+ size_t m_countFreedSinceLastCoalesce;
+
+ void* m_base;
+ size_t m_totalHeapSize;
+};
+
+void ExecutableAllocator::intializePageSize()
+{
+ ExecutableAllocator::pageSize = getpagesize();
+}
+
+static FixedVMPoolAllocator* allocator = 0;
+static SpinLock spinlock = SPINLOCK_INITIALIZER;
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
+{
+ SpinLockHolder lock_holder(&spinlock);
+
+ if (!allocator)
+ allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, TWO_GB);
+ ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocator->alloc(size)), size};
+ return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& allocation)
+{
+ SpinLockHolder lock_holder(&spinlock);
+
+ ASSERT(allocator);
+ allocator->free(allocation.pages, allocation.size);
+}
+
+}
+
+#endif // HAVE(ASSEMBLER)
#include <sys/mman.h>
#include <unistd.h>
+#include <wtf/VMTags.h>
namespace JSC {
+#if !(PLATFORM(MAC) && PLATFORM(X86_64))
+
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};
+ ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(mmap(NULL, n, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0)), n };
return alloc;
}
-void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
{
int result = munmap(alloc.pages, alloc.size);
ASSERT_UNUSED(result, !result);
}
+#endif // !(PLATFORM(MAC) && PLATFORM(X86_64))
+
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
+{
+ if (!pageSize)
+ intializePageSize();
+
+ // Calculate the start of the page containing this region,
+ // and account for this extra memory within size.
+ intptr_t startPtr = reinterpret_cast<intptr_t>(start);
+ intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
+ void* pageStart = reinterpret_cast<void*>(pageStartPtr);
+ size += (startPtr - pageStartPtr);
+
+ // Round size up
+ size += (pageSize - 1);
+ size &= ~(pageSize - 1);
+
+ mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
+}
+#endif
+
}
#endif // HAVE(ASSEMBLER)
VirtualFree(alloc.pages, 0, MEM_RELEASE);
}
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
+#endif
+
}
#endif // HAVE(ASSEMBLER)
#include "config.h"
#include "JIT.h"
+// This probably does not belong here; adding here for now as a quick Windows build fix.
+#if ENABLE(ASSEMBLER) && PLATFORM(X86) && !PLATFORM(MAC)
+#include "MacroAssembler.h"
+JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
+#endif
+
#if ENABLE(JIT)
#include "CodeBlock.h"
+#include "Interpreter.h"
#include "JITInlineMethods.h"
+#include "JITStubs.h"
+#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
-#include "Interpreter.h"
+#include "LinkBuffer.h"
+#include "RepatchBuffer.h"
#include "ResultType.h"
#include "SamplingTool.h"
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;
- }
- }
-
+void ctiPatchNearCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction)
+{
+ RepatchBuffer repatchBuffer(codeblock);
+ repatchBuffer.relinkNearCallerToTrampoline(returnAddress, newCalleeFunction);
}
-#endif
-
-void ctiSetReturnAddress(void** where, void* what)
+void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction)
{
- *where = what;
+ RepatchBuffer repatchBuffer(codeblock);
+ repatchBuffer.relinkCallerToTrampoline(returnAddress, newCalleeFunction);
}
-void ctiPatchCallByReturnAddress(void* where, void* what)
+void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction)
{
- MacroAssembler::Jump::patch(where, what);
+ RepatchBuffer repatchBuffer(codeblock);
+ repatchBuffer.relinkCallerToFunction(returnAddress, newCalleeFunction);
}
JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
, m_labels(codeBlock ? codeBlock->instructions().size() : 0)
, m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
, m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
+ , m_bytecodeIndex((unsigned)-1)
+#if USE(JSVALUE32_64)
+ , m_jumpTargetIndex(0)
+ , m_mappedBytecodeIndex((unsigned)-1)
+ , m_mappedVirtualRegisterIndex((unsigned)-1)
+ , m_mappedTag((RegisterID)-1)
+ , m_mappedPayload((RegisterID)-1)
+#else
, m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
, m_jumpTargetsPosition(0)
+#endif
{
}
-void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
+#if USE(JSVALUE32_64)
+void JIT::emitTimeoutCheck()
{
- 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);
+ Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
+ JITStubCall stubCall(this, cti_timeout_check);
+ stubCall.addArgument(regT1, regT0); // save last result registers.
+ stubCall.call(timeoutCheckRegister);
+ stubCall.getArgument(0, regT1, regT0); // reload last result registers.
+ skipTimeout.link(this);
}
-
-void JIT::emitSlowScriptCheck()
+#else
+void JIT::emitTimeoutCheck()
{
- Jump skipTimeout = jnzSub32(Imm32(1), timeoutCheckRegister);
- emitCTICall(Interpreter::cti_timeout_check);
- move(X86::eax, timeoutCheckRegister);
+ Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
+ JITStubCall(this, cti_timeout_check).call(timeoutCheckRegister);
skipTimeout.link(this);
killLastResultRegister();
}
-
+#endif
#define NEXT_OPCODE(name) \
m_bytecodeIndex += OPCODE_LENGTH(name); \
break;
-#define CTI_COMPILE_BINARY_OP(name) \
+#if USE(JSVALUE32_64)
+#define DEFINE_BINARY_OP(name) \
+ case name: { \
+ JITStubCall stubCall(this, cti_##name); \
+ stubCall.addArgument(currentInstruction[2].u.operand); \
+ stubCall.addArgument(currentInstruction[3].u.operand); \
+ stubCall.call(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+
+#define DEFINE_UNARY_OP(name) \
+ case name: { \
+ JITStubCall stubCall(this, cti_##name); \
+ stubCall.addArgument(currentInstruction[2].u.operand); \
+ stubCall.call(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+
+#else // USE(JSVALUE32_64)
+
+#define DEFINE_BINARY_OP(name) \
+ case name: { \
+ JITStubCall stubCall(this, cti_##name); \
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2); \
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2); \
+ stubCall.call(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+
+#define DEFINE_UNARY_OP(name) \
+ case name: { \
+ JITStubCall stubCall(this, cti_##name); \
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2); \
+ stubCall.call(currentInstruction[1].u.operand); \
+ NEXT_OPCODE(name); \
+ }
+#endif // USE(JSVALUE32_64)
+
+#define DEFINE_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); \
+ emit_##name(currentInstruction); \
NEXT_OPCODE(name); \
}
-#define CTI_COMPILE_UNARY_OP(name) \
+#define DEFINE_SLOWCASE_OP(name) \
case name: { \
- emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \
- emitCTICall(Interpreter::cti_##name); \
- emitPutVirtualRegister(currentInstruction[1].u.operand); \
+ emitSlow_##name(currentInstruction, iter); \
NEXT_OPCODE(name); \
}
{
Instruction* instructionsBegin = m_codeBlock->instructions().begin();
unsigned instructionCount = m_codeBlock->instructions().size();
- unsigned propertyAccessInstructionIndex = 0;
- unsigned globalResolveInfoIndex = 0;
- unsigned callLinkInfoIndex = 0;
+
+ m_propertyAccessInstructionIndex = 0;
+ m_globalResolveInfoIndex = 0;
+ m_callLinkInfoIndex = 0;
for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) {
Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
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)));
+#if !USE(JSVALUE32_64)
+ if (m_labels[m_bytecodeIndex].isUsed())
+ killLastResultRegister();
#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)));
+ m_labels[m_bytecodeIndex] = label();
- 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);
+ switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
+ DEFINE_BINARY_OP(op_del_by_val)
+#if !USE(JSVALUE32_64)
+ DEFINE_BINARY_OP(op_div)
#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);
+ DEFINE_BINARY_OP(op_in)
+ DEFINE_BINARY_OP(op_less)
+ DEFINE_BINARY_OP(op_lesseq)
+ DEFINE_BINARY_OP(op_urshift)
+ DEFINE_UNARY_OP(op_get_pnames)
+ DEFINE_UNARY_OP(op_is_boolean)
+ DEFINE_UNARY_OP(op_is_function)
+ DEFINE_UNARY_OP(op_is_number)
+ DEFINE_UNARY_OP(op_is_object)
+ DEFINE_UNARY_OP(op_is_string)
+ DEFINE_UNARY_OP(op_is_undefined)
+#if !USE(JSVALUE32_64)
+ DEFINE_UNARY_OP(op_negate)
#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)));
+ DEFINE_UNARY_OP(op_typeof)
+
+ DEFINE_OP(op_add)
+ DEFINE_OP(op_bitand)
+ DEFINE_OP(op_bitnot)
+ DEFINE_OP(op_bitor)
+ DEFINE_OP(op_bitxor)
+ DEFINE_OP(op_call)
+ DEFINE_OP(op_call_eval)
+ DEFINE_OP(op_call_varargs)
+ DEFINE_OP(op_catch)
+ DEFINE_OP(op_construct)
+ DEFINE_OP(op_construct_verify)
+ DEFINE_OP(op_convert_this)
+ DEFINE_OP(op_init_arguments)
+ DEFINE_OP(op_create_arguments)
+ DEFINE_OP(op_debug)
+ DEFINE_OP(op_del_by_id)
+#if USE(JSVALUE32_64)
+ DEFINE_OP(op_div)
#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);
+ DEFINE_OP(op_end)
+ DEFINE_OP(op_enter)
+ DEFINE_OP(op_enter_with_activation)
+ DEFINE_OP(op_eq)
+ DEFINE_OP(op_eq_null)
+ DEFINE_OP(op_get_by_id)
+ DEFINE_OP(op_get_by_val)
+ DEFINE_OP(op_get_global_var)
+ DEFINE_OP(op_get_scoped_var)
+ DEFINE_OP(op_instanceof)
+ DEFINE_OP(op_jeq_null)
+ DEFINE_OP(op_jfalse)
+ DEFINE_OP(op_jmp)
+ DEFINE_OP(op_jmp_scopes)
+ DEFINE_OP(op_jneq_null)
+ DEFINE_OP(op_jneq_ptr)
+ DEFINE_OP(op_jnless)
+ DEFINE_OP(op_jnlesseq)
+ DEFINE_OP(op_jsr)
+ DEFINE_OP(op_jtrue)
+ DEFINE_OP(op_load_varargs)
+ DEFINE_OP(op_loop)
+ DEFINE_OP(op_loop_if_less)
+ DEFINE_OP(op_loop_if_lesseq)
+ DEFINE_OP(op_loop_if_true)
+ DEFINE_OP(op_lshift)
+ DEFINE_OP(op_method_check)
+ DEFINE_OP(op_mod)
+ DEFINE_OP(op_mov)
+ DEFINE_OP(op_mul)
+#if USE(JSVALUE32_64)
+ DEFINE_OP(op_negate)
#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)))));
+ DEFINE_OP(op_neq)
+ DEFINE_OP(op_neq_null)
+ DEFINE_OP(op_new_array)
+ DEFINE_OP(op_new_error)
+ DEFINE_OP(op_new_func)
+ DEFINE_OP(op_new_func_exp)
+ DEFINE_OP(op_new_object)
+ DEFINE_OP(op_new_regexp)
+ DEFINE_OP(op_next_pname)
+ DEFINE_OP(op_not)
+ DEFINE_OP(op_nstricteq)
+ DEFINE_OP(op_pop_scope)
+ DEFINE_OP(op_post_dec)
+ DEFINE_OP(op_post_inc)
+ DEFINE_OP(op_pre_dec)
+ DEFINE_OP(op_pre_inc)
+ DEFINE_OP(op_profile_did_call)
+ DEFINE_OP(op_profile_will_call)
+ DEFINE_OP(op_push_new_scope)
+ DEFINE_OP(op_push_scope)
+ DEFINE_OP(op_put_by_id)
+ DEFINE_OP(op_put_by_index)
+ DEFINE_OP(op_put_by_val)
+ DEFINE_OP(op_put_getter)
+ DEFINE_OP(op_put_global_var)
+ DEFINE_OP(op_put_scoped_var)
+ DEFINE_OP(op_put_setter)
+ DEFINE_OP(op_resolve)
+ DEFINE_OP(op_resolve_base)
+ DEFINE_OP(op_resolve_global)
+ DEFINE_OP(op_resolve_skip)
+ DEFINE_OP(op_resolve_with_base)
+ DEFINE_OP(op_ret)
+ DEFINE_OP(op_rshift)
+ DEFINE_OP(op_sret)
+ DEFINE_OP(op_strcat)
+ DEFINE_OP(op_stricteq)
+ DEFINE_OP(op_sub)
+ DEFINE_OP(op_switch_char)
+ DEFINE_OP(op_switch_imm)
+ DEFINE_OP(op_switch_string)
+ DEFINE_OP(op_tear_off_activation)
+ DEFINE_OP(op_tear_off_arguments)
+ DEFINE_OP(op_throw)
+ DEFINE_OP(op_to_jsnumber)
+ DEFINE_OP(op_to_primitive)
- 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:
}
}
- ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
- ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
+ ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
+ ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
#ifndef NDEBUG
- // reset this, in order to guard it's use with asserts
+ // Reset this, in order to guard its use with ASSERTs.
m_bytecodeIndex = (unsigned)-1;
#endif
}
void JIT::privateCompileSlowCases()
{
Instruction* instructionsBegin = m_codeBlock->instructions().begin();
- unsigned propertyAccessInstructionIndex = 0;
- unsigned callLinkInfoIndex = 0;
+
+ m_propertyAccessInstructionIndex = 0;
+#if USE(JSVALUE32_64)
+ m_globalResolveInfoIndex = 0;
+#endif
+ m_callLinkInfoIndex = 0;
for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
- // FIXME: enable peephole optimizations for slow cases when applicable
+#if !USE(JSVALUE32_64)
killLastResultRegister();
+#endif
m_bytecodeIndex = iter->to;
#ifndef NDEBUG
#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);
+ switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
+ DEFINE_SLOWCASE_OP(op_add)
+ DEFINE_SLOWCASE_OP(op_bitand)
+ DEFINE_SLOWCASE_OP(op_bitnot)
+ DEFINE_SLOWCASE_OP(op_bitor)
+ DEFINE_SLOWCASE_OP(op_bitxor)
+ DEFINE_SLOWCASE_OP(op_call)
+ DEFINE_SLOWCASE_OP(op_call_eval)
+ DEFINE_SLOWCASE_OP(op_call_varargs)
+ DEFINE_SLOWCASE_OP(op_construct)
+ DEFINE_SLOWCASE_OP(op_construct_verify)
+ DEFINE_SLOWCASE_OP(op_convert_this)
+#if USE(JSVALUE32_64)
+ DEFINE_SLOWCASE_OP(op_div)
#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);
+ DEFINE_SLOWCASE_OP(op_eq)
+ DEFINE_SLOWCASE_OP(op_get_by_id)
+ DEFINE_SLOWCASE_OP(op_get_by_val)
+ DEFINE_SLOWCASE_OP(op_instanceof)
+ DEFINE_SLOWCASE_OP(op_jfalse)
+ DEFINE_SLOWCASE_OP(op_jnless)
+ DEFINE_SLOWCASE_OP(op_jnlesseq)
+ DEFINE_SLOWCASE_OP(op_jtrue)
+ DEFINE_SLOWCASE_OP(op_loop_if_less)
+ DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
+ DEFINE_SLOWCASE_OP(op_loop_if_true)
+ DEFINE_SLOWCASE_OP(op_lshift)
+ DEFINE_SLOWCASE_OP(op_method_check)
+ DEFINE_SLOWCASE_OP(op_mod)
+ DEFINE_SLOWCASE_OP(op_mul)
+#if USE(JSVALUE32_64)
+ DEFINE_SLOWCASE_OP(op_negate)
#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);
- }
-
+ DEFINE_SLOWCASE_OP(op_neq)
+ DEFINE_SLOWCASE_OP(op_not)
+ DEFINE_SLOWCASE_OP(op_nstricteq)
+ DEFINE_SLOWCASE_OP(op_post_dec)
+ DEFINE_SLOWCASE_OP(op_post_inc)
+ DEFINE_SLOWCASE_OP(op_pre_dec)
+ DEFINE_SLOWCASE_OP(op_pre_inc)
+ DEFINE_SLOWCASE_OP(op_put_by_id)
+ DEFINE_SLOWCASE_OP(op_put_by_val)
+#if USE(JSVALUE32_64)
+ DEFINE_SLOWCASE_OP(op_resolve_global)
+#endif
+ DEFINE_SLOWCASE_OP(op_rshift)
+ DEFINE_SLOWCASE_OP(op_stricteq)
+ DEFINE_SLOWCASE_OP(op_sub)
+ DEFINE_SLOWCASE_OP(op_to_jsnumber)
+ DEFINE_SLOWCASE_OP(op_to_primitive)
default:
ASSERT_NOT_REACHED();
}
}
#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
- ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
+ ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
#endif
- ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
+ ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
#ifndef NDEBUG
- // reset this, in order to guard it's use with asserts
+ // Reset this, in order to guard its use with ASSERTs.
m_bytecodeIndex = (unsigned)-1;
#endif
}
#endif
// Could use a pop_m, but would need to offset the following instruction if so.
- pop(X86::ecx);
- emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
+ preserveReturnAddressAfterCall(regT2);
+ emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
Jump slowRegisterFileCheck;
Label afterRegisterFileCheck;
// 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)));
+ peek(regT0, OBJECT_OFFSETOF(JITStackFrame, registerFile) / sizeof (void*));
+ addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1);
+
+ slowRegisterFileCheck = branchPtr(Above, regT1, Address(regT0, OBJECT_OFFSETOF(RegisterFile, m_end)));
afterRegisterFileCheck = label();
}
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);
+ m_bytecodeIndex = 0;
+ JITStubCall(this, cti_register_file_check).call();
#ifndef NDEBUG
- // reset this, in order to guard it's use with asserts
- m_bytecodeIndex = (unsigned)-1;
+ m_bytecodeIndex = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
#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);
+ LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
// Translate vPC offsets into addresses in JIT generated code, for switch tables.
for (unsigned i = 0; i < m_switches.size(); ++i) {
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]);
+ record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(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;
+ record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(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]);
+ record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(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;
+ it->second.ctiOffset = offset ? patchBuffer.locationOf(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]);
+ handler.nativeCode = patchBuffer.locationOf(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);
+ patchBuffer.link(iter->from, FunctionPtr(iter->to));
}
if (m_codeBlock->hasExceptionInfo()) {
- m_codeBlock->pcVector().reserveCapacity(m_calls.size());
+ m_codeBlock->callReturnIndexVector().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));
+ m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeIndex(patchBuffer.returnAddressOffset(iter->from), 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));
+ patchBuffer.patch(iter->storeLocation, patchBuffer.locationOf(iter->target).executableAddress());
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
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
+ info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation);
+ info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin);
}
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
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;
+ info.ownerCodeBlock = m_codeBlock;
+ info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
+ info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
+ info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
+ }
#endif
+ unsigned methodCallCount = m_methodCallCompilationInfo.size();
+ m_codeBlock->addMethodCallLinkInfos(methodCallCount);
+ for (unsigned i = 0; i < methodCallCount; ++i) {
+ MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
+ info.structureLabel = patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare);
+ info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
}
- m_codeBlock->setJITCode(codeRef);
+ m_codeBlock->setJITCode(patchBuffer.finalizeCode());
}
-void JIT::privateCompileCTIMachineTrampolines()
+#if !USE(JSVALUE32_64)
+void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
{
-#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));
+ loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), dst);
+ loadPtr(Address(dst, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), dst);
+ loadPtr(Address(dst, index * sizeof(Register)), dst);
+}
- // 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();
+void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
+{
+ loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), variableObject);
+ loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), variableObject);
+ storePtr(src, Address(variableObject, index * sizeof(Register)));
+}
#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);
+#if ENABLE(JIT_OPTIMIZE_CALL)
+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.
+ RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock);
+#if USE(JSVALUE32_64)
+ repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0);
+#else
+ repatchBuffer.repatch(callLinkInfo->hotPathBegin, JSValue::encode(JSValue()));
#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)
+void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
{
- loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), dst);
- loadPtr(Address(dst, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), dst);
- loadPtr(Address(dst, index * sizeof(Register)), dst);
-}
+ ASSERT(calleeCodeBlock);
+ RepatchBuffer repatchBuffer(callerCodeBlock);
-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)));
+ // Currently we only link calls with the exact number of arguments.
+ // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
+ if (callerArgCount == calleeCodeBlock->m_numParameters || calleeCodeBlock->codeType() == NativeCode) {
+ ASSERT(!callLinkInfo->isLinked());
+
+ if (calleeCodeBlock)
+ calleeCodeBlock->addCaller(callLinkInfo);
+
+ repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee);
+ repatchBuffer.relink(callLinkInfo->hotPathOther, code.addressForCall());
+ }
+
+ // patch the call so we do not continue to try to link.
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs.ctiVirtualCall());
}
+#endif // ENABLE(JIT_OPTIMIZE_CALL)
} // namespace JSC
#define JIT_h
#include <wtf/Platform.h>
-#include <bytecode/SamplingTool.h>
#if ENABLE(JIT)
-#define WTF_USE_CTI_REPATCH_PIC 1
+// We've run into some problems where changing the size of the class JIT leads to
+// performance fluctuations. Try forcing alignment in an attempt to stabalize this.
+#if COMPILER(GCC)
+#define JIT_CLASS_ALIGNMENT __attribute__ ((aligned (32)))
+#else
+#define JIT_CLASS_ALIGNMENT
+#endif
+#include "CodeBlock.h"
#include "Interpreter.h"
+#include "JITCode.h"
+#include "JITStubs.h"
#include "Opcode.h"
#include "RegisterFile.h"
#include "MacroAssembler.h"
#include "Profiler.h"
+#include <bytecode/SamplingTool.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 JIT;
class JSPropertyNameIterator;
class Interpreter;
class Register;
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;
+ MacroAssembler::Call from;
unsigned bytecodeIndex;
void* to;
{
}
- CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0)
+ CallRecord(MacroAssembler::Call from, unsigned bytecodeIndex, void* to = 0)
: from(from)
, bytecodeIndex(bytecodeIndex)
, to(to)
};
struct PropertyStubCompilationInfo {
- MacroAssembler::Jump callReturnLocation;
+ MacroAssembler::Call callReturnLocation;
MacroAssembler::Label hotPathBegin;
};
struct StructureStubCompilationInfo {
MacroAssembler::DataLabelPtr hotPathBegin;
- MacroAssembler::Jump hotPathOther;
- MacroAssembler::Jump callReturnLocation;
- MacroAssembler::Label coldPathOther;
+ MacroAssembler::Call hotPathOther;
+ MacroAssembler::Call callReturnLocation;
};
- 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();
+ struct MethodCallCompilationInfo {
+ MethodCallCompilationInfo(unsigned propertyAccessIndex)
+ : propertyAccessIndex(propertyAccessIndex)
+ {
+ }
+
+ MacroAssembler::DataLabelPtr structureToCompare;
+ unsigned propertyAccessIndex;
};
- void ctiSetReturnAddress(void** where, void* what);
- void ctiPatchCallByReturnAddress(void* where, void* what);
+ // Near calls can only be patched to other JIT code, regular calls can be patched to JIT code or relinked to stub functions.
+ void ctiPatchNearCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction);
+ void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction);
+ void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction);
class JIT : private MacroAssembler {
+ friend class JITStubCall;
+
using MacroAssembler::Jump;
using MacroAssembler::JumpList;
using MacroAssembler::Label;
+ // NOTES:
+ //
+ // regT0 has two special meanings. The return value from a stub
+ // call will always be in regT0, and by default (unless
+ // a register is specified) emitPutVirtualRegister() will store
+ // the value from regT0.
+ //
+ // regT3 is required to be callee-preserved.
+ //
+ // tempRegister2 is has no such dependencies. It is important that
+ // on x86/x86-64 it is ecx for performance reasons, since the
+ // MacroAssembler will need to plant register swaps if it is not -
+ // however the code will still function correctly.
#if PLATFORM(X86_64)
+ static const RegisterID returnValueRegister = X86::eax;
+ static const RegisterID cachedResultRegister = X86::eax;
+ static const RegisterID firstArgumentRegister = X86::edi;
+
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 regT0 = X86::eax;
+ static const RegisterID regT1 = X86::edx;
+ static const RegisterID regT2 = X86::ecx;
+ static const RegisterID regT3 = X86::ebx;
+
+ static const FPRegisterID fpRegT0 = X86::xmm0;
+ static const FPRegisterID fpRegT1 = X86::xmm1;
+ static const FPRegisterID fpRegT2 = X86::xmm2;
+#elif PLATFORM(X86)
+ static const RegisterID returnValueRegister = X86::eax;
+ static const RegisterID cachedResultRegister = X86::eax;
+ // On x86 we always use fastcall conventions = but on
+ // OS X if might make more sense to just use regparm.
+ static const RegisterID firstArgumentRegister = X86::ecx;
+
static const RegisterID timeoutCheckRegister = X86::esi;
static const RegisterID callFrameRegister = X86::edi;
+
+ static const RegisterID regT0 = X86::eax;
+ static const RegisterID regT1 = X86::edx;
+ static const RegisterID regT2 = X86::ecx;
+ static const RegisterID regT3 = X86::ebx;
+
+ static const FPRegisterID fpRegT0 = X86::xmm0;
+ static const FPRegisterID fpRegT1 = X86::xmm1;
+ static const FPRegisterID fpRegT2 = X86::xmm2;
+#elif PLATFORM_ARM_ARCH(7)
+ static const RegisterID returnValueRegister = ARM::r0;
+ static const RegisterID cachedResultRegister = ARM::r0;
+ static const RegisterID firstArgumentRegister = ARM::r0;
+
+ static const RegisterID regT0 = ARM::r0;
+ static const RegisterID regT1 = ARM::r1;
+ static const RegisterID regT2 = ARM::r2;
+ static const RegisterID regT3 = ARM::r4;
+
+ static const RegisterID callFrameRegister = ARM::r5;
+ static const RegisterID timeoutCheckRegister = ARM::r6;
+
+ static const FPRegisterID fpRegT0 = ARM::d0;
+ static const FPRegisterID fpRegT1 = ARM::d1;
+ static const FPRegisterID fpRegT2 = ARM::d2;
+#else
+ #error "JIT not supported on this platform."
#endif
static const int patchGetByIdDefaultStructure = -1;
// 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.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)
+ static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr 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 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)
+ static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr 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)
+ static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
{
JIT jit(globalData, codeBlock);
jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
}
- static void compileCTIMachineTrampolines(JSGlobalData* globalData)
+ static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
{
JIT jit(globalData);
- jit.privateCompileCTIMachineTrampolines();
+ jit.privateCompileCTIMachineTrampolines(executablePool, globalData, ctiStringLengthTrampoline, ctiVirtualCallPreLink, ctiVirtualCallLink, ctiVirtualCall, ctiNativeCallThunk);
}
- static void patchGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
- static void patchPutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
+ static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
+ static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
+ static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*);
- static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress)
+ static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
{
JIT jit(globalData, codeBlock);
return jit.privateCompilePatchGetArrayLength(returnAddress);
}
- static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount);
+ static void linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode&, CallLinkInfo*, int callerArgCount, JSGlobalData*);
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:
+ struct JSRInfo {
+ DataLabelPtr storeLocation;
+ Label target;
+
+ JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
+ : storeLocation(storeLocation)
+ , target(targetLocation)
+ {
+ }
+ };
+
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 privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
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 privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
+ void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
- void privateCompileCTIMachineTrampolines();
- void privateCompilePatchGetArrayLength(void* returnAddress);
+ void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk);
+ void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
void addSlowCase(Jump);
+ void addSlowCase(JumpList);
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 compileOpCallVarargs(Instruction* instruction);
void compileOpCallInitializeCallFrame();
void compileOpCallSetupArgs(Instruction*);
- void compileOpCallEvalSetupArgs(Instruction*);
+ void compileOpCallVarargsSetupArgs(Instruction*);
void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
+ void compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter);
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);
+#if USE(JSVALUE32_64)
+ Address tagFor(unsigned index, RegisterID base = callFrameRegister);
+ Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
+ Address addressFor(unsigned index, RegisterID base = callFrameRegister);
+
+ bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
+ bool isOperandConstantImmediateDouble(unsigned src);
+
+ void emitLoadTag(unsigned index, RegisterID tag);
+ void emitLoadPayload(unsigned index, RegisterID payload);
+
+ void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
+ void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
+ void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
+ void emitLoadDouble(unsigned index, FPRegisterID value);
+ void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
+
+ void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
+ void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister);
+ void emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32 = false);
+ void emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32 = false);
+ void emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell = false);
+ void emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool = false);
+ void emitStoreDouble(unsigned index, FPRegisterID value);
+
+ bool isLabeled(unsigned bytecodeIndex);
+ void map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload);
+ void unmap(RegisterID);
+ void unmap();
+ bool isMapped(unsigned virtualRegisterIndex);
+ bool getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload);
+ bool getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag);
+
+ void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex);
+ void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag);
+ void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, unsigned virtualRegisterIndex);
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ void compileGetByIdHotPath();
+ void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
+#endif
+ void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
+ void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
+ void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
- 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);
+ // Arithmetic opcode helpers
+ void emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
+ void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
+ void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
- void emitInitRegister(unsigned dst);
+#if PLATFORM(X86)
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 7;
+ static const int patchOffsetPutByIdExternalLoad = 13;
+ static const int patchLengthPutByIdExternalLoad = 3;
+ static const int patchOffsetPutByIdPropertyMapOffset1 = 22;
+ static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
+ // 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 patchOffsetGetByIdExternalLoad = 13;
+ static const int patchLengthGetByIdExternalLoad = 3;
+ static const int patchOffsetGetByIdPropertyMapOffset1 = 22;
+ static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
+ static const int patchOffsetGetByIdPutResult = 28;
+#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
+ static const int patchOffsetGetByIdSlowCaseCall = 35;
+#elif ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 37;
+#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
+ static const int patchOffsetGetByIdSlowCaseCall = 25;
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 27;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 6;
- void emitPutCTIParam(void* value, unsigned name);
- void emitPutCTIParam(RegisterID from, unsigned name);
- void emitGetCTIParam(unsigned name, RegisterID to);
+ static const int patchOffsetMethodCheckProtoObj = 11;
+ static const int patchOffsetMethodCheckProtoStruct = 18;
+ static const int patchOffsetMethodCheckPutFunction = 29;
+#else
+#error "JSVALUE32_64 not supported on this platform."
+#endif
- void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
- void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
- void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to);
+#else // USE(JSVALUE32_64)
+ void emitGetVirtualRegister(int src, RegisterID dst);
+ void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
+ void emitPutVirtualRegister(unsigned dst, RegisterID from = regT0);
- JSValuePtr getConstantOperand(unsigned src);
int32_t getConstantOperandImmediateInt(unsigned src);
- bool isOperandConstantImmediateInt(unsigned src);
+
+ void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
+ void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
+
+ void killLastResultRegister();
Jump emitJumpIfJSCell(RegisterID);
Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID);
Jump emitJumpIfNotJSCell(RegisterID);
void emitJumpSlowCaseIfNotJSCell(RegisterID);
void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
JIT::Jump emitJumpIfImmediateNumber(RegisterID);
JIT::Jump emitJumpIfNotImmediateNumber(RegisterID);
-#endif
-
- Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
+#else
+ JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
{
- return iter++->from;
+ return emitJumpIfImmediateInteger(reg);
}
- void linkSlowCase(Vector<SlowCaseEntry>::iterator& iter)
+
+ JIT::Jump emitJumpIfNotImmediateNumber(RegisterID reg)
{
- iter->from.link(this);
- ++iter;
+ return emitJumpIfNotImmediateInteger(reg);
}
- void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
-
+#endif
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)
+#if !USE(JSVALUE64)
void emitFastArithDeTagImmediate(RegisterID);
Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
#endif
void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
void emitTagAsBoolImmediate(RegisterID reg);
+ 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);
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
+ void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
+#endif
+ void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
+ void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
+ void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
+
+#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 patchOffsetPutByIdExternalLoad = 20;
+ static const int patchLengthPutByIdExternalLoad = 4;
+ 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 patchOffsetGetByIdExternalLoad = 20;
+ static const int patchLengthGetByIdExternalLoad = 4;
+ static const int patchOffsetGetByIdPropertyMapOffset = 31;
+ static const int patchOffsetGetByIdPutResult = 31;
+#if ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 66;
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 44;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 9;
+
+ static const int patchOffsetMethodCheckProtoObj = 20;
+ static const int patchOffsetMethodCheckProtoStruct = 30;
+ static const int patchOffsetMethodCheckPutFunction = 50;
+#elif PLATFORM(X86)
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 7;
+ static const int patchOffsetPutByIdExternalLoad = 13;
+ static const int patchLengthPutByIdExternalLoad = 3;
+ 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 patchOffsetGetByIdExternalLoad = 13;
+ static const int patchLengthGetByIdExternalLoad = 3;
+ static const int patchOffsetGetByIdPropertyMapOffset = 22;
+ static const int patchOffsetGetByIdPutResult = 22;
+#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
+ static const int patchOffsetGetByIdSlowCaseCall = 31;
+#elif ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 33;
+#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
+ static const int patchOffsetGetByIdSlowCaseCall = 21;
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 23;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 6;
+
+ static const int patchOffsetMethodCheckProtoObj = 11;
+ static const int patchOffsetMethodCheckProtoStruct = 18;
+ static const int patchOffsetMethodCheckPutFunction = 29;
+#elif PLATFORM_ARM_ARCH(7)
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 10;
+ static const int patchOffsetPutByIdExternalLoad = 20;
+ static const int patchLengthPutByIdExternalLoad = 12;
+ static const int patchOffsetPutByIdPropertyMapOffset = 40;
+ // 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 patchOffsetGetByIdExternalLoad = 20;
+ static const int patchLengthGetByIdExternalLoad = 12;
+ static const int patchOffsetGetByIdPropertyMapOffset = 40;
+ static const int patchOffsetGetByIdPutResult = 44;
+#if ENABLE(OPCODE_SAMPLING)
+ static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 28;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 10;
+
+ static const int patchOffsetMethodCheckProtoObj = 18;
+ static const int patchOffsetMethodCheckProtoStruct = 28;
+ static const int patchOffsetMethodCheckPutFunction = 46;
+#endif
+#endif // USE(JSVALUE32_64)
+
+ void emit_op_add(Instruction*);
+ void emit_op_bitand(Instruction*);
+ void emit_op_bitnot(Instruction*);
+ void emit_op_bitor(Instruction*);
+ void emit_op_bitxor(Instruction*);
+ void emit_op_call(Instruction*);
+ void emit_op_call_eval(Instruction*);
+ void emit_op_call_varargs(Instruction*);
+ void emit_op_catch(Instruction*);
+ void emit_op_construct(Instruction*);
+ void emit_op_construct_verify(Instruction*);
+ void emit_op_convert_this(Instruction*);
+ void emit_op_create_arguments(Instruction*);
+ void emit_op_debug(Instruction*);
+ void emit_op_del_by_id(Instruction*);
+ void emit_op_div(Instruction*);
+ void emit_op_end(Instruction*);
+ void emit_op_enter(Instruction*);
+ void emit_op_enter_with_activation(Instruction*);
+ void emit_op_eq(Instruction*);
+ void emit_op_eq_null(Instruction*);
+ void emit_op_get_by_id(Instruction*);
+ void emit_op_get_by_val(Instruction*);
+ void emit_op_get_global_var(Instruction*);
+ void emit_op_get_scoped_var(Instruction*);
+ void emit_op_init_arguments(Instruction*);
+ void emit_op_instanceof(Instruction*);
+ void emit_op_jeq_null(Instruction*);
+ void emit_op_jfalse(Instruction*);
+ void emit_op_jmp(Instruction*);
+ void emit_op_jmp_scopes(Instruction*);
+ void emit_op_jneq_null(Instruction*);
+ void emit_op_jneq_ptr(Instruction*);
+ void emit_op_jnless(Instruction*);
+ void emit_op_jnlesseq(Instruction*);
+ void emit_op_jsr(Instruction*);
+ void emit_op_jtrue(Instruction*);
+ void emit_op_load_varargs(Instruction*);
+ void emit_op_loop(Instruction*);
+ void emit_op_loop_if_less(Instruction*);
+ void emit_op_loop_if_lesseq(Instruction*);
+ void emit_op_loop_if_true(Instruction*);
+ void emit_op_lshift(Instruction*);
+ void emit_op_method_check(Instruction*);
+ void emit_op_mod(Instruction*);
+ void emit_op_mov(Instruction*);
+ void emit_op_mul(Instruction*);
+ void emit_op_negate(Instruction*);
+ void emit_op_neq(Instruction*);
+ void emit_op_neq_null(Instruction*);
+ void emit_op_new_array(Instruction*);
+ void emit_op_new_error(Instruction*);
+ void emit_op_new_func(Instruction*);
+ void emit_op_new_func_exp(Instruction*);
+ void emit_op_new_object(Instruction*);
+ void emit_op_new_regexp(Instruction*);
+ void emit_op_next_pname(Instruction*);
+ void emit_op_not(Instruction*);
+ void emit_op_nstricteq(Instruction*);
+ void emit_op_pop_scope(Instruction*);
+ void emit_op_post_dec(Instruction*);
+ void emit_op_post_inc(Instruction*);
+ void emit_op_pre_dec(Instruction*);
+ void emit_op_pre_inc(Instruction*);
+ void emit_op_profile_did_call(Instruction*);
+ void emit_op_profile_will_call(Instruction*);
+ void emit_op_push_new_scope(Instruction*);
+ void emit_op_push_scope(Instruction*);
+ void emit_op_put_by_id(Instruction*);
+ void emit_op_put_by_index(Instruction*);
+ void emit_op_put_by_val(Instruction*);
+ void emit_op_put_getter(Instruction*);
+ void emit_op_put_global_var(Instruction*);
+ void emit_op_put_scoped_var(Instruction*);
+ void emit_op_put_setter(Instruction*);
+ void emit_op_resolve(Instruction*);
+ void emit_op_resolve_base(Instruction*);
+ void emit_op_resolve_global(Instruction*);
+ void emit_op_resolve_skip(Instruction*);
+ void emit_op_resolve_with_base(Instruction*);
+ void emit_op_ret(Instruction*);
+ void emit_op_rshift(Instruction*);
+ void emit_op_sret(Instruction*);
+ void emit_op_strcat(Instruction*);
+ void emit_op_stricteq(Instruction*);
+ void emit_op_sub(Instruction*);
+ void emit_op_switch_char(Instruction*);
+ void emit_op_switch_imm(Instruction*);
+ void emit_op_switch_string(Instruction*);
+ void emit_op_tear_off_activation(Instruction*);
+ void emit_op_tear_off_arguments(Instruction*);
+ void emit_op_throw(Instruction*);
+ void emit_op_to_jsnumber(Instruction*);
+ void emit_op_to_primitive(Instruction*);
+ void emit_op_unexpected_load(Instruction*);
+
+ void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_bitnot(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_construct_verify(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_post_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_post_inc(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_pre_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_pre_inc(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_resolve_global(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_rshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_stricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
+
+ /* These functions are deprecated: Please use JITStubCall instead. */
+ void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
+#if USE(JSVALUE32_64)
+ void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2);
+#else
+ void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
+#endif
+ void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber);
+ void emitPutJITStubArgConstant(void* value, unsigned argumentNumber);
+ void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst);
+
+ void emitInitRegister(unsigned dst);
+
+ void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
+ void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
+ void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
+ void emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
+
+ JSValue getConstantOperand(unsigned src);
+ bool isOperandConstantImmediateInt(unsigned src);
+
+ 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);
+
+ Jump checkStructure(RegisterID reg, Structure* structure);
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)); }
+ Call emitNakedCall(CodePtr function = CodePtr());
- void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
- void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
-
- void emitSlowScriptCheck();
+ void preserveReturnAddressAfterCall(RegisterID);
+ void restoreReturnAddressBeforeReturn(RegisterID);
+ void restoreReturnAddressBeforeReturn(Address);
+
+ void emitTimeoutCheck();
#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());
+#if ENABLE(SAMPLING_FLAGS)
+ void setSamplingFlag(int32_t);
+ void clearSamplingFlag(int32_t);
#endif
- }
-#else
- void sampleCodeBlock(CodeBlock*) {}
+
+#if ENABLE(SAMPLING_COUNTERS)
+ void emitCount(AbstractSamplingCounter&, uint32_t = 1);
#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());
+ void sampleInstruction(Instruction*, bool = false);
#endif
- }
+
+#if ENABLE(CODEBLOCK_SAMPLING)
+ void sampleCodeBlock(CodeBlock*);
#else
- void sampleInstruction(Instruction*, bool) {}
+ void sampleCodeBlock(CodeBlock*) {}
#endif
Interpreter* m_interpreter;
Vector<Label> m_labels;
Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo;
Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
+ Vector<MethodCallCompilationInfo> m_methodCallCompilationInfo;
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;
+ unsigned m_propertyAccessInstructionIndex;
+ unsigned m_globalResolveInfoIndex;
+ unsigned m_callLinkInfoIndex;
+
+#if USE(JSVALUE32_64)
+ unsigned m_jumpTargetIndex;
+ unsigned m_mappedBytecodeIndex;
+ unsigned m_mappedVirtualRegisterIndex;
+ RegisterID m_mappedTag;
+ RegisterID m_mappedPayload;
+#else
int m_lastResultBytecodeRegister;
unsigned m_jumpTargetsPosition;
- };
-}
+#endif
+ } JIT_CLASS_ALIGNMENT;
+} // namespace JSC
#endif // ENABLE(JIT)
#include "CodeBlock.h"
#include "JITInlineMethods.h"
+#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include <stdio.h>
#endif
-#define __ m_assembler.
+using namespace std;
+
+namespace JSC {
+
+#if USE(JSVALUE32_64)
+
+void JIT::emit_op_negate(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+
+ Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ addSlowCase(branch32(Equal, regT0, Imm32(0)));
+
+ neg32(regT0);
+ emitStoreInt32(dst, regT0, (dst == src));
+
+ Jump end = jump();
+
+ srcNotInt.link(this);
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+
+ xor32(Imm32(1 << 31), regT1);
+ store32(regT1, tagFor(dst));
+ if (dst != src)
+ store32(regT0, payloadFor(dst));
+
+ end.link(this);
+}
+
+void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter); // 0 check
+ linkSlowCase(iter); // double check
+
+ JITStubCall stubCall(this, cti_op_negate);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_jnless(Instruction* currentInstruction)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ // Int32 less.
+ if (isOperandConstantImmediateInt(op1)) {
+ emitLoad(op2, regT3, regT2);
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+ } else {
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThanOrEqual, regT0, regT2), target + 3);
+ }
+
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32Op1);
+ addSlowCase(notInt32Op2);
+ return;
+ }
+ Jump end = jump();
+
+ // Double less.
+ emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
+ end.link(this);
+}
+
+void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ if (!supportsFloatingPoint()) {
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ } else {
+ if (!isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter); // double check
+ linkSlowCase(iter); // int32 check
+ }
+ if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // double check
+ }
+
+ JITStubCall stubCall(this, cti_op_jless);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+}
+
+void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ // Int32 less.
+ if (isOperandConstantImmediateInt(op1)) {
+ emitLoad(op2, regT3, regT2);
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+ } else if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+ } else {
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThan, regT0, regT2), target + 3);
+ }
+
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32Op1);
+ addSlowCase(notInt32Op2);
+ return;
+ }
+ Jump end = jump();
+
+ // Double less.
+ emitBinaryDoubleOp(op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
+ end.link(this);
+}
+
+void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ if (!supportsFloatingPoint()) {
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ } else {
+ if (!isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter); // double check
+ linkSlowCase(iter); // int32 check
+ }
+ if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // double check
+ }
+
+ JITStubCall stubCall(this, cti_op_jlesseq);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+}
+
+// LeftShift (<<)
+
+void JIT::emit_op_lshift(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
+ emitStoreInt32(dst, regT0, dst == op1);
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ if (!isOperandConstantImmediateInt(op1))
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ lshift32(regT2, regT0);
+ emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
+}
+
+void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_lshift);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// RightShift (>>)
+
+void JIT::emit_op_rshift(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
+ emitStoreInt32(dst, regT0, dst == op1);
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ if (!isOperandConstantImmediateInt(op1))
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ rshift32(regT2, regT0);
+ emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
+}
+
+void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_rshift);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// BitAnd (&)
+
+void JIT::emit_op_bitand(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ unsigned op;
+ int32_t constant;
+ if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
+ emitLoad(op, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ and32(Imm32(constant), regT0);
+ emitStoreInt32(dst, regT0, (op == dst));
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ and32(regT2, regT0);
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+}
+
+void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_bitand);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// BitOr (|)
+
+void JIT::emit_op_bitor(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ unsigned op;
+ int32_t constant;
+ if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
+ emitLoad(op, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ or32(Imm32(constant), regT0);
+ emitStoreInt32(dst, regT0, (op == dst));
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ or32(regT2, regT0);
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+}
+
+void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_bitor);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// BitXor (^)
+
+void JIT::emit_op_bitxor(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ unsigned op;
+ int32_t constant;
+ if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
+ emitLoad(op, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ xor32(Imm32(constant), regT0);
+ emitStoreInt32(dst, regT0, (op == dst));
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ xor32(regT2, regT0);
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+}
+
+void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_bitxor);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// BitNot (~)
+
+void JIT::emit_op_bitnot(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+
+ not32(regT0);
+ emitStoreInt32(dst, regT0, (dst == src));
+}
+
+void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_bitnot);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.call(dst);
+}
+
+// PostInc (i++)
+
+void JIT::emit_op_post_inc(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ emitLoad(srcDst, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+
+ if (dst == srcDst) // x = x++ is a noop for ints.
+ return;
+
+ emitStoreInt32(dst, regT0);
+
+ addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+ emitStoreInt32(srcDst, regT0, true);
+}
+
+void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter); // int32 check
+ if (dst != srcDst)
+ linkSlowCase(iter); // overflow check
+
+ JITStubCall stubCall(this, cti_op_post_inc);
+ stubCall.addArgument(srcDst);
+ stubCall.addArgument(Imm32(srcDst));
+ stubCall.call(dst);
+}
+
+// PostDec (i--)
+
+void JIT::emit_op_post_dec(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ emitLoad(srcDst, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+
+ if (dst == srcDst) // x = x-- is a noop for ints.
+ return;
+
+ emitStoreInt32(dst, regT0);
+
+ addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
+ emitStoreInt32(srcDst, regT0, true);
+}
+
+void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter); // int32 check
+ if (dst != srcDst)
+ linkSlowCase(iter); // overflow check
+
+ JITStubCall stubCall(this, cti_op_post_dec);
+ stubCall.addArgument(srcDst);
+ stubCall.addArgument(Imm32(srcDst));
+ stubCall.call(dst);
+}
+
+// PreInc (++i)
+
+void JIT::emit_op_pre_inc(Instruction* currentInstruction)
+{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ emitLoad(srcDst, regT1, regT0);
+
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+ emitStoreInt32(srcDst, regT0, true);
+}
+
+void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // overflow check
+
+ JITStubCall stubCall(this, cti_op_pre_inc);
+ stubCall.addArgument(srcDst);
+ stubCall.call(srcDst);
+}
+
+// PreDec (--i)
+
+void JIT::emit_op_pre_dec(Instruction* currentInstruction)
+{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ emitLoad(srcDst, regT1, regT0);
+
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
+ emitStoreInt32(srcDst, regT0, true);
+}
+
+void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // overflow check
+
+ JITStubCall stubCall(this, cti_op_pre_dec);
+ stubCall.addArgument(srcDst);
+ stubCall.call(srcDst);
+}
+
+// Addition (+)
+
+void JIT::emit_op_add(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ unsigned op;
+ int32_t constant;
+ if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
+ emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second());
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+
+ // Int32 case.
+ addSlowCase(branchAdd32(Overflow, regT2, regT0));
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32Op1);
+ addSlowCase(notInt32Op2);
+ return;
+ }
+ Jump end = jump();
+
+ // Double case.
+ emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2);
+ end.link(this);
+}
+
+void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
+{
+ // Int32 case.
+ emitLoad(op, regT1, regT0);
+ Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
+ emitStoreInt32(dst, regT0, (op == dst));
+
+ // Double case.
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32);
+ return;
+ }
+ Jump end = jump();
+
+ notInt32.link(this);
+ if (!opType.definitelyIsNumber())
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+ move(Imm32(constant), regT2);
+ convertInt32ToDouble(regT2, fpRegT0);
+ emitLoadDouble(op, fpRegT1);
+ addDouble(fpRegT1, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+
+ end.link(this);
+}
+
+void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ unsigned op;
+ int32_t constant;
+ if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
+ linkSlowCase(iter); // overflow check
+
+ if (!supportsFloatingPoint())
+ linkSlowCase(iter); // non-sse case
+ else {
+ ResultType opType = op == op1 ? types.first() : types.second();
+ if (!opType.definitelyIsNumber())
+ linkSlowCase(iter); // double check
+ }
+ } else {
+ linkSlowCase(iter); // overflow check
+
+ if (!supportsFloatingPoint()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ } else {
+ if (!types.first().definitelyIsNumber())
+ linkSlowCase(iter); // double check
+
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // double check
+ }
+ }
+ }
+
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// Subtraction (-)
+
+void JIT::emit_op_sub(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+
+ // Int32 case.
+ addSlowCase(branchSub32(Overflow, regT2, regT0));
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32Op1);
+ addSlowCase(notInt32Op2);
+ return;
+ }
+ Jump end = jump();
+
+ // Double case.
+ emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
+ end.link(this);
+}
+
+void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
+{
+ // Int32 case.
+ emitLoad(op, regT1, regT0);
+ Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
+ emitStoreInt32(dst, regT0, (op == dst));
+
+ // Double case.
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32);
+ return;
+ }
+ Jump end = jump();
+
+ notInt32.link(this);
+ if (!opType.definitelyIsNumber())
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+ move(Imm32(constant), regT2);
+ convertInt32ToDouble(regT2, fpRegT0);
+ emitLoadDouble(op, fpRegT1);
+ subDouble(fpRegT0, fpRegT1);
+ emitStoreDouble(dst, fpRegT1);
+
+ end.link(this);
+}
+
+void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = 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(op2)) {
+ linkSlowCase(iter); // overflow check
+
+ if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
+ linkSlowCase(iter); // int32 or double check
+ } else {
+ linkSlowCase(iter); // overflow check
+
+ if (!supportsFloatingPoint()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ } else {
+ if (!types.first().definitelyIsNumber())
+ linkSlowCase(iter); // double check
+
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // double check
+ }
+ }
+ }
+
+ JITStubCall stubCall(this, cti_op_sub);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
+{
+ JumpList end;
+
+ if (!notInt32Op1.empty()) {
+ // Double case 1: Op1 is not int32; Op2 is unknown.
+ notInt32Op1.link(this);
+
+ ASSERT(op1IsInRegisters);
+
+ // Verify Op1 is double.
+ if (!types.first().definitelyIsNumber())
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+
+ if (!op2IsInRegisters)
+ emitLoad(op2, regT3, regT2);
+
+ Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag));
+
+ if (!types.second().definitelyIsNumber())
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+
+ convertInt32ToDouble(regT2, fpRegT0);
+ Jump doTheMath = jump();
+
+ // Load Op2 as double into double register.
+ doubleOp2.link(this);
+ emitLoadDouble(op2, fpRegT0);
+
+ // Do the math.
+ doTheMath.link(this);
+ switch (opcodeID) {
+ case op_mul:
+ emitLoadDouble(op1, fpRegT2);
+ mulDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_add:
+ emitLoadDouble(op1, fpRegT2);
+ addDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_sub:
+ emitLoadDouble(op1, fpRegT1);
+ subDouble(fpRegT0, fpRegT1);
+ emitStoreDouble(dst, fpRegT1);
+ break;
+ case op_div:
+ emitLoadDouble(op1, fpRegT1);
+ divDouble(fpRegT0, fpRegT1);
+ emitStoreDouble(dst, fpRegT1);
+ break;
+ case op_jnless:
+ emitLoadDouble(op1, fpRegT2);
+ addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT2), dst + 3);
+ break;
+ case op_jnlesseq:
+ emitLoadDouble(op1, fpRegT2);
+ addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT2), dst + 3);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ if (!notInt32Op2.empty())
+ end.append(jump());
+ }
+
+ if (!notInt32Op2.empty()) {
+ // Double case 2: Op1 is int32; Op2 is not int32.
+ notInt32Op2.link(this);
+
+ ASSERT(op2IsInRegisters);
+
+ if (!op1IsInRegisters)
+ emitLoadPayload(op1, regT0);
+
+ convertInt32ToDouble(regT0, fpRegT0);
+
+ // Verify op2 is double.
+ if (!types.second().definitelyIsNumber())
+ addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag)));
+
+ // Do the math.
+ switch (opcodeID) {
+ case op_mul:
+ emitLoadDouble(op2, fpRegT2);
+ mulDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_add:
+ emitLoadDouble(op2, fpRegT2);
+ addDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_sub:
+ emitLoadDouble(op2, fpRegT2);
+ subDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_div:
+ emitLoadDouble(op2, fpRegT2);
+ divDouble(fpRegT2, fpRegT0);
+ emitStoreDouble(dst, fpRegT0);
+ break;
+ case op_jnless:
+ emitLoadDouble(op2, fpRegT1);
+ addJump(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), dst + 3);
+ break;
+ case op_jnlesseq:
+ emitLoadDouble(op2, fpRegT1);
+ addJump(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), dst + 3);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ end.link(this);
+}
+
+// Multiplication (*)
+
+void JIT::emit_op_mul(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+
+ // Int32 case.
+ move(regT0, regT3);
+ addSlowCase(branchMul32(Overflow, regT2, regT0));
+ addSlowCase(branchTest32(Zero, regT0));
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+
+ if (!supportsFloatingPoint()) {
+ addSlowCase(notInt32Op1);
+ addSlowCase(notInt32Op2);
+ return;
+ }
+ Jump end = jump();
+
+ // Double case.
+ emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2);
+ end.link(this);
+}
+
+void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+ OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+ Jump overflow = getSlowCase(iter); // overflow check
+ linkSlowCase(iter); // zero result check
+
+ Jump negZero = branchOr32(Signed, regT2, regT3);
+ emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst));
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
+
+ negZero.link(this);
+ overflow.link(this);
+
+ if (!supportsFloatingPoint()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ }
+
+ if (supportsFloatingPoint()) {
+ if (!types.first().definitelyIsNumber())
+ linkSlowCase(iter); // double check
+
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // double check
+ }
+ }
+
+ Label jitStubCall(this);
+ JITStubCall stubCall(this, cti_op_mul);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// Division (/)
+
+void JIT::emit_op_div(Instruction* currentInstruction)
+{
+ unsigned dst = 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 (!supportsFloatingPoint()) {
+ addSlowCase(jump());
+ return;
+ }
+
+ // Int32 divide.
+ JumpList notInt32Op1;
+ JumpList notInt32Op2;
+
+ JumpList end;
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+
+ notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+
+ convertInt32ToDouble(regT0, fpRegT0);
+ convertInt32ToDouble(regT2, fpRegT1);
+ divDouble(fpRegT1, fpRegT0);
+
+ JumpList doubleResult;
+ if (!isOperandConstantImmediateInt(op1) || getConstantOperand(op1).asInt32() > 1) {
+ m_assembler.cvttsd2si_rr(fpRegT0, regT0);
+ convertInt32ToDouble(regT0, fpRegT1);
+ m_assembler.ucomisd_rr(fpRegT1, fpRegT0);
+
+ doubleResult.append(m_assembler.jne());
+ doubleResult.append(m_assembler.jp());
+
+ doubleResult.append(branchTest32(Zero, regT0));
+
+ // Int32 result.
+ emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+ end.append(jump());
+ }
+
+ // Double result.
+ doubleResult.link(this);
+ emitStoreDouble(dst, fpRegT0);
+ end.append(jump());
+
+ // Double divide.
+ emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);
+ end.link(this);
+}
+
+void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = 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 (!supportsFloatingPoint())
+ linkSlowCase(iter);
+ else {
+ if (!types.first().definitelyIsNumber())
+ linkSlowCase(iter); // double check
+
+ if (!types.second().definitelyIsNumber()) {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // double check
+ }
+ }
+
+ JITStubCall stubCall(this, cti_op_div);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+// Mod (%)
+
+/* ------------------------------ BEGIN: OP_MOD ------------------------------ */
+
+#if PLATFORM(X86) || PLATFORM(X86_64)
+
+void JIT::emit_op_mod(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
+ emitLoad(op1, X86::edx, X86::eax);
+ move(Imm32(getConstantOperand(op2).asInt32()), X86::ecx);
+ addSlowCase(branch32(NotEqual, X86::edx, Imm32(JSValue::Int32Tag)));
+ if (getConstantOperand(op2).asInt32() == -1)
+ addSlowCase(branch32(Equal, X86::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+ } else {
+ emitLoad2(op1, X86::edx, X86::eax, op2, X86::ebx, X86::ecx);
+ addSlowCase(branch32(NotEqual, X86::edx, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, X86::ebx, Imm32(JSValue::Int32Tag)));
+
+ addSlowCase(branch32(Equal, X86::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+ addSlowCase(branch32(Equal, X86::ecx, Imm32(0))); // divide by 0
+ }
+
+ move(X86::eax, X86::ebx); // Save dividend payload, in case of 0.
+ m_assembler.cdq();
+ m_assembler.idivl_r(X86::ecx);
+
+ // If the remainder is zero and the dividend is negative, the result is -0.
+ Jump storeResult1 = branchTest32(NonZero, X86::edx);
+ Jump storeResult2 = branchTest32(Zero, X86::ebx, Imm32(0x80000000)); // not negative
+ emitStore(dst, jsNumber(m_globalData, -0.0));
+ Jump end = jump();
+
+ storeResult1.link(this);
+ storeResult2.link(this);
+ emitStoreInt32(dst, X86::edx, (op1 == dst || op2 == dst));
+ end.link(this);
+}
+
+void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
+ linkSlowCase(iter); // int32 check
+ if (getConstantOperand(op2).asInt32() == -1)
+ linkSlowCase(iter); // 0x80000000 check
+ } else {
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // 0 check
+ linkSlowCase(iter); // 0x80000000 check
+ }
+
+ JITStubCall stubCall(this, cti_op_mod);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+#else // PLATFORM(X86) || PLATFORM(X86_64)
+
+void JIT::emit_op_mod(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_mod);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call(dst);
+}
+
+void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+}
+
+#endif // PLATFORM(X86) || PLATFORM(X86_64)
+
+/* ------------------------------ END: OP_MOD ------------------------------ */
+
+#else // USE(JSVALUE32_64)
+
+void JIT::emit_op_lshift(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegisters(op1, regT0, op2, regT2);
+ // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT2);
+ emitFastArithImmToInt(regT0);
+ emitFastArithImmToInt(regT2);
+#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), regT2);
+#endif
+ lshift32(regT2, regT0);
+#if !USE(JSVALUE64)
+ addSlowCase(branchAdd32(Overflow, regT0, regT0));
+ signExtend32ToPtr(regT0, regT0);
+#endif
+ emitFastArithReTagImmediate(regT0, regT0);
+ emitPutVirtualRegister(result);
+}
+
+void JIT::emitSlow_op_lshift(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 USE(JSVALUE64)
+ 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, regT0, op2, regT2);
+ notImm1.link(this);
+ notImm2.link(this);
+#endif
+ JITStubCall stubCall(this, cti_op_lshift);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT2);
+ stubCall.call(result);
+}
+
+void JIT::emit_op_rshift(Instruction* currentInstruction)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ if (isOperandConstantImmediateInt(op2)) {
+ // isOperandConstantImmediateInt(op2) => 1 SlowCase
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+#if USE(JSVALUE64)
+ rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
+#else
+ rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
+#endif
+ } else {
+ emitGetVirtualRegisters(op1, regT0, op2, regT2);
+ if (supportsFloatingPointTruncate()) {
+ Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
+ addSlowCase(emitJumpIfNotImmediateNumber(regT0));
+ addPtr(tagTypeNumberRegister, regT0);
+ movePtrToDouble(regT0, fpRegT0);
+ addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
+#else
+ // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell)
+ emitJumpSlowCaseIfNotJSCell(regT0, op1);
+ addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get()));
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+ addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
+ addSlowCase(branchAdd32(Overflow, regT0, regT0));
+#endif
+ lhsIsInt.link(this);
+ emitJumpSlowCaseIfNotImmediateInteger(regT2);
+ } else {
+ // !supportsFloatingPoint() => 2 SlowCases
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT2);
+ }
+ emitFastArithImmToInt(regT2);
+#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), regT2);
+#endif
+#if USE(JSVALUE64)
+ rshift32(regT2, regT0);
+#else
+ rshiftPtr(regT2, regT0);
+#endif
+ }
+#if USE(JSVALUE64)
+ emitFastArithIntToImmNoCheck(regT0, regT0);
+#else
+ orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
+#endif
+ emitPutVirtualRegister(result);
+}
+
+void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_rshift);
+
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ } else {
+ if (supportsFloatingPointTruncate()) {
+#if USE(JSVALUE64)
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#else
+ linkSlowCaseIfNotJSCell(iter, op1);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+#endif
+ // We're reloading op1 to regT0 as we can no longer guarantee that
+ // we have not munged the operand. It may have already been shifted
+ // correctly, but it still will not have been tagged.
+ stubCall.addArgument(op1, regT0);
+ stubCall.addArgument(regT2);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT2);
+ }
+ }
+
+ stubCall.call(result);
+}
+
+void JIT::emit_op_jnless(Instruction* currentInstruction)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ // We generate inline code for the following cases in the fast path:
+ // - int immediate to constant int immediate
+ // - constant int immediate to int immediate
+ // - int immediate to int immediate
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target + 3);
+ } else if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+ int32_t op1imm = getConstantOperandImmediateInt(op1);
+#else
+ int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
+#endif
+ addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+
+ addJump(branch32(GreaterThanOrEqual, regT0, regT1), target + 3);
+ }
+}
+
+void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ // We generate inline code for the following cases in the slow path:
+ // - floating-point number to constant int immediate
+ // - constant int immediate to floating-point number
+ // - floating-point number to floating-point number.
+
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+ addPtr(tagTypeNumberRegister, regT0);
+ movePtrToDouble(regT0, fpRegT0);
+#else
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1 = emitJumpIfNotJSCell(regT0);
+
+ Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+#endif
+
+ int32_t op2imm = getConstantOperand(op2).asInt32();;
+
+ move(Imm32(op2imm), regT1);
+ convertInt32ToDouble(regT1, fpRegT1);
+
+ emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
+#else
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1.link(this);
+ fail2.link(this);
+#endif
+ }
+
+ JITStubCall stubCall(this, cti_op_jless);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+
+ } else if (isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter);
-using namespace std;
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
+ addPtr(tagTypeNumberRegister, regT1);
+ movePtrToDouble(regT1, fpRegT1);
+#else
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail1 = emitJumpIfNotJSCell(regT1);
+
+ Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
+ loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+
+ int32_t op1imm = getConstantOperand(op1).asInt32();;
+
+ move(Imm32(op1imm), regT0);
+ convertInt32ToDouble(regT0, fpRegT0);
-namespace JSC {
+ emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
-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);
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
+#else
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail1.link(this);
+ fail2.link(this);
+#endif
+ }
+
+ JITStubCall stubCall(this, cti_op_jless);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+
+ } else {
+ linkSlowCase(iter);
+
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+ Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
+ Jump fail3 = emitJumpIfImmediateInteger(regT1);
+ addPtr(tagTypeNumberRegister, regT0);
+ addPtr(tagTypeNumberRegister, regT1);
+ movePtrToDouble(regT0, fpRegT0);
+ movePtrToDouble(regT1, fpRegT1);
+#else
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1 = emitJumpIfNotJSCell(regT0);
+
+ Jump fail2;
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail2 = emitJumpIfNotJSCell(regT1);
+
+ Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
+ Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+ loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
#endif
- lshift32(X86::ecx, X86::eax);
-#if !USE(ALTERNATE_JSIMMEDIATE)
- addSlowCase(joAdd32(X86::eax, X86::eax));
- signExtend32ToPtr(X86::eax, X86::eax);
+
+ emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
+ fail2.link(this);
+ fail3.link(this);
+#else
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1.link(this);
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail2.link(this);
+ fail3.link(this);
+ fail4.link(this);
#endif
- emitFastArithReTagImmediate(X86::eax, X86::eax);
- emitPutVirtualRegister(result);
+ }
+
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jless);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+ }
}
-void JIT::compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- UNUSED_PARAM(op1);
- UNUSED_PARAM(op2);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ // We generate inline code for the following cases in the fast path:
+ // - int immediate to constant int immediate
+ // - constant int immediate to int immediate
+ // - int immediate to int immediate
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
#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);
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
#endif
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArg(X86::ecx, 2);
- emitCTICall(Interpreter::cti_op_lshift);
- emitPutVirtualRegister(result);
+ addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target + 3);
+ } else if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+ int32_t op1imm = getConstantOperandImmediateInt(op1);
+#else
+ int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
+#endif
+ addJump(branch32(LessThan, regT1, Imm32(op1imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+
+ addJump(branch32(GreaterThan, regT0, regT1), target + 3);
+ }
}
-void JIT::compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2)
+void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ // We generate inline code for the following cases in the slow path:
+ // - floating-point number to constant int immediate
+ // - constant int immediate to floating-point number
+ // - floating-point number to floating-point number.
+
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);
+ linkSlowCase(iter);
+
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+ addPtr(tagTypeNumberRegister, regT0);
+ movePtrToDouble(regT0, fpRegT0);
#else
- rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), X86::eax);
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1 = emitJumpIfNotJSCell(regT0);
+
+ Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
#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);
+
+ int32_t op2imm = getConstantOperand(op2).asInt32();;
+
+ move(Imm32(op2imm), regT1);
+ convertInt32ToDouble(regT1, fpRegT1);
+
+ emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
+#else
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1.link(this);
+ fail2.link(this);
#endif
-#if USE(ALTERNATE_JSIMMEDIATE)
- rshift32(X86::ecx, X86::eax);
+ }
+
+ JITStubCall stubCall(this, cti_op_jlesseq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+
+ } else if (isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter);
+
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
+ addPtr(tagTypeNumberRegister, regT1);
+ movePtrToDouble(regT1, fpRegT1);
#else
- rshiftPtr(X86::ecx, X86::eax);
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail1 = emitJumpIfNotJSCell(regT1);
+
+ Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
+ loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
#endif
- }
-#if USE(ALTERNATE_JSIMMEDIATE)
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+
+ int32_t op1imm = getConstantOperand(op1).asInt32();;
+
+ move(Imm32(op1imm), regT0);
+ convertInt32ToDouble(regT0, fpRegT0);
+
+ emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
#else
- orPtr(Imm32(JSImmediate::TagTypeNumber), X86::eax);
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail1.link(this);
+ fail2.link(this);
#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 {
+ }
+
+ JITStubCall stubCall(this, cti_op_jlesseq);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+
+ } else {
linkSlowCase(iter);
- emitPutJITStubArg(X86::ecx, 2);
- }
- emitPutJITStubArg(X86::eax, 1);
- emitCTICall(Interpreter::cti_op_rshift);
- emitPutVirtualRegister(result);
+ if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+ Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+ Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
+ Jump fail3 = emitJumpIfImmediateInteger(regT1);
+ addPtr(tagTypeNumberRegister, regT0);
+ addPtr(tagTypeNumberRegister, regT1);
+ movePtrToDouble(regT0, fpRegT0);
+ movePtrToDouble(regT1, fpRegT1);
+#else
+ Jump fail1;
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1 = emitJumpIfNotJSCell(regT0);
+
+ Jump fail2;
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail2 = emitJumpIfNotJSCell(regT1);
+
+ Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
+ Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+ loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+
+ emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+
+#if USE(JSVALUE64)
+ fail1.link(this);
+ fail2.link(this);
+ fail3.link(this);
+#else
+ if (!m_codeBlock->isKnownNotImmediate(op1))
+ fail1.link(this);
+ if (!m_codeBlock->isKnownNotImmediate(op2))
+ fail2.link(this);
+ fail3.link(this);
+ fail4.link(this);
+#endif
+ }
+
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jlesseq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+ }
}
-void JIT::compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2)
+void JIT::emit_op_bitand(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);
-#if USE(ALTERNATE_JSIMMEDIATE)
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
int32_t imm = getConstantOperandImmediateInt(op1);
- andPtr(Imm32(imm), X86::eax);
+ andPtr(Imm32(imm), regT0);
if (imm >= 0)
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ emitFastArithIntToImmNoCheck(regT0, regT0);
#else
- andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), X86::eax);
+ andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);
#endif
} else if (isOperandConstantImmediateInt(op2)) {
- emitGetVirtualRegister(op1, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
-#if USE(ALTERNATE_JSIMMEDIATE)
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
int32_t imm = getConstantOperandImmediateInt(op2);
- andPtr(Imm32(imm), X86::eax);
+ andPtr(Imm32(imm), regT0);
if (imm >= 0)
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ emitFastArithIntToImmNoCheck(regT0, regT0);
#else
- andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), X86::eax);
+ andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);
#endif
} else {
- emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
- andPtr(X86::edx, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ andPtr(regT1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
}
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
linkSlowCase(iter);
if (isOperandConstantImmediateInt(op1)) {
- emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
- emitPutJITStubArg(X86::eax, 2);
+ JITStubCall stubCall(this, cti_op_bitand);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT0);
+ stubCall.call(result);
} else if (isOperandConstantImmediateInt(op2)) {
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
+ JITStubCall stubCall(this, cti_op_bitand);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
} else {
- emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
- emitPutJITStubArg(X86::edx, 2);
+ JITStubCall stubCall(this, cti_op_bitand);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT1);
+ stubCall.call(result);
}
- 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)
+void JIT::emit_op_post_inc(Instruction* currentInstruction)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- linkSlowCase(iter);
- linkSlowCase(iter);
- linkSlowCase(iter);
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(srcDst, regT0);
+ move(regT0, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ addSlowCase(branchAdd32(Overflow, Imm32(1), regT1));
+ emitFastArithIntToImmNoCheck(regT1, regT1);
#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);
+ addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
+ signExtend32ToPtr(regT1, regT1);
#endif
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArg(X86::ecx, 2);
- emitCTICall(Interpreter::cti_op_mod);
+ emitPutVirtualRegister(srcDst, regT1);
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)
+void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
linkSlowCase(iter);
linkSlowCase(iter);
- emitPutJITStubArg(X86::eax, 1);
- emitCTICall(Interpreter::cti_op_post_inc);
- emitPutVirtualRegister(srcDst, X86::edx);
- emitPutVirtualRegister(result);
+ JITStubCall stubCall(this, cti_op_post_inc);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(Imm32(srcDst));
+ stubCall.call(result);
}
-void JIT::compileFastArith_op_post_dec(unsigned result, unsigned srcDst)
+void JIT::emit_op_post_dec(Instruction* currentInstruction)
{
- 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);
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(srcDst, regT0);
+ move(regT0, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ addSlowCase(branchSub32(Zero, Imm32(1), regT1));
+ emitFastArithIntToImmNoCheck(regT1, regT1);
#else
- addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::edx));
- signExtend32ToPtr(X86::edx, X86::edx);
+ addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
+ signExtend32ToPtr(regT1, regT1);
#endif
- emitPutVirtualRegister(srcDst, X86::edx);
+ emitPutVirtualRegister(srcDst, regT1);
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned result = currentInstruction[1].u.operand;
+ unsigned srcDst = currentInstruction[2].u.operand;
+
linkSlowCase(iter);
linkSlowCase(iter);
- emitPutJITStubArg(X86::eax, 1);
- emitCTICall(Interpreter::cti_op_post_dec);
- emitPutVirtualRegister(srcDst, X86::edx);
- emitPutVirtualRegister(result);
+ JITStubCall stubCall(this, cti_op_post_dec);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(Imm32(srcDst));
+ stubCall.call(result);
}
-void JIT::compileFastArith_op_pre_inc(unsigned srcDst)
+void JIT::emit_op_pre_inc(Instruction* currentInstruction)
{
- emitGetVirtualRegister(srcDst, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
-#if USE(ALTERNATE_JSIMMEDIATE)
- addSlowCase(joAdd32(Imm32(1), X86::eax));
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ emitGetVirtualRegister(srcDst, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+ emitFastArithIntToImmNoCheck(regT0, regT0);
#else
- addSlowCase(joAdd32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
- signExtend32ToPtr(X86::eax, X86::eax);
+ addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
+ signExtend32ToPtr(regT0, regT0);
#endif
emitPutVirtualRegister(srcDst);
}
-void JIT::compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
- emitGetVirtualRegister(srcDst, X86::eax);
+ emitGetVirtualRegister(srcDst, regT0);
notImm.link(this);
- emitPutJITStubArg(X86::eax, 1);
- emitCTICall(Interpreter::cti_op_pre_inc);
- emitPutVirtualRegister(srcDst);
+ JITStubCall stubCall(this, cti_op_pre_inc);
+ stubCall.addArgument(regT0);
+ stubCall.call(srcDst);
}
-void JIT::compileFastArith_op_pre_dec(unsigned srcDst)
+void JIT::emit_op_pre_dec(Instruction* currentInstruction)
{
- emitGetVirtualRegister(srcDst, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
-#if USE(ALTERNATE_JSIMMEDIATE)
- addSlowCase(joSub32(Imm32(1), X86::eax));
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ unsigned srcDst = currentInstruction[1].u.operand;
+
+ emitGetVirtualRegister(srcDst, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ addSlowCase(branchSub32(Zero, Imm32(1), regT0));
+ emitFastArithIntToImmNoCheck(regT0, regT0);
#else
- addSlowCase(joSub32(Imm32(1 << JSImmediate::IntegerPayloadShift), X86::eax));
- signExtend32ToPtr(X86::eax, X86::eax);
+ addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
+ signExtend32ToPtr(regT0, regT0);
#endif
emitPutVirtualRegister(srcDst);
}
-void JIT::compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned srcDst = currentInstruction[1].u.operand;
+
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
- emitGetVirtualRegister(srcDst, X86::eax);
+ emitGetVirtualRegister(srcDst, regT0);
notImm.link(this);
- emitPutJITStubArg(X86::eax, 1);
- emitCTICall(Interpreter::cti_op_pre_dec);
- emitPutVirtualRegister(srcDst);
+ JITStubCall stubCall(this, cti_op_pre_dec);
+ stubCall.addArgument(regT0);
+ stubCall.call(srcDst);
}
+/* ------------------------------ BEGIN: OP_MOD ------------------------------ */
-#if !ENABLE(JIT_OPTIMIZE_ARITHMETIC)
+#if PLATFORM(X86) || PLATFORM(X86_64)
-void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+void JIT::emit_op_mod(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);
+ emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
+ emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
+#if USE(JSVALUE64)
+ addSlowCase(branchPtr(Equal, X86::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
+ m_assembler.cdq();
+ m_assembler.idivl_r(X86::ecx);
+#else
+ emitFastArithDeTagImmediate(X86::eax);
+ addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
+ m_assembler.cdq();
+ m_assembler.idivl_r(X86::ecx);
+ signExtend32ToPtr(X86::edx, X86::edx);
+#endif
+ emitFastArithReTagImmediate(X86::edx, X86::eax);
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
- ASSERT_NOT_REACHED();
-}
-void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
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();
+#if USE(JSVALUE64)
+ 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
+ JITStubCall stubCall(this, cti_op_mod);
+ stubCall.addArgument(X86::eax);
+ stubCall.addArgument(X86::ecx);
+ stubCall.call(result);
}
-void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+#else // PLATFORM(X86) || PLATFORM(X86_64)
+
+void JIT::emit_op_mod(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);
+ JITStubCall stubCall(this, cti_op_mod);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
}
-void JIT::compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&)
+
+void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
{
ASSERT_NOT_REACHED();
}
-#elif USE(ALTERNATE_JSIMMEDIATE) // *AND* ENABLE(JIT_OPTIMIZE_ARITHMETIC)
+#endif // PLATFORM(X86) || PLATFORM(X86_64)
+
+/* ------------------------------ END: OP_MOD ------------------------------ */
+
+#if USE(JSVALUE64)
+
+/* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
{
- emitGetVirtualRegisters(op1, X86::eax, op2, X86::edx);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::edx);
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
if (opcodeID == op_add)
- addSlowCase(joAdd32(X86::edx, X86::eax));
+ addSlowCase(branchAdd32(Overflow, regT1, regT0));
else if (opcodeID == op_sub)
- addSlowCase(joSub32(X86::edx, X86::eax));
+ addSlowCase(branchSub32(Overflow, regT1, regT0));
else {
ASSERT(opcodeID == op_mul);
- addSlowCase(joMul32(X86::edx, X86::eax));
- addSlowCase(jz32(X86::eax));
+ addSlowCase(branchMul32(Overflow, regT1, regT0));
+ addSlowCase(branchTest32(Zero, regT0));
}
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ emitFastArithIntToImmNoCheck(regT0, regT0);
}
-void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned, unsigned op1, unsigned, OperandTypes types)
+void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, 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);
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);
+ emitGetVirtualRegister(op1, regT0);
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);
- }
+ JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(result);
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);
+ emitJumpIfNotImmediateNumber(regT0).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);
+ emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
+ addPtr(tagTypeNumberRegister, regT0);
+ movePtrToDouble(regT0, fpRegT1);
+ Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
+ convertInt32ToDouble(regT1, fpRegT2);
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);
+ emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
+ convertInt32ToDouble(regT0, fpRegT1);
op2isDouble.link(this);
- addPtr(tagTypeNumberRegister, X86::edx);
- m_assembler.movq_rr(X86::edx, X86::xmm2);
+ addPtr(tagTypeNumberRegister, regT1);
+ movePtrToDouble(regT1, fpRegT2);
op2wasInteger.link(this);
if (opcodeID == op_add)
- m_assembler.addsd_rr(X86::xmm2, X86::xmm1);
+ addDouble(fpRegT2, fpRegT1);
else if (opcodeID == op_sub)
- m_assembler.subsd_rr(X86::xmm2, X86::xmm1);
+ subDouble(fpRegT2, fpRegT1);
else {
ASSERT(opcodeID == op_mul);
- m_assembler.mulsd_rr(X86::xmm2, X86::xmm1);
+ mulDouble(fpRegT2, fpRegT1);
}
- m_assembler.movq_rr(X86::xmm1, X86::eax);
- subPtr(tagTypeNumberRegister, X86::eax);
+ moveDoubleToPtr(fpRegT1, regT0);
+ subPtr(tagTypeNumberRegister, regT0);
+ emitPutVirtualRegister(result, regT0);
end.link(this);
}
-void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+void JIT::emit_op_add(Instruction* currentInstruction)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].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);
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
return;
}
if (isOperandConstantImmediateInt(op1)) {
- emitGetVirtualRegister(op2, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
- addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op1)), X86::eax));
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
+ emitFastArithIntToImmNoCheck(regT0, regT0);
} else if (isOperandConstantImmediateInt(op2)) {
- emitGetVirtualRegister(op1, X86::eax);
- emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
- addSlowCase(joAdd32(Imm32(getConstantOperandImmediateInt(op2)), X86::eax));
- emitFastArithIntToImmNoCheck(X86::eax, X86::eax);
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
+ emitFastArithIntToImmNoCheck(regT0, regT0);
} else
compileBinaryArithOp(op_add, result, op1, op2, types);
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_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)) {
+ if (isOperandConstantImmediateInt(op1) || isOperandConstantImmediateInt(op2)) {
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);
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
} else
- compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
-
- emitPutVirtualRegister(result);
+ compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
}
-void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+void JIT::emit_op_mul(Instruction* currentInstruction)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].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);
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
+ emitFastArithReTagImmediate(regT0, regT0);
} 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);
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
+ emitFastArithReTagImmediate(regT0, regT0);
} else
compileBinaryArithOp(op_mul, result, op1, op2, types);
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].u.operand;
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);
+ JITStubCall stubCall(this, cti_op_mul);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
} else
compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types);
-
- emitPutVirtualRegister(result);
}
-void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+void JIT::emit_op_sub(Instruction* currentInstruction)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].u.operand;
emitPutVirtualRegister(result);
}
-void JIT::compileFastArithSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].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
+#else // USE(JSVALUE64)
-/*
- 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);
-}
+/* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
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;
+ Jump wasJSNumberCell1;
+ Jump wasJSNumberCell2;
- emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
+ emitGetVirtualRegisters(src1, regT0, src2, regT1);
- if (types.second().isReusable() && isSSE2Present()) {
+ if (types.second().isReusable() && supportsFloatingPoint()) {
ASSERT(types.second().mightBeNumber());
// Check op2 is a number
- __ testl_i32r(JSImmediate::TagTypeNumber, X86::edx);
- JmpSrc op2imm = __ jne();
+ Jump op2imm = emitJumpIfImmediateInteger(regT1);
if (!types.second().definitelyIsNumber()) {
- emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
- __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
- addSlowCase(__ jne());
+ emitJumpSlowCaseIfNotJSCell(regT1, src2);
+ addSlowCase(checkStructure(regT1, numberStructure));
}
// (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();
+ Jump op1imm = emitJumpIfImmediateInteger(regT0);
if (!types.first().definitelyIsNumber()) {
- emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
- __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
- addSlowCase(__ jne());
+ emitJumpSlowCaseIfNotJSCell(regT0, src1);
+ addSlowCase(checkStructure(regT0, numberStructure));
}
// (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();
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+ Jump loadedDouble = jump();
// (1b) if we get here, src1 is an immediate
- __ link(op1imm, __ label());
- emitFastArithImmToInt(X86::eax);
- __ cvtsi2sd_rr(X86::eax, X86::xmm0);
+ op1imm.link(this);
+ emitFastArithImmToInt(regT0);
+ convertInt32ToDouble(regT0, fpRegT0);
// (1c)
- __ link(loadedDouble, __ label());
+ loadedDouble.link(this);
if (opcodeID == op_add)
- __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
else if (opcodeID == op_sub)
- __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
else {
ASSERT(opcodeID == op_mul);
- __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
+ mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
}
- putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax);
- wasJSNumberCell2b = __ jmp();
+ // Store the result to the JSNumberCell and jump.
+ storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)));
+ move(regT1, regT0);
+ emitPutVirtualRegister(dst);
+ wasJSNumberCell2 = jump();
// (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()) {
+ op2imm.link(this);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ } else if (types.first().isReusable() && supportsFloatingPoint()) {
ASSERT(types.first().mightBeNumber());
// Check op1 is a number
- __ testl_i32r(JSImmediate::TagTypeNumber, X86::eax);
- JmpSrc op1imm = __ jne();
+ Jump op1imm = emitJumpIfImmediateInteger(regT0);
if (!types.first().definitelyIsNumber()) {
- emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
- __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
- addSlowCase(__ jne());
+ emitJumpSlowCaseIfNotJSCell(regT0, src1);
+ addSlowCase(checkStructure(regT0, numberStructure));
}
// (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();
+ Jump op2imm = emitJumpIfImmediateInteger(regT1);
if (!types.second().definitelyIsNumber()) {
- emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
- __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
- addSlowCase(__ jne());
+ emitJumpSlowCaseIfNotJSCell(regT1, src2);
+ addSlowCase(checkStructure(regT1, numberStructure));
}
// (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();
+ loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+ Jump loadedDouble = jump();
// (1b) if we get here, src2 is an immediate
- __ link(op2imm, __ label());
- emitFastArithImmToInt(X86::edx);
- __ cvtsi2sd_rr(X86::edx, X86::xmm1);
+ op2imm.link(this);
+ emitFastArithImmToInt(regT1);
+ convertInt32ToDouble(regT1, fpRegT1);
// (1c)
- __ link(loadedDouble, __ label());
- __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
+ loadedDouble.link(this);
+ loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
if (opcodeID == op_add)
- __ addsd_rr(X86::xmm1, X86::xmm0);
+ addDouble(fpRegT1, fpRegT0);
else if (opcodeID == op_sub)
- __ subsd_rr(X86::xmm1, X86::xmm0);
+ subDouble(fpRegT1, fpRegT0);
else {
ASSERT(opcodeID == op_mul);
- __ mulsd_rr(X86::xmm1, X86::xmm0);
+ mulDouble(fpRegT1, fpRegT0);
}
- __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);
+ storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
emitPutVirtualRegister(dst);
- putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx);
- wasJSNumberCell1b = __ jmp();
+ // Store the result to the JSNumberCell and jump.
+ storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
+ emitPutVirtualRegister(dst);
+ wasJSNumberCell1 = jump();
// (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);
+ op1imm.link(this);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
} else
- emitJumpSlowCaseIfNotImmediateIntegers(X86::eax, X86::edx, X86::ecx);
+ emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
if (opcodeID == op_add) {
- emitFastArithDeTagImmediate(X86::eax);
- __ addl_rr(X86::edx, X86::eax);
- addSlowCase(__ jo());
+ emitFastArithDeTagImmediate(regT0);
+ addSlowCase(branchAdd32(Overflow, regT1, regT0));
} else if (opcodeID == op_sub) {
- __ subl_rr(X86::edx, X86::eax);
- addSlowCase(__ jo());
- signExtend32ToPtr(X86::eax, X86::eax);
- emitFastArithReTagImmediate(X86::eax, X86::eax);
+ addSlowCase(branchSub32(Overflow, regT1, regT0));
+ signExtend32ToPtr(regT0, regT0);
+ emitFastArithReTagImmediate(regT0, regT0);
} 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());
+ emitFastArithImmToInt(regT1);
+ Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0);
+ Jump op2NonZero = branchTest32(NonZero, regT1);
+ op1Zero.link(this);
// 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());
+ move(regT0, regT2);
+ addSlowCase(branchAdd32(Signed, regT1, regT2));
// 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);
+ op2NonZero.link(this);
+ addSlowCase(branchMul32(Overflow, regT1, regT0));
+ signExtend32ToPtr(regT0, regT0);
+ emitFastArithReTagImmediate(regT0, regT0);
}
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());
- }
+ if (types.second().isReusable() && supportsFloatingPoint())
+ wasJSNumberCell2.link(this);
+ else if (types.first().isReusable() && supportsFloatingPoint())
+ wasJSNumberCell1.link(this);
}
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.second().isReusable() && supportsFloatingPoint()) {
if (!types.first().definitelyIsNumber()) {
linkSlowCaseIfNotJSCell(iter, src1);
linkSlowCase(iter);
linkSlowCaseIfNotJSCell(iter, src2);
linkSlowCase(iter);
}
- } else if (types.first().isReusable() && isSSE2Present()) {
+ } else if (types.first().isReusable() && supportsFloatingPoint()) {
if (!types.first().definitelyIsNumber()) {
linkSlowCaseIfNotJSCell(iter, src1);
linkSlowCase(iter);
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);
+ JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
+ stubCall.addArgument(src1, regT2);
+ stubCall.addArgument(src2, regT2);
+ stubCall.call(dst);
}
-void JIT::compileFastArith_op_add(Instruction* currentInstruction)
+void JIT::emit_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);
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0));
+ signExtend32ToPtr(regT0, regT0);
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);
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0));
+ signExtend32ToPtr(regT0, regT0);
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);
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
}
}
}
-void JIT::compileFastArithSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+
+void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].u.operand;
if (isOperandConstantImmediateInt(op1)) {
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
- sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), X86::eax);
+ sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0);
notImm.link(this);
- emitPutJITStubArgFromVirtualRegister(op1, 1, X86::ecx);
- emitPutJITStubArg(X86::eax, 2);
- emitCTICall(Interpreter::cti_op_add);
- emitPutVirtualRegister(result);
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT0);
+ stubCall.call(result);
} else if (isOperandConstantImmediateInt(op2)) {
Jump notImm = getSlowCase(iter);
linkSlowCase(iter);
- sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), X86::eax);
+ sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0);
notImm.link(this);
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArgFromVirtualRegister(op2, 2, X86::ecx);
- emitCTICall(Interpreter::cti_op_add);
- emitPutVirtualRegister(result);
+ JITStubCall stubCall(this, cti_op_add);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
} else {
OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
}
}
-void JIT::compileFastArith_op_mul(Instruction* currentInstruction)
+void JIT::emit_op_mul(Instruction* currentInstruction)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].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);
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitFastArithDeTagImmediate(regT0);
+ addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
+ signExtend32ToPtr(regT0, regT0);
+ emitFastArithReTagImmediate(regT0, regT0);
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);
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitFastArithDeTagImmediate(regT0);
+ addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
+ signExtend32ToPtr(regT0, regT0);
+ emitFastArithReTagImmediate(regT0, regT0);
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)
+
+void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
unsigned result = currentInstruction[1].u.operand;
unsigned op1 = currentInstruction[2].u.operand;
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);
+ JITStubCall stubCall(this, cti_op_mul);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call(result);
} else
compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
}
-void JIT::compileFastArith_op_sub(Instruction* currentInstruction)
+void JIT::emit_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)
+
+void JIT::emitSlow_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
+#endif // USE(JSVALUE64)
+
+/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
+
+#endif // USE(JSVALUE32_64)
} // namespace JSC
#include "CodeBlock.h"
#include "JITInlineMethods.h"
+#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "Interpreter.h"
namespace JSC {
-void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
+#if USE(JSVALUE32_64)
+
+void JIT::compileOpCallInitializeCallFrame()
+{
+ // regT0 holds callee, regT1 holds argCount
+ store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // scopeChain
+
+ emitStore(static_cast<unsigned>(RegisterFile::OptionalCalleeArguments), JSValue());
+ storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); // callee
+ storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); // scopeChain
+}
+
+void JIT::compileOpCallSetupArgs(Instruction* instruction)
+{
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ emitPutJITStubArg(regT0, 1);
+ emitPutJITStubArg(regT1, 2);
+ emitPutJITStubArgConstant(registerOffset, 3);
+ emitPutJITStubArgConstant(argCount, 5);
+}
+
+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;
+
+ emitPutJITStubArg(regT0, 1);
+ emitPutJITStubArg(regT1, 2);
+ emitPutJITStubArgConstant(registerOffset, 3);
+ emitPutJITStubArgConstant(argCount, 5);
+ emitPutJITStubArgFromVirtualRegister(proto, 7, regT2, regT3);
+ emitPutJITStubArgConstant(thisRegister, 9);
+}
+
+void JIT::compileOpCallVarargsSetupArgs(Instruction*)
{
- // 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()));
+ emitPutJITStubArg(regT0, 1);
+ emitPutJITStubArg(regT1, 2);
+ emitPutJITStubArg(regT3, 3); // registerOffset
+ emitPutJITStubArg(regT2, 5); // argCount
}
-void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount)
+void JIT::compileOpCallVarargs(Instruction* instruction)
{
- // Currently we only link calls with the exact number of arguments.
- if (callerArgCount == calleeCodeBlock->m_numParameters) {
- ASSERT(!callLinkInfo->isLinked());
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+ int argCountRegister = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ emitLoad(callee, regT1, regT0);
+ emitLoadPayload(argCountRegister, regT2); // argCount
+ addPtr(Imm32(registerOffset), regT2, regT3); // registerOffset
+
+ compileOpCallVarargsSetupArgs(instruction);
+
+ emitJumpSlowCaseIfNotJSCell(callee, regT1);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
+
+ // Speculatively roll the callframe, assuming argCount will match the arity.
+ mul32(Imm32(sizeof(Register)), regT3, regT3);
+ addPtr(callFrameRegister, regT3);
+ storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
+ move(regT3, callFrameRegister);
+
+ move(regT2, regT1); // argCount
+
+ emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
+
+ emitStore(dst, regT1, regT0);
- calleeCodeBlock->addCaller(callLinkInfo);
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+
+ linkSlowCaseIfNotJSCell(iter, callee);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_call_NotJSFunction);
+ stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
+
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_call_varargs), dst, regT1, regT0);
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::emit_op_ret(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+
+ // We could JIT generate the deref, only calling out to C when the refcount hits zero.
+ if (m_codeBlock->needsFullScopeChain())
+ JITStubCall(this, cti_op_ret_scopeChain).call();
+
+ emitLoad(dst, regT1, regT0);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+ restoreReturnAddressBeforeReturn(regT2);
+ ret();
+}
+
+void JIT::emit_op_construct_verify(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+
+ emitLoad(dst, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
+}
+
+void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitLoad(src, regT1, regT0);
+ emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
+}
+
+void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
+}
+
+void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallVarargsSlowCase(currentInstruction, iter);
+}
+
+void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
+}
+
+void JIT::emit_op_call(Instruction* currentInstruction)
+{
+ compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_call_eval(Instruction* currentInstruction)
+{
+ compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_load_varargs(Instruction* currentInstruction)
+{
+ int argCountDst = currentInstruction[1].u.operand;
+ int argsOffset = currentInstruction[2].u.operand;
+
+ JITStubCall stubCall(this, cti_op_load_varargs);
+ stubCall.addArgument(Imm32(argsOffset));
+ stubCall.call();
+ // Stores a naked int32 in the register file.
+ store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
+}
+
+void JIT::emit_op_call_varargs(Instruction* currentInstruction)
+{
+ compileOpCallVarargs(currentInstruction);
+}
+
+void JIT::emit_op_construct(Instruction* currentInstruction)
+{
+ compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
+}
+
+#if !ENABLE(JIT_OPTIMIZE_CALL)
+
+/* ------------------------------ BEGIN: !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;
+
+ Jump wasEval1;
+ Jump wasEval2;
+ if (opcodeID == op_call_eval) {
+ JITStubCall stubCall(this, cti_op_call_eval);
+ stubCall.addArgument(callee);
+ stubCall.addArgument(JIT::Imm32(registerOffset));
+ stubCall.addArgument(JIT::Imm32(argCount));
+ stubCall.call();
+ wasEval1 = branchTest32(NonZero, regT0);
+ wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+ }
+
+ emitLoad(callee, regT1, regT2);
+
+ if (opcodeID == op_call)
+ compileOpCallSetupArgs(instruction);
+ else if (opcodeID == op_construct)
+ compileOpConstructSetupArgs(instruction);
+
+ emitJumpSlowCaseIfNotJSCell(callee, regT1);
+ addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)));
+
+ // First, in the case of a construct, allocate the new object.
+ if (opcodeID == op_construct) {
+ JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitLoad(callee, regT1, regT2);
+ }
+
+ // 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), regT1);
+
+ emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
+
+ if (opcodeID == op_call_eval) {
+ wasEval1.link(this);
+ wasEval2.link(this);
+ }
+
+ emitStore(dst, regT1, regT0);;
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+
+ linkSlowCaseIfNotJSCell(iter, callee);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
+ stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+#else // !ENABLE(JIT_OPTIMIZE_CALL)
+
+/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+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;
+
+ Jump wasEval1;
+ Jump wasEval2;
+ if (opcodeID == op_call_eval) {
+ JITStubCall stubCall(this, cti_op_call_eval);
+ stubCall.addArgument(callee);
+ stubCall.addArgument(JIT::Imm32(registerOffset));
+ stubCall.addArgument(JIT::Imm32(argCount));
+ stubCall.call();
+ wasEval1 = branchTest32(NonZero, regT0);
+ wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+ }
+
+ emitLoad(callee, regT1, regT0);
+
+ DataLabelPtr addressOfLinkedFunctionCheck;
+ Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0));
+ addSlowCase(jumpToSlow);
+ ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
+
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+
+ // 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;
+
+ JITStubCall stubCall(this, cti_op_construct_JSConstruct);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(Imm32(0)); // FIXME: Remove this unused JITStub argument.
+ stubCall.addArgument(Imm32(0)); // FIXME: Remove this unused JITStub argument.
+ stubCall.addArgument(proto);
+ stubCall.call(thisRegister);
+
+ emitLoad(callee, regT1, regT0);
+ }
+
+ // 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
+ emitStore(registerOffset + RegisterFile::OptionalCalleeArguments, JSValue());
+ emitStore(registerOffset + RegisterFile::Callee, regT1, regT0);
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // 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(regT1, 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();
- DataLabelPtr::patch(callLinkInfo->hotPathBegin, callee);
- Jump::patch(callLinkInfo->hotPathOther, ctiCode);
+ if (opcodeID == op_call_eval) {
+ wasEval1.link(this);
+ wasEval2.link(this);
}
- // 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);
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + opcodeLengths[opcodeID], dst, regT1, regT0);
+
+ 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);
+ 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 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+ Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr));
+
+ // First, in the case of a construct, allocate the new object.
+ if (opcodeID == op_construct) {
+ JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitLoad(callee, regT1, regT0);
+ }
+
+ // 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), regT1);
+
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallPreLink());
+
+ // Put the return value in dst.
+ emitStore(dst, regT1, regT0);;
+ sampleCodeBlock(m_codeBlock);
+
+ // If not, we need an extra case in the if below!
+ ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+
+ // Done! - return back to the hot path.
+ if (opcodeID == op_construct)
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_construct));
+ else
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
+
+ // This handles host functions
+ callLinkFailNotObject.link(this);
+ callLinkFailNotJSFunction.link(this);
+ JITStubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction).call();
+
+ emitStore(dst, regT1, regT0);;
+ sampleCodeBlock(m_codeBlock);
}
+/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+#endif // !ENABLE(JIT_OPTIMIZE_CALL)
+
+#else // USE(JSVALUE32_64)
+
void JIT::compileOpCallInitializeCallFrame()
{
- store32(X86::edx, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
+ store32(regT1, 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
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // 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))));
+ storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register))));
+ storePtr(regT2, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
+ storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register))));
}
void JIT::compileOpCallSetupArgs(Instruction* instruction)
int registerOffset = instruction[4].u.operand;
// ecx holds func
- emitPutJITStubArg(X86::ecx, 1);
- emitPutJITStubArgConstant(registerOffset, 2);
+ emitPutJITStubArg(regT2, 1);
emitPutJITStubArgConstant(argCount, 3);
+ emitPutJITStubArgConstant(registerOffset, 2);
}
-
-void JIT::compileOpCallEvalSetupArgs(Instruction* instruction)
+
+void JIT::compileOpCallVarargsSetupArgs(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);
+ emitPutJITStubArg(regT2, 1);
+ emitPutJITStubArg(regT1, 3);
+ addPtr(Imm32(registerOffset), regT1, regT0);
+ emitPutJITStubArg(regT0, 2);
}
void JIT::compileOpConstructSetupArgs(Instruction* instruction)
int thisRegister = instruction[6].u.operand;
// ecx holds func
- emitPutJITStubArg(X86::ecx, 1);
+ emitPutJITStubArg(regT2, 1);
emitPutJITStubArgConstant(registerOffset, 2);
emitPutJITStubArgConstant(argCount, 3);
- emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax);
+ emitPutJITStubArgFromVirtualRegister(proto, 4, regT0);
emitPutJITStubArgConstant(thisRegister, 5);
}
+void JIT::compileOpCallVarargs(Instruction* instruction)
+{
+ int dst = instruction[1].u.operand;
+ int callee = instruction[2].u.operand;
+ int argCountRegister = instruction[3].u.operand;
+
+ emitGetVirtualRegister(argCountRegister, regT1);
+ emitGetVirtualRegister(callee, regT2);
+ compileOpCallVarargsSetupArgs(instruction);
+
+ // Check for JSFunctions.
+ emitJumpSlowCaseIfNotJSCell(regT2);
+ addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)));
+
+ // Speculatively roll the callframe, assuming argCount will match the arity.
+ mul32(Imm32(sizeof(Register)), regT0, regT0);
+ intptr_t offset = (intptr_t)sizeof(Register) * (intptr_t)RegisterFile::CallerFrame;
+ addPtr(Imm32((int32_t)offset), regT0, regT3);
+ addPtr(callFrameRegister, regT3);
+ storePtr(callFrameRegister, regT3);
+ addPtr(regT0, callFrameRegister);
+ emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
+
+ // Put the return value in dst. In the interpreter, op_ret does this.
+ emitPutVirtualRegister(dst);
+
+ sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int dst = instruction[1].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_call_NotJSFunction);
+ stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
+
+ sampleCodeBlock(m_codeBlock);
+}
+
#if !ENABLE(JIT_OPTIMIZE_CALL)
+/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
{
int dst = instruction[1].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())));
+ JITStubCall stubCall(this, cti_op_call_eval);
+ stubCall.addArgument(callee, regT2);
+ stubCall.addArgument(JIT::Imm32(registerOffset));
+ stubCall.addArgument(JIT::Imm32(argCount));
+ stubCall.call();
+ wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
}
- emitGetVirtualRegister(callee, X86::ecx);
+ emitGetVirtualRegister(callee, regT2);
// The arguments have been set up on the hot path for op_call_eval
if (opcodeID == op_call)
compileOpCallSetupArgs(instruction);
compileOpConstructSetupArgs(instruction);
// Check for JSFunctions.
- emitJumpSlowCaseIfNotJSCell(X86::ecx);
- addSlowCase(jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)));
+ emitJumpSlowCaseIfNotJSCell(regT2);
+ addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->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);
+ JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitGetVirtualRegister(callee, regT2);
}
// 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);
+ move(Imm32(argCount), regT1);
- emitNakedCall(m_interpreter->m_ctiVirtualCall);
+ emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
if (opcodeID == op_call_eval)
wasEval.link(this);
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);
+ JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
+ stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
sampleCodeBlock(m_codeBlock);
}
-#else
+#else // !ENABLE(JIT_OPTIMIZE_CALL)
-static NO_RETURN void unreachable()
-{
- ASSERT_NOT_REACHED();
- exit(1);
-}
+/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
{
// 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())));
+ JITStubCall stubCall(this, cti_op_call_eval);
+ stubCall.addArgument(callee, regT2);
+ stubCall.addArgument(JIT::Imm32(registerOffset));
+ stubCall.addArgument(JIT::Imm32(argCount));
+ stubCall.call();
+ wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
}
// 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);
+ emitGetVirtualRegister(callee, regT2);
DataLabelPtr addressOfLinkedFunctionCheck;
- Jump jumpToSlow = jnePtrWithPatch(X86::ecx, addressOfLinkedFunctionCheck, ImmPtr(JSValuePtr::encode(jsImpossibleValue())));
+ Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT2, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue())));
addSlowCase(jumpToSlow);
ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
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);
+ emitPutJITStubArg(regT2, 1);
+ emitPutJITStubArgFromVirtualRegister(proto, 4, regT0);
+ JITStubCall stubCall(this, cti_op_construct_JSConstruct);
+ stubCall.call(thisRegister);
+ emitGetVirtualRegister(callee, regT2);
}
// 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
+ storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register))));
+ storePtr(regT2, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // 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))));
+ storePtr(regT1, 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));
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
if (opcodeID == op_call_eval)
wasEval.link(this);
compileOpConstructSetupArgs(instruction);
// Fast check for JS function.
- Jump callLinkFailNotObject = emitJumpIfNotJSCell(X86::ecx);
- Jump callLinkFailNotJSFunction = jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr));
+ Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT2);
+ Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->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);
+ JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
+ emitGetVirtualRegister(callee, regT2);
}
- 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);
+ move(Imm32(argCount), regT1);
- m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation =
- emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink);
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallPreLink());
- Jump storeResultForFirstRun = jump();
+ // Put the return value in dst.
+ emitPutVirtualRegister(dst);
+ sampleCodeBlock(m_codeBlock);
-// 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);
+ // If not, we need an extra case in the if below!
+ ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
- // 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));
+ // Done! - return back to the hot path.
+ if (opcodeID == op_construct)
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_construct));
+ else
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
// 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);
+ JITStubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction).call();
- // 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
+/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+#endif // !ENABLE(JIT_OPTIMIZE_CALL)
+
+#endif // USE(JSVALUE32_64)
} // 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 JITCode_h
+#define JITCode_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "CallFrame.h"
+#include "JSValue.h"
+#include "MacroAssemblerCodeRef.h"
+#include "Profiler.h"
+
+namespace JSC {
+
+ class JSGlobalData;
+ class RegisterFile;
+
+ class JITCode {
+ typedef MacroAssemblerCodeRef CodeRef;
+ typedef MacroAssemblerCodePtr CodePtr;
+ public:
+ JITCode()
+ {
+ }
+
+ JITCode(const CodeRef ref)
+ : m_ref(ref)
+ {
+ }
+
+ bool operator !() const
+ {
+ return !m_ref.m_code.executableAddress();
+ }
+
+ CodePtr addressForCall()
+ {
+ return m_ref.m_code;
+ }
+
+ // This function returns the offset in bytes of 'pointerIntoCode' into
+ // this block of code. The pointer provided must be a pointer into this
+ // block of code. It is ASSERTed that no codeblock >4gb in size.
+ unsigned offsetOf(void* pointerIntoCode)
+ {
+ intptr_t result = reinterpret_cast<intptr_t>(pointerIntoCode) - reinterpret_cast<intptr_t>(m_ref.m_code.executableAddress());
+ ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result)) == result);
+ return static_cast<unsigned>(result);
+ }
+
+ // Execute the code!
+ inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue* exception)
+ {
+ return JSValue::decode(ctiTrampoline(
+#if PLATFORM(X86_64)
+ 0, 0, 0, 0, 0, 0,
+#endif
+ m_ref.m_code.executableAddress(), registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
+ }
+
+ void* start()
+ {
+ return m_ref.m_code.dataLocation();
+ }
+
+ size_t size()
+ {
+ ASSERT(m_ref.m_code.executableAddress());
+ return m_ref.m_size;
+ }
+
+ ExecutablePool* getExecutablePool()
+ {
+ return m_ref.m_executablePool.get();
+ }
+
+ // Host functions are a bit special; they have a m_code pointer but they
+ // do not individully ref the executable pool containing the trampoline.
+ static JITCode HostFunction(CodePtr code)
+ {
+ return JITCode(code.dataLocation(), 0, 0);
+ }
+
+ private:
+ JITCode(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
+ : m_ref(code, executablePool, size)
+ {
+ }
+
+ CodeRef m_ref;
+ };
+
+};
+
+#endif
+
+#endif
#if ENABLE(JIT)
-#if PLATFORM(WIN)
-#undef FIELD_OFFSET // Fix conflict with winnt.h.
+namespace JSC {
+
+/* Deprecated: Please use JITStubCall instead. */
+
+// 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);
+}
+
+/* Deprecated: Please use JITStubCall instead. */
+
+ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
+{
+ poke(Imm32(value), argumentNumber);
+}
+
+/* Deprecated: Please use JITStubCall instead. */
+
+ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
+{
+ poke(ImmPtr(value), argumentNumber);
+}
+
+/* Deprecated: Please use JITStubCall instead. */
+
+ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
+{
+ peek(dst, argumentNumber);
+}
+
+ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
+{
+ ASSERT(m_codeBlock->isConstantRegisterIndex(src));
+ return m_codeBlock->getConstant(src);
+}
+
+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::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
+{
+ loadPtr(Address(from, entry * sizeof(Register)), to);
+#if !USE(JSVALUE32_64)
+ killLastResultRegister();
#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)
+ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
+{
+ load32(Address(from, entry * sizeof(Register)), to);
+#if !USE(JSVALUE32_64)
+ killLastResultRegister();
+#endif
+}
-namespace JSC {
+ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
-ALWAYS_INLINE void JIT::killLastResultRegister()
+ Call nakedCall = nearCall();
+ m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function.executableAddress()));
+ return nakedCall;
+}
+
+#if PLATFORM(X86) || PLATFORM(X86_64)
+
+ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
{
- m_lastResultBytecodeRegister = std::numeric_limits<int>::max();
+ pop(reg);
}
-// get arg puts an arg from the SF register array into a h/w register
-ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
+{
+ push(reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
+{
+ push(address);
+}
+
+#elif PLATFORM_ARM_ARCH(7)
+
+ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
+{
+ move(linkRegister, reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
+{
+ move(reg, linkRegister);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
+{
+ loadPtr(address, linkRegister);
+}
+
+#endif
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+ALWAYS_INLINE void JIT::restoreArgumentReference()
+{
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+}
+ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
+#else
+ALWAYS_INLINE void JIT::restoreArgumentReference()
+{
+ move(stackPointerRegister, firstArgumentRegister);
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+}
+ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
+{
+#if PLATFORM(X86)
+ // Within a trampoline the return address will be on the stack at this point.
+ addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
+#elif PLATFORM_ARM_ARCH(7)
+ move(stackPointerRegister, firstArgumentRegister);
+#endif
+ // In the trampoline on x86-64, the first argument register is not overwritten.
+}
+#endif
+
+ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
+{
+ return branchPtr(NotEqual, Address(reg, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(structure));
+}
+
+ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
+{
+ if (!m_codeBlock->isKnownNotImmediate(vReg))
+ linkSlowCase(iter);
+}
+
+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.
- // 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();
+ m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));
+}
+
+ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList)
+{
+ ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+ const JumpList::JumpVector& jumpVector = jumpList.jumps();
+ size_t size = jumpVector.size();
+ for (size_t i = 0; i < size; ++i)
+ m_slowCases.append(SlowCaseEntry(jumpVector[i], 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);
+}
+
+#if ENABLE(SAMPLING_FLAGS)
+ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
+{
+ ASSERT(flag >= 1);
+ ASSERT(flag <= 32);
+ or32(Imm32(1u << (flag - 1)), AbsoluteAddress(&SamplingFlags::s_flags));
+}
+
+ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
+{
+ ASSERT(flag >= 1);
+ ASSERT(flag <= 32);
+ and32(Imm32(~(1u << (flag - 1))), AbsoluteAddress(&SamplingFlags::s_flags));
+}
+#endif
+
+#if ENABLE(SAMPLING_COUNTERS)
+ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
+{
+#if PLATFORM(X86_64) // Or any other 64-bit plattform.
+ addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter));
+#elif PLATFORM(X86) // Or any other little-endian 32-bit plattform.
+ intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t);
+ add32(Imm32(count), AbsoluteAddress(&counter.m_counter));
+ addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
+#else
+#error "SAMPLING_FLAGS not implemented on this platform."
+#endif
+}
+#endif
+
+#if ENABLE(OPCODE_SAMPLING)
+#if PLATFORM(X86_64)
+ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
+{
+ move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86::ecx);
+ storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86::ecx);
+}
+#else
+ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
+{
+ storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
+}
+#endif
+#endif
+
+#if ENABLE(CODEBLOCK_SAMPLING)
+#if PLATFORM(X86_64)
+ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
+{
+ move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86::ecx);
+ storePtr(ImmPtr(codeBlock), X86::ecx);
+}
+#else
+ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
+{
+ storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
+}
+#endif
+#endif
+
+#if USE(JSVALUE32_64)
+
+inline JIT::Address JIT::tagFor(unsigned index, RegisterID base)
+{
+ return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
+}
+
+inline JIT::Address JIT::payloadFor(unsigned index, RegisterID base)
+{
+ return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
+}
+
+inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
+{
+ return Address(base, (index * sizeof(Register)));
+}
+
+inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
+{
+ RegisterID mappedTag;
+ if (getMappedTag(index, mappedTag)) {
+ move(mappedTag, tag);
+ unmap(tag);
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 (m_codeBlock->isConstantRegisterIndex(index)) {
+ move(Imm32(getConstantOperand(index).tag()), tag);
+ unmap(tag);
+ return;
+ }
- if (!atJumpTarget) {
- // The argument we want is already stored in eax
- if (dst != X86::eax)
- move(X86::eax, dst);
- killLastResultRegister();
- return;
- }
+ load32(tagFor(index), tag);
+ unmap(tag);
+}
+
+inline void JIT::emitLoadPayload(unsigned index, RegisterID payload)
+{
+ RegisterID mappedPayload;
+ if (getMappedPayload(index, mappedPayload)) {
+ move(mappedPayload, payload);
+ unmap(payload);
+ return;
}
- loadPtr(Address(callFrameRegister, src * sizeof(Register)), dst);
- killLastResultRegister();
+ if (m_codeBlock->isConstantRegisterIndex(index)) {
+ move(Imm32(getConstantOperand(index).payload()), payload);
+ unmap(payload);
+ return;
+ }
+
+ load32(payloadFor(index), payload);
+ unmap(payload);
}
-ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2)
+inline void JIT::emitLoad(const JSValue& v, RegisterID tag, RegisterID payload)
{
- if (src2 == m_lastResultBytecodeRegister) {
- emitGetVirtualRegister(src2, dst2);
- emitGetVirtualRegister(src1, dst1);
- } else {
- emitGetVirtualRegister(src1, dst1);
- emitGetVirtualRegister(src2, dst2);
+ move(Imm32(v.payload()), payload);
+ move(Imm32(v.tag()), tag);
+}
+
+inline void JIT::emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
+{
+ ASSERT(tag != payload);
+
+ if (base == callFrameRegister) {
+ ASSERT(payload != base);
+ emitLoadPayload(index, payload);
+ emitLoadTag(index, tag);
+ return;
}
+
+ if (payload == base) { // avoid stomping base
+ load32(tagFor(index, base), tag);
+ load32(payloadFor(index, base), payload);
+ return;
+ }
+
+ load32(payloadFor(index, base), payload);
+ load32(tagFor(index, base), tag);
}
-// puts an arg onto the stack, as an arg to a context threaded function.
-ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
+inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2)
{
- poke(src, argumentNumber);
+ if (isMapped(index1)) {
+ emitLoad(index1, tag1, payload1);
+ emitLoad(index2, tag2, payload2);
+ return;
+ }
+ emitLoad(index2, tag2, payload2);
+ emitLoad(index1, tag1, payload1);
}
-ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
+inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
{
- poke(Imm32(value), argumentNumber);
+ if (m_codeBlock->isConstantRegisterIndex(index)) {
+ Register& inConstantPool = m_codeBlock->constantRegister(index);
+ loadDouble(&inConstantPool, value);
+ } else
+ loadDouble(addressFor(index), value);
}
-ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
+inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
{
- poke(ImmPtr(value), argumentNumber);
+ if (m_codeBlock->isConstantRegisterIndex(index)) {
+ Register& inConstantPool = m_codeBlock->constantRegister(index);
+ char* bytePointer = reinterpret_cast<char*>(&inConstantPool);
+ convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value);
+ } else
+ convertInt32ToDouble(payloadFor(index), value);
}
-ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
+inline void JIT::emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
{
- peek(dst, argumentNumber);
+ store32(payload, payloadFor(index, base));
+ store32(tag, tagFor(index, base));
}
-ALWAYS_INLINE JSValuePtr JIT::getConstantOperand(unsigned src)
+inline void JIT::emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32)
{
- ASSERT(m_codeBlock->isConstantRegisterIndex(src));
- return m_codeBlock->getConstant(src);
+ store32(payload, payloadFor(index, callFrameRegister));
+ if (!indexIsInt32)
+ store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
}
-ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src)
+inline void JIT::emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32)
{
- return getConstantOperand(src).getInt32Fast();
+ store32(payload, payloadFor(index, callFrameRegister));
+ if (!indexIsInt32)
+ store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
}
-ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
+inline void JIT::emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell)
{
- return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32Fast();
+ store32(payload, payloadFor(index, callFrameRegister));
+ if (!indexIsCell)
+ store32(Imm32(JSValue::CellTag), tagFor(index, callFrameRegister));
}
-// 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)
+inline void JIT::emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool)
{
- 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);
- }
+ if (!indexIsBool)
+ store32(Imm32(0), payloadFor(index, callFrameRegister));
+ store32(tag, tagFor(index, callFrameRegister));
+}
- killLastResultRegister();
+inline void JIT::emitStoreDouble(unsigned index, FPRegisterID value)
+{
+ storeDouble(value, addressFor(index));
}
-ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name)
+inline void JIT::emitStore(unsigned index, const JSValue constant, RegisterID base)
{
- poke(ImmPtr(value), name);
+ store32(Imm32(constant.payload()), payloadFor(index, base));
+ store32(Imm32(constant.tag()), tagFor(index, base));
}
-ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name)
+ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
{
- poke(from, name);
+ emitStore(dst, jsUndefined());
}
-ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to)
+inline bool JIT::isLabeled(unsigned bytecodeIndex)
{
- peek(to, name);
- killLastResultRegister();
+ for (size_t numberOfJumpTargets = m_codeBlock->numberOfJumpTargets(); m_jumpTargetIndex != numberOfJumpTargets; ++m_jumpTargetIndex) {
+ unsigned jumpTarget = m_codeBlock->jumpTarget(m_jumpTargetIndex);
+ if (jumpTarget == bytecodeIndex)
+ return true;
+ if (jumpTarget > bytecodeIndex)
+ return false;
+ }
+ return false;
}
-ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
+inline void JIT::map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload)
{
- storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));
+ if (isLabeled(bytecodeIndex))
+ return;
+
+ m_mappedBytecodeIndex = bytecodeIndex;
+ m_mappedVirtualRegisterIndex = virtualRegisterIndex;
+ m_mappedTag = tag;
+ m_mappedPayload = payload;
}
-ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
+inline void JIT::unmap(RegisterID registerID)
{
- storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
+ if (m_mappedTag == registerID)
+ m_mappedTag = (RegisterID)-1;
+ else if (m_mappedPayload == registerID)
+ m_mappedPayload = (RegisterID)-1;
}
-ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to)
+inline void JIT::unmap()
{
- loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to);
- killLastResultRegister();
+ m_mappedBytecodeIndex = (unsigned)-1;
+ m_mappedVirtualRegisterIndex = (unsigned)-1;
+ m_mappedTag = (RegisterID)-1;
+ m_mappedPayload = (RegisterID)-1;
}
-ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
+inline bool JIT::isMapped(unsigned virtualRegisterIndex)
{
- 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.
+ if (m_mappedBytecodeIndex != m_bytecodeIndex)
+ return false;
+ if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
+ return false;
+ return true;
}
-ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
+inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload)
{
- storePtr(ImmPtr(JSValuePtr::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
- // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
+ if (m_mappedBytecodeIndex != m_bytecodeIndex)
+ return false;
+ if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
+ return false;
+ if (m_mappedPayload == (RegisterID)-1)
+ return false;
+ payload = m_mappedPayload;
+ return true;
}
-ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(X86::RegisterID r)
+inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag)
{
- ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+ if (m_mappedBytecodeIndex != m_bytecodeIndex)
+ return false;
+ if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
+ return false;
+ if (m_mappedTag == (RegisterID)-1)
+ return false;
+ tag = m_mappedTag;
+ return true;
+}
- Jump nakedCall = call(r);
- m_calls.append(CallRecord(nakedCall, m_bytecodeIndex));
- return nakedCall;
+inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex)
+{
+ if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
+ addSlowCase(branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag)));
}
-ALWAYS_INLINE JIT::Jump JIT::emitNakedCall(void* function)
+inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag)
{
- ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+ if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
+ addSlowCase(branch32(NotEqual, tag, Imm32(JSValue::CellTag)));
+}
- Jump nakedCall = call();
- m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function));
- return nakedCall;
+inline void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, unsigned virtualRegisterIndex)
+{
+ if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
+ linkSlowCase(iter);
}
-#if USE(JIT_STUB_ARGUMENT_REGISTER)
-ALWAYS_INLINE void JIT::restoreArgumentReference()
+ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
{
-#if PLATFORM(X86_64)
- move(X86::esp, X86::edi);
-#else
- move(X86::esp, X86::ecx);
-#endif
- emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+ return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
}
-ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
+
+ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant)
{
- // 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
+ if (isOperandConstantImmediateInt(op1)) {
+ constant = getConstantOperand(op1).asInt32();
+ op = op2;
+ return true;
+ }
+
+ if (isOperandConstantImmediateInt(op2)) {
+ constant = getConstantOperand(op2).asInt32();
+ op = op1;
+ return true;
+ }
+
+ return false;
}
-#elif USE(JIT_STUB_ARGUMENT_STACK)
-ALWAYS_INLINE void JIT::restoreArgumentReference()
+
+ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
{
- storePtr(X86::esp, X86::esp);
- emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+ return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
}
-ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
-#else // JIT_STUB_ARGUMENT_VA_LIST
-ALWAYS_INLINE void JIT::restoreArgumentReference()
+
+/* Deprecated: Please use JITStubCall instead. */
+
+ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2)
{
- emitPutCTIParam(callFrameRegister, STUB_ARGS_callFrame);
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ JSValue constant = m_codeBlock->getConstant(src);
+ poke(Imm32(constant.payload()), argumentNumber);
+ poke(Imm32(constant.tag()), argumentNumber + 1);
+ } else {
+ emitLoad(src, scratch1, scratch2);
+ poke(scratch2, argumentNumber);
+ poke(scratch1, argumentNumber + 1);
+ }
+}
+
+#else // USE(JSVALUE32_64)
+
+ALWAYS_INLINE void JIT::killLastResultRegister()
+{
+ m_lastResultBytecodeRegister = std::numeric_limits<int>::max();
}
-ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
-#endif
-ALWAYS_INLINE JIT::Jump JIT::emitCTICall_internal(void* helper)
+// 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.
-#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
+ // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ JSValue value = m_codeBlock->getConstant(src);
+ move(ImmPtr(JSValue::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 != cachedResultRegister)
+ move(cachedResultRegister, 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);
+ }
+}
- return ctiCall;
+ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(unsigned src)
+{
+ return getConstantOperand(src).asInt32();
}
-ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
+ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
+{
+ return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
+}
+
+ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
{
- return jnePtr(Address(reg, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(structure));
+ storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));
+ m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();
+}
+
+ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
+{
+ storePtr(ImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
}
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- return jzPtr(reg, tagMaskRegister);
+#if USE(JSVALUE64)
+ return branchTestPtr(Zero, reg, tagMaskRegister);
#else
- return jz32(reg, Imm32(JSImmediate::TagMask));
+ return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask));
#endif
}
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- return jnzPtr(reg, tagMaskRegister);
+#if USE(JSVALUE64)
+ return branchTestPtr(NonZero, reg, tagMaskRegister);
#else
- return jnz32(reg, Imm32(JSImmediate::TagMask));
+ return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask));
#endif
}
emitJumpSlowCaseIfNotJSCell(reg);
}
-ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
-{
- if (!m_codeBlock->isKnownNotImmediate(vReg))
- linkSlowCase(iter);
-}
-
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg)
{
- return jnzPtr(reg, tagTypeNumberRegister);
+ return branchTestPtr(NonZero, reg, tagTypeNumberRegister);
}
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg)
{
- return jzPtr(reg, tagTypeNumberRegister);
+ return branchTestPtr(Zero, reg, tagTypeNumberRegister);
}
#endif
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- return jaePtr(reg, tagTypeNumberRegister);
+#if USE(JSVALUE64)
+ return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister);
#else
- return jnz32(reg, Imm32(JSImmediate::TagTypeNumber));
+ return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber));
#endif
}
ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
- return jbPtr(reg, tagTypeNumberRegister);
+#if USE(JSVALUE64)
+ return branchPtr(Below, reg, tagTypeNumberRegister);
#else
- return jz32(reg, Imm32(JSImmediate::TagTypeNumber));
+ return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber));
#endif
}
addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
}
-#if !USE(ALTERNATE_JSIMMEDIATE)
+#if !USE(JSVALUE64)
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);
+ return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg);
}
#endif
ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
emitFastArithIntToImmNoCheck(src, dest);
#else
if (src != dest)
ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
UNUSED_PARAM(reg);
#else
rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
// 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 USE(JSVALUE64)
if (src != dest)
move(src, dest);
orPtr(tagTypeNumberRegister, dest);
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));
-}
+/* Deprecated: Please use JITStubCall instead. */
-ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
+// 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)
{
- ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ JSValue value = m_codeBlock->getConstant(src);
+ emitPutJITStubArgConstant(JSValue::encode(value), argumentNumber);
+ } else {
+ loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
+ emitPutJITStubArg(scratch, argumentNumber);
+ }
- m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));
+ killLastResultRegister();
}
-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.
+#endif // USE(JSVALUE32_64)
- jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);
-}
-
-}
+} // namespace JSC
#endif // ENABLE(JIT)
--- /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 "JIT.h"
+
+#if ENABLE(JIT)
+
+#include "JITInlineMethods.h"
+#include "JITStubCall.h"
+#include "JSArray.h"
+#include "JSCell.h"
+#include "JSFunction.h"
+#include "LinkBuffer.h"
+
+namespace JSC {
+
+#if USE(JSVALUE32_64)
+
+void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
+{
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ // (1) This function provides fast property access for string length
+ Label stringLengthBegin = align();
+
+ // regT0 holds payload, regT1 holds tag
+
+ Jump string_failureCases1 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+ Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
+
+ // Checks out okay! - get the length from the Ustring.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT2);
+ load32(Address(regT2, OBJECT_OFFSETOF(UString::Rep, len)), regT2);
+
+ Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
+ move(regT2, regT0);
+ move(Imm32(JSValue::Int32Tag), regT1);
+
+ ret();
+#endif
+
+ // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
+
+#if ENABLE(JIT_OPTIMIZE_CALL)
+ /* VirtualCallPreLink Trampoline */
+ Label virtualCallPreLinkBegin = align();
+
+ // regT0 holds callee, regT1 holds argCount.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
+ Jump hasCodeBlock1 = branchTestPtr(NonZero, regT2);
+
+ // Lazily generate a CodeBlock.
+ preserveReturnAddressAfterCall(regT3); // return address
+ restoreArgumentReference();
+ Call callJSFunction1 = call();
+ move(regT0, regT2);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+ hasCodeBlock1.link(this);
+
+ // regT2 holds codeBlock.
+ Jump isNativeFunc1 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay1 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 3); // return address
+ emitPutJITStubArg(regT2, 7); // codeBlock
+ restoreArgumentReference();
+ Call callArityCheck1 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+
+ arityCheckOkay1.link(this);
+ isNativeFunc1.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 3);
+ restoreArgumentReference();
+ Call callDontLazyLinkCall = call();
+ restoreReturnAddressBeforeReturn(regT3);
+ jump(regT0);
+
+ /* VirtualCallLink Trampoline */
+ Label virtualCallLinkBegin = align();
+
+ // regT0 holds callee, regT1 holds argCount.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
+ Jump hasCodeBlock2 = branchTestPtr(NonZero, regT2);
+
+ // Lazily generate a CodeBlock.
+ preserveReturnAddressAfterCall(regT3); // return address
+ restoreArgumentReference();
+ Call callJSFunction2 = call();
+ move(regT0, regT2);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+ hasCodeBlock2.link(this);
+
+ // regT2 holds codeBlock.
+ Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 3); // return address
+ emitPutJITStubArg(regT2, 7); // codeBlock
+ restoreArgumentReference();
+ Call callArityCheck2 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+
+ arityCheckOkay2.link(this);
+ isNativeFunc2.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 3);
+ restoreArgumentReference();
+ Call callLazyLinkCall = call();
+ restoreReturnAddressBeforeReturn(regT3);
+ jump(regT0);
+#endif // ENABLE(JIT_OPTIMIZE_CALL)
+
+ /* VirtualCall Trampoline */
+ Label virtualCallBegin = align();
+
+ // regT0 holds callee, regT1 holds argCount.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
+ Jump hasCodeBlock3 = branchTestPtr(NonZero, regT2);
+
+ // Lazily generate a CodeBlock.
+ preserveReturnAddressAfterCall(regT3); // return address
+ restoreArgumentReference();
+ Call callJSFunction3 = call();
+ move(regT0, regT2);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+ hasCodeBlock3.link(this);
+
+ // regT2 holds codeBlock.
+ Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee.
+ Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 3); // return address
+ emitPutJITStubArg(regT2, 7); // codeBlock
+ restoreArgumentReference();
+ Call callArityCheck3 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT0); // callee
+ emitGetJITStubArg(5, regT1); // argCount
+ restoreReturnAddressBeforeReturn(regT3); // return address
+
+ arityCheckOkay3.link(this);
+ isNativeFunc3.link(this);
+ compileOpCallInitializeCallFrame();
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT0);
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(FunctionBodyNode, m_jitCode)), regT0);
+ jump(regT0);
+
+#if PLATFORM(X86)
+ Label nativeCallThunk = align();
+ preserveReturnAddressAfterCall(regT0);
+ emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
+
+ // Load caller frame's scope chain into this callframe so that whatever we call can
+ // get to its global data.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
+ emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+ emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+
+ /* We have two structs that we use to describe the stackframe we set up for our
+ * call to native code. NativeCallFrameStructure describes the how we set up the stack
+ * in advance of the call. NativeFunctionCalleeSignature describes the callframe
+ * as the native code expects it. We do this as we are using the fastcall calling
+ * convention which results in the callee popping its arguments off the stack, but
+ * not the rest of the callframe so we need a nice way to ensure we increment the
+ * stack pointer by the right amount after the call.
+ */
+
+#if COMPILER(MSVC) || PLATFORM(LINUX)
+#if COMPILER(MSVC)
+#pragma pack(push)
+#pragma pack(4)
+#endif // COMPILER(MSVC)
+ struct NativeCallFrameStructure {
+ // CallFrame* callFrame; // passed in EDX
+ JSObject* callee;
+ JSValue thisValue;
+ ArgList* argPointer;
+ ArgList args;
+ JSValue result;
+ };
+ struct NativeFunctionCalleeSignature {
+ JSObject* callee;
+ JSValue thisValue;
+ ArgList* argPointer;
+ };
+#if COMPILER(MSVC)
+#pragma pack(pop)
+#endif // COMPILER(MSVC)
+#else
+ struct NativeCallFrameStructure {
+ // CallFrame* callFrame; // passed in ECX
+ // JSObject* callee; // passed in EDX
+ JSValue thisValue;
+ ArgList* argPointer;
+ ArgList args;
+ };
+ struct NativeFunctionCalleeSignature {
+ JSValue thisValue;
+ ArgList* argPointer;
+ };
+#endif
+
+ const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
+ // Allocate system stack frame
+ subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
+
+ // Set up arguments
+ subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+
+ // push argcount
+ storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
+
+ // Calculate the start of the callframe header, and store in regT1
+ addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
+
+ // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
+ mul32(Imm32(sizeof(Register)), regT0, regT0);
+ subPtr(regT0, regT1);
+ storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
+
+ // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
+ addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
+ storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
+
+ // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
+ loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
+ loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT3);
+ storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+
+#if COMPILER(MSVC) || PLATFORM(LINUX)
+ // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
+ addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86::ecx);
+
+ // Plant callee
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::eax);
+ storePtr(X86::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+
+ // Plant callframe
+ move(callFrameRegister, X86::edx);
+
+ call(Address(X86::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+
+ // JSValue is a non-POD type, so eax points to it
+ emitLoad(0, regT1, regT0, X86::eax);
+#else
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::edx); // callee
+ move(callFrameRegister, X86::ecx); // callFrame
+ call(Address(X86::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
+#endif
+
+ // We've put a few temporaries on the stack in addition to the actual arguments
+ // so pull them off now
+ addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
+
+ // Check for an exception
+ // FIXME: Maybe we can optimize this comparison to JSValue().
+ move(ImmPtr(&globalData->exception), regT2);
+ Jump sawException1 = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::CellTag));
+ Jump sawException2 = branch32(NonZero, payloadFor(0, regT2), Imm32(0));
+
+ // Grab the return address.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT3);
+
+ // Restore our caller's "r".
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+ // Return.
+ restoreReturnAddressBeforeReturn(regT3);
+ ret();
+
+ // Handle an exception
+ sawException1.link(this);
+ sawException2.link(this);
+ // Grab the return address.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+ move(ImmPtr(&globalData->exceptionLocation), regT2);
+ storePtr(regT1, regT2);
+ move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+ restoreReturnAddressBeforeReturn(regT2);
+ ret();
+
+#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
+#else
+ breakpoint();
+#endif
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
+ Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
+ Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
+#endif
+
+ // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
+ LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
+ patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
+ patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
+ patchBuffer.link(callDontLazyLinkCall, FunctionPtr(cti_vm_dontLazyLinkCall));
+ patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
+#endif
+ patchBuffer.link(callArityCheck3, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callJSFunction3, FunctionPtr(cti_op_call_JSFunction));
+
+ CodeRef finalCode = patchBuffer.finalizeCode();
+ *executablePool = finalCode.m_executablePool;
+
+ *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
+ *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
+#else
+ UNUSED_PARAM(ctiStringLengthTrampoline);
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
+ *ctiVirtualCallPreLink = trampolineAt(finalCode, virtualCallPreLinkBegin);
+ *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
+#else
+ UNUSED_PARAM(ctiVirtualCallPreLink);
+ UNUSED_PARAM(ctiVirtualCallLink);
+#endif
+}
+
+void JIT::emit_op_mov(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ if (m_codeBlock->isConstantRegisterIndex(src))
+ emitStore(dst, getConstantOperand(src));
+ else {
+ emitLoad(src, regT1, regT0);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_mov), dst, regT1, regT0);
+ }
+}
+
+void JIT::emit_op_end(Instruction* currentInstruction)
+{
+ if (m_codeBlock->needsFullScopeChain())
+ JITStubCall(this, cti_op_end).call();
+ ASSERT(returnValueRegister != callFrameRegister);
+ emitLoad(currentInstruction[1].u.operand, regT1, regT0);
+ restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
+ ret();
+}
+
+void JIT::emit_op_jmp(Instruction* currentInstruction)
+{
+ unsigned target = currentInstruction[1].u.operand;
+ addJump(jump(), target + 1);
+}
+
+void JIT::emit_op_loop(Instruction* currentInstruction)
+{
+ unsigned target = currentInstruction[1].u.operand;
+ emitTimeoutCheck();
+ addJump(jump(), target + 1);
+}
+
+void JIT::emit_op_loop_if_less(Instruction* currentInstruction)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ emitTimeoutCheck();
+
+ if (isOperandConstantImmediateInt(op1)) {
+ emitLoad(op2, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+ return;
+ }
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThan, regT0, regT2), target + 3);
+}
+
+void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_loop_if_less);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+}
+
+void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ emitTimeoutCheck();
+
+ if (isOperandConstantImmediateInt(op1)) {
+ emitLoad(op2, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+ return;
+ }
+
+ if (isOperandConstantImmediateInt(op2)) {
+ emitLoad(op1, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+ return;
+ }
+
+ emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ addJump(branch32(LessThanOrEqual, regT0, regT2), target + 3);
+}
+
+void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+
+ if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+ linkSlowCase(iter); // int32 check
+ linkSlowCase(iter); // int32 check
+
+ JITStubCall stubCall(this, cti_op_loop_if_lesseq);
+ stubCall.addArgument(op1);
+ stubCall.addArgument(op2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+}
+
+void JIT::emit_op_new_object(Instruction* currentInstruction)
+{
+ JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_instanceof(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned value = currentInstruction[2].u.operand;
+ unsigned baseVal = currentInstruction[3].u.operand;
+ unsigned proto = currentInstruction[4].u.operand;
+
+ // Load the operands (baseVal, proto, and value respectively) into registers.
+ // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
+ emitLoadPayload(proto, regT1);
+ emitLoadPayload(baseVal, regT0);
+ emitLoadPayload(value, regT2);
+
+ // Check that baseVal & proto are cells.
+ emitJumpSlowCaseIfNotJSCell(proto);
+ emitJumpSlowCaseIfNotJSCell(baseVal);
+
+ // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); // FIXME: Maybe remove this test.
+ addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance))); // FIXME: TOT checks ImplementsDefaultHasInstance.
+
+ // If value is not an Object, return false.
+ emitLoadTag(value, regT0);
+ Jump valueIsImmediate = branch32(NotEqual, regT0, Imm32(JSValue::CellTag));
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); // FIXME: Maybe remove this test.
+
+ // Check proto is object.
+ loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+
+ // Optimistically load the result true, and start looping.
+ // Initially, regT1 still contains proto and regT2 still contains value.
+ // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
+ move(Imm32(JSValue::TrueTag), regT0);
+ Label loop(this);
+
+ // Load the prototype of the object in regT2. If this is equal to regT1 - WIN!
+ // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
+ Jump isInstance = branchPtr(Equal, regT2, regT1);
+ branch32(NotEqual, regT2, Imm32(0), loop);
+
+ // We get here either by dropping out of the loop, or if value was not an Object. Result is false.
+ valueIsImmediate.link(this);
+ valueIsNotObject.link(this);
+ move(Imm32(JSValue::FalseTag), regT0);
+
+ // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
+ isInstance.link(this);
+ emitStoreBool(dst, regT0);
+}
+
+void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned value = currentInstruction[2].u.operand;
+ unsigned baseVal = currentInstruction[3].u.operand;
+ unsigned proto = currentInstruction[4].u.operand;
+
+ linkSlowCaseIfNotJSCell(iter, baseVal);
+ linkSlowCaseIfNotJSCell(iter, proto);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_instanceof);
+ stubCall.addArgument(value);
+ stubCall.addArgument(baseVal);
+ stubCall.addArgument(proto);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_new_func(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_func);
+ stubCall.addArgument(ImmPtr(m_codeBlock->function(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[2].u.jsCell);
+ ASSERT(globalObject->isGlobalObject());
+ int index = currentInstruction[3].u.operand;
+
+ loadPtr(&globalObject->d()->registers, regT2);
+
+ emitLoad(index, regT1, regT0, regT2);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
+}
+
+void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+{
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[1].u.jsCell);
+ ASSERT(globalObject->isGlobalObject());
+ int index = currentInstruction[2].u.operand;
+ int value = currentInstruction[3].u.operand;
+
+ emitLoad(value, regT1, regT0);
+
+ loadPtr(&globalObject->d()->registers, regT2);
+ emitStore(index, regT1, regT0, regT2);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
+}
+
+void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int index = currentInstruction[2].u.operand;
+ int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+ while (skip--)
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
+
+ emitLoad(index, regT1, regT0, regT2);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
+}
+
+void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+{
+ int index = currentInstruction[1].u.operand;
+ int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
+ int value = currentInstruction[3].u.operand;
+
+ emitLoad(value, regT1, regT0);
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+ while (skip--)
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
+
+ emitStore(index, regT1, regT0, regT2);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
+}
+
+void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_tear_off_activation);
+ stubCall.addArgument(currentInstruction[1].u.operand);
+ stubCall.call();
+}
+
+void JIT::emit_op_tear_off_arguments(Instruction*)
+{
+ JITStubCall(this, cti_op_tear_off_arguments).call();
+}
+
+void JIT::emit_op_new_array(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_array);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_to_primitive(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+
+ Jump isImm = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+ isImm.link(this);
+
+ if (dst != src)
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_to_primitive), dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int dst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_to_primitive);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_strcat(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_strcat);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitTimeoutCheck();
+
+ emitLoad(cond, regT1, regT0);
+
+ Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ addJump(branch32(NotEqual, regT0, Imm32(0)), target + 2);
+ Jump isNotZero = jump();
+
+ isNotInteger.link(this);
+
+ addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2);
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::FalseTag)));
+
+ isNotZero.link(this);
+}
+
+void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(cond);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2);
+}
+
+void JIT::emit_op_resolve_base(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_skip);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve_global(Instruction* currentInstruction)
+{
+ // FIXME: Optimize to use patching instead of so many memory accesses.
+
+ unsigned dst = currentInstruction[1].u.operand;
+ void* globalObject = currentInstruction[2].u.jsCell;
+
+ unsigned currentIndex = m_globalResolveInfoIndex++;
+ void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
+ void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
+
+ // Verify structure.
+ move(ImmPtr(globalObject), regT0);
+ loadPtr(structureAddress, regT1);
+ addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))));
+
+ // Load property.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT2);
+ load32(offsetAddr, regT3);
+ load32(BaseIndex(regT2, regT3, TimesEight), regT0); // payload
+ load32(BaseIndex(regT2, regT3, TimesEight, 4), regT1); // tag
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_resolve_global), dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ void* globalObject = currentInstruction[2].u.jsCell;
+ Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
+
+ unsigned currentIndex = m_globalResolveInfoIndex++;
+
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_resolve_global);
+ stubCall.addArgument(ImmPtr(globalObject));
+ stubCall.addArgument(ImmPtr(ident));
+ stubCall.addArgument(Imm32(currentIndex));
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_not(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ emitLoadTag(src, regT0);
+
+ xor32(Imm32(JSValue::FalseTag), regT0);
+ addSlowCase(branchTest32(NonZero, regT0, Imm32(~1)));
+ xor32(Imm32(JSValue::TrueTag), regT0);
+
+ emitStoreBool(dst, regT0, (dst == src));
+}
+
+void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_not);
+ stubCall.addArgument(src);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_jfalse(Instruction* currentInstruction)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitLoad(cond, regT1, regT0);
+
+ Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
+ addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target + 2);
+
+ Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
+ addJump(jump(), target + 2);
+
+ if (supportsFloatingPoint()) {
+ isNotInteger.link(this);
+
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+
+ zeroDouble(fpRegT0);
+ emitLoadDouble(cond, fpRegT1);
+ addJump(branchDouble(DoubleEqual, fpRegT0, fpRegT1), target + 2);
+ } else
+ addSlowCase(isNotInteger);
+
+ isTrue.link(this);
+ isTrue2.link(this);
+}
+
+void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(cond);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), target + 2); // Inverted.
+}
+
+void JIT::emit_op_jtrue(Instruction* currentInstruction)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitLoad(cond, regT1, regT0);
+
+ Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag));
+ addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2);
+
+ Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+ Jump isFalse2 = branch32(Equal, regT0, Imm32(0));
+ addJump(jump(), target + 2);
+
+ if (supportsFloatingPoint()) {
+ isNotInteger.link(this);
+
+ addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+
+ zeroDouble(fpRegT0);
+ emitLoadDouble(cond, fpRegT1);
+ addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target + 2);
+ } else
+ addSlowCase(isNotInteger);
+
+ isFalse.link(this);
+ isFalse2.link(this);
+}
+
+void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned cond = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(cond);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2);
+}
+
+void JIT::emit_op_jeq_null(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+
+ Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+
+ Jump wasNotImmediate = jump();
+
+ // Now handle the immediate cases - undefined & null
+ isImmediate.link(this);
+
+ set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
+ set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
+ or32(regT2, regT1);
+
+ addJump(branchTest32(NonZero, regT1), target + 2);
+
+ wasNotImmediate.link(this);
+}
+
+void JIT::emit_op_jneq_null(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+
+ Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+
+ Jump wasNotImmediate = jump();
+
+ // Now handle the immediate cases - undefined & null
+ isImmediate.link(this);
+
+ set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
+ set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
+ or32(regT2, regT1);
+
+ addJump(branchTest32(Zero, regT1), target + 2);
+
+ wasNotImmediate.link(this);
+}
+
+void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ JSCell* ptr = currentInstruction[2].u.jsCell;
+ unsigned target = currentInstruction[3].u.operand;
+
+ emitLoad(src, regT1, regT0);
+ addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target + 3);
+ addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target + 3);
+}
+
+void JIT::emit_op_jsr(Instruction* currentInstruction)
+{
+ int retAddrDst = currentInstruction[1].u.operand;
+ int target = currentInstruction[2].u.operand;
+ DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
+ addJump(jump(), target + 2);
+ m_jsrSites.append(JSRInfo(storeLocation, label()));
+}
+
+void JIT::emit_op_sret(Instruction* currentInstruction)
+{
+ jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
+}
+
+void JIT::emit_op_eq(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+ unsigned src2 = currentInstruction[3].u.operand;
+
+ emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, regT3));
+ addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
+ addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
+
+ set8(Equal, regT0, regT2, regT0);
+ or32(Imm32(JSValue::FalseTag), regT0);
+
+ emitStoreBool(dst, regT0);
+}
+
+void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned op1 = currentInstruction[2].u.operand;
+ unsigned op2 = currentInstruction[3].u.operand;
+
+ JumpList storeResult;
+ JumpList genericCase;
+
+ genericCase.append(getSlowCase(iter)); // tags not equal
+
+ linkSlowCase(iter); // tags equal and JSCell
+ genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+ genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
+
+ // String case.
+ JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
+ stubCallEqStrings.addArgument(regT0);
+ stubCallEqStrings.addArgument(regT2);
+ stubCallEqStrings.call();
+ storeResult.append(jump());
+
+ // Generic case.
+ genericCase.append(getSlowCase(iter)); // doubles
+ genericCase.link(this);
+ JITStubCall stubCallEq(this, cti_op_eq);
+ stubCallEq.addArgument(op1);
+ stubCallEq.addArgument(op2);
+ stubCallEq.call(regT0);
+
+ storeResult.link(this);
+ or32(Imm32(JSValue::FalseTag), regT0);
+ emitStoreBool(dst, regT0);
+}
+
+void JIT::emit_op_neq(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+ unsigned src2 = currentInstruction[3].u.operand;
+
+ emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
+ addSlowCase(branch32(NotEqual, regT1, regT3));
+ addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
+ addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
+
+ set8(NotEqual, regT0, regT2, regT0);
+ or32(Imm32(JSValue::FalseTag), regT0);
+
+ emitStoreBool(dst, regT0);
+}
+
+void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+
+ JumpList storeResult;
+ JumpList genericCase;
+
+ genericCase.append(getSlowCase(iter)); // tags not equal
+
+ linkSlowCase(iter); // tags equal and JSCell
+ genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+ genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
+
+ // String case.
+ JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
+ stubCallEqStrings.addArgument(regT0);
+ stubCallEqStrings.addArgument(regT2);
+ stubCallEqStrings.call(regT0);
+ storeResult.append(jump());
+
+ // Generic case.
+ genericCase.append(getSlowCase(iter)); // doubles
+ genericCase.link(this);
+ JITStubCall stubCallEq(this, cti_op_eq);
+ stubCallEq.addArgument(regT1, regT0);
+ stubCallEq.addArgument(regT3, regT2);
+ stubCallEq.call(regT0);
+
+ storeResult.link(this);
+ xor32(Imm32(0x1), regT0);
+ or32(Imm32(JSValue::FalseTag), regT0);
+ emitStoreBool(dst, regT0);
+}
+
+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;
+
+ emitLoadTag(src1, regT0);
+ emitLoadTag(src2, regT1);
+
+ // Jump to a slow case if either operand is double, or if both operands are
+ // cells and/or Int32s.
+ move(regT0, regT2);
+ and32(regT1, regT2);
+ addSlowCase(branch32(Below, regT2, Imm32(JSValue::LowestTag)));
+ addSlowCase(branch32(AboveOrEqual, regT2, Imm32(JSValue::CellTag)));
+
+ if (type == OpStrictEq)
+ set8(Equal, regT0, regT1, regT0);
+ else
+ set8(NotEqual, regT0, regT1, regT0);
+
+ or32(Imm32(JSValue::FalseTag), regT0);
+
+ emitStoreBool(dst, regT0);
+}
+
+void JIT::emit_op_stricteq(Instruction* currentInstruction)
+{
+ compileOpStrictEq(currentInstruction, OpStrictEq);
+}
+
+void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+ unsigned src2 = currentInstruction[3].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_stricteq);
+ stubCall.addArgument(src1);
+ stubCall.addArgument(src2);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_nstricteq(Instruction* currentInstruction)
+{
+ compileOpStrictEq(currentInstruction, OpNStrictEq);
+}
+
+void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+ unsigned src2 = currentInstruction[3].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_nstricteq);
+ stubCall.addArgument(src1);
+ stubCall.addArgument(src2);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_eq_null(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+ Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
+ setTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ set8(Equal, regT1, Imm32(JSValue::NullTag), regT2);
+ set8(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
+ or32(regT2, regT1);
+
+ wasNotImmediate.link(this);
+
+ or32(Imm32(JSValue::FalseTag), regT1);
+
+ emitStoreBool(dst, regT1);
+}
+
+void JIT::emit_op_neq_null(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+ Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
+ setTest8(Zero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ set8(NotEqual, regT1, Imm32(JSValue::NullTag), regT2);
+ set8(NotEqual, regT1, Imm32(JSValue::UndefinedTag), regT1);
+ and32(regT2, regT1);
+
+ wasNotImmediate.link(this);
+
+ or32(Imm32(JSValue::FalseTag), regT1);
+
+ emitStoreBool(dst, regT1);
+}
+
+void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_with_base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.call(currentInstruction[2].u.operand);
+}
+
+void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_func_exp);
+ stubCall.addArgument(ImmPtr(m_codeBlock->functionExpression(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_new_regexp(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_regexp);
+ stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_throw(Instruction* currentInstruction)
+{
+ unsigned exception = currentInstruction[1].u.operand;
+ JITStubCall stubCall(this, cti_op_throw);
+ stubCall.addArgument(exception);
+ stubCall.call();
+
+#ifndef NDEBUG
+ // cti_op_throw always changes it's return address,
+ // this point in the code should never be reached.
+ breakpoint();
+#endif
+}
+
+void JIT::emit_op_next_pname(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int iter = currentInstruction[2].u.operand;
+ int target = currentInstruction[3].u.operand;
+
+ load32(Address(callFrameRegister, (iter * sizeof(Register))), regT0);
+
+ JITStubCall stubCall(this, cti_op_next_pname);
+ stubCall.addArgument(regT0);
+ stubCall.call();
+
+ Jump endOfIter = branchTestPtr(Zero, regT0);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_next_pname), dst, regT1, regT0);
+ addJump(jump(), target + 3);
+ endOfIter.link(this);
+}
+
+void JIT::emit_op_push_scope(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_push_scope);
+ stubCall.addArgument(currentInstruction[1].u.operand);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_pop_scope(Instruction*)
+{
+ JITStubCall(this, cti_op_pop_scope).call();
+}
+
+void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int src = currentInstruction[2].u.operand;
+
+ emitLoad(src, regT1, regT0);
+
+ Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
+ addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::DeletedValueTag)));
+ isInt32.link(this);
+
+ if (src != dst)
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_to_jsnumber), dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int dst = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_to_jsnumber);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_push_new_scope);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(currentInstruction[3].u.operand);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_catch(Instruction* currentInstruction)
+{
+ unsigned exception = currentInstruction[1].u.operand;
+
+ // This opcode only executes after a return from cti_op_throw.
+
+ // cti_op_throw may have taken us to a call frame further up the stack; reload
+ // the call frame pointer to adjust.
+ peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+
+ // Now store the exception returned by cti_op_throw.
+ emitStore(exception, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_catch), exception, regT1, regT0);
+}
+
+void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_jmp_scopes);
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.call();
+ addJump(jump(), currentInstruction[2].u.operand + 2);
+}
+
+void JIT::emit_op_switch_imm(Instruction* currentInstruction)
+{
+ 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());
+
+ JITStubCall stubCall(this, cti_op_switch_imm);
+ stubCall.addArgument(scrutinee);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_switch_char(Instruction* currentInstruction)
+{
+ 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());
+
+ JITStubCall stubCall(this, cti_op_switch_char);
+ stubCall.addArgument(scrutinee);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_switch_string(Instruction* currentInstruction)
+{
+ 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));
+
+ JITStubCall stubCall(this, cti_op_switch_string);
+ stubCall.addArgument(scrutinee);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_new_error(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned type = currentInstruction[2].u.operand;
+ unsigned message = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_new_error);
+ stubCall.addArgument(Imm32(type));
+ stubCall.addArgument(m_codeBlock->getConstant(message));
+ stubCall.addArgument(Imm32(m_bytecodeIndex));
+ stubCall.call(dst);
+}
+
+void JIT::emit_op_debug(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_debug);
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call();
+}
+
+
+void JIT::emit_op_enter(Instruction*)
+{
+ // Even though JIT code doesn't use them, we initialize our constant
+ // registers to zap stale pointers, to avoid unnecessarily prolonging
+ // object lifetime and increasing GC pressure.
+ for (int i = 0; i < m_codeBlock->m_numVars; ++i)
+ emitStore(i, jsUndefined());
+}
+
+void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+{
+ emit_op_enter(currentInstruction);
+
+ JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_create_arguments(Instruction*)
+{
+ Jump argsNotCell = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::CellTag));
+ Jump argsNotNull = branchTestPtr(NonZero, payloadFor(RegisterFile::ArgumentsRegister, callFrameRegister));
+
+ // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
+ if (m_codeBlock->m_numParameters == 1)
+ JITStubCall(this, cti_op_create_arguments_no_params).call();
+ else
+ JITStubCall(this, cti_op_create_arguments).call();
+
+ argsNotCell.link(this);
+ argsNotNull.link(this);
+}
+
+void JIT::emit_op_init_arguments(Instruction*)
+{
+ emitStore(RegisterFile::ArgumentsRegister, JSValue(), callFrameRegister);
+}
+
+void JIT::emit_op_convert_this(Instruction* currentInstruction)
+{
+ unsigned thisRegister = currentInstruction[1].u.operand;
+
+ emitLoad(thisRegister, regT1, regT0);
+
+ addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addSlowCase(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
+
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
+}
+
+void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned thisRegister = currentInstruction[1].u.operand;
+
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_convert_this);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.call(thisRegister);
+}
+
+void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+{
+ peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ Jump noProfiler = branchTestPtr(Zero, Address(regT2));
+
+ JITStubCall stubCall(this, cti_op_profile_will_call);
+ stubCall.addArgument(currentInstruction[1].u.operand);
+ stubCall.call();
+ noProfiler.link(this);
+}
+
+void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+{
+ peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ Jump noProfiler = branchTestPtr(Zero, Address(regT2));
+
+ JITStubCall stubCall(this, cti_op_profile_did_call);
+ stubCall.addArgument(currentInstruction[1].u.operand);
+ stubCall.call();
+ noProfiler.link(this);
+}
+
+#else // USE(JSVALUE32_64)
+
+#define RECORD_JUMP_TARGET(targetOffset) \
+ do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)
+
+void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
+{
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ // (2) The second function provides fast property access for string length
+ Label stringLengthBegin = align();
+
+ // Check eax is a string
+ Jump string_failureCases1 = emitJumpIfNotJSCell(regT0);
+ Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
+
+ // Checks out okay! - get the length from the Ustring.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT0);
+ load32(Address(regT0, OBJECT_OFFSETOF(UString::Rep, len)), regT0);
+
+ Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
+
+ // regT0 contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
+ emitFastArithIntToImmNoCheck(regT0, regT0);
+
+ ret();
+#endif
+
+ // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
+ COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
+
+ Label virtualCallPreLinkBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
+ loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
+ Jump hasCodeBlock1 = branchTestPtr(NonZero, regT0);
+ preserveReturnAddressAfterCall(regT3);
+ restoreArgumentReference();
+ Call callJSFunction1 = call();
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ hasCodeBlock1.link(this);
+
+ Jump isNativeFunc1 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay1 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 2);
+ emitPutJITStubArg(regT0, 4);
+ restoreArgumentReference();
+ Call callArityCheck1 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ arityCheckOkay1.link(this);
+ isNativeFunc1.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 2);
+ restoreArgumentReference();
+ Call callDontLazyLinkCall = call();
+ emitGetJITStubArg(1, regT2);
+ restoreReturnAddressBeforeReturn(regT3);
+
+ jump(regT0);
+
+ Label virtualCallLinkBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
+ loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
+ Jump hasCodeBlock2 = branchTestPtr(NonZero, regT0);
+ preserveReturnAddressAfterCall(regT3);
+ restoreArgumentReference();
+ Call callJSFunction2 = call();
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ hasCodeBlock2.link(this);
+
+ Jump isNativeFunc2 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay2 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 2);
+ emitPutJITStubArg(regT0, 4);
+ restoreArgumentReference();
+ Call callArityCheck2 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ arityCheckOkay2.link(this);
+ isNativeFunc2.link(this);
+
+ compileOpCallInitializeCallFrame();
+
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 2);
+ restoreArgumentReference();
+ Call callLazyLinkCall = call();
+ restoreReturnAddressBeforeReturn(regT3);
+
+ jump(regT0);
+
+ Label virtualCallBegin = align();
+
+ // Load the callee CodeBlock* into eax
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
+ loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
+ Jump hasCodeBlock3 = branchTestPtr(NonZero, regT0);
+ preserveReturnAddressAfterCall(regT3);
+ restoreArgumentReference();
+ Call callJSFunction3 = call();
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer.
+ hasCodeBlock3.link(this);
+
+ Jump isNativeFunc3 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
+
+ // Check argCount matches callee arity.
+ Jump arityCheckOkay3 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+ preserveReturnAddressAfterCall(regT3);
+ emitPutJITStubArg(regT3, 2);
+ emitPutJITStubArg(regT0, 4);
+ restoreArgumentReference();
+ Call callArityCheck3 = call();
+ move(regT1, callFrameRegister);
+ emitGetJITStubArg(1, regT2);
+ emitGetJITStubArg(3, regT1);
+ restoreReturnAddressBeforeReturn(regT3);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer.
+ arityCheckOkay3.link(this);
+ isNativeFunc3.link(this);
+
+ // load ctiCode from the new codeBlock.
+ loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_jitCode)), regT0);
+
+ compileOpCallInitializeCallFrame();
+ jump(regT0);
+
+
+ Label nativeCallThunk = align();
+ preserveReturnAddressAfterCall(regT0);
+ emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
+
+ // Load caller frame's scope chain into this callframe so that whatever we call can
+ // get to its global data.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
+ emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+
+#if PLATFORM(X86_64)
+ emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86::ecx);
+
+ // Allocate stack space for our arglist
+ subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+ COMPILE_ASSERT((sizeof(ArgList) & 0xf) == 0, ArgList_should_by_16byte_aligned);
+
+ // Set up arguments
+ subPtr(Imm32(1), X86::ecx); // Don't include 'this' in argcount
+
+ // Push argcount
+ storePtr(X86::ecx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+
+ // Calculate the start of the callframe header, and store in edx
+ addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), callFrameRegister, X86::edx);
+
+ // Calculate start of arguments as callframe header - sizeof(Register) * argcount (ecx)
+ mul32(Imm32(sizeof(Register)), X86::ecx, X86::ecx);
+ subPtr(X86::ecx, X86::edx);
+
+ // push pointer to arguments
+ storePtr(X86::edx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
+
+ // ArgList is passed by reference so is stackPointerRegister
+ move(stackPointerRegister, X86::ecx);
+
+ // edx currently points to the first argument, edx-sizeof(Register) points to 'this'
+ loadPtr(Address(X86::edx, -(int32_t)sizeof(Register)), X86::edx);
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::esi);
+
+ move(callFrameRegister, X86::edi);
+
+ call(Address(X86::esi, OBJECT_OFFSETOF(JSFunction, m_data)));
+
+ addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+#elif PLATFORM(X86)
+ emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+
+ /* We have two structs that we use to describe the stackframe we set up for our
+ * call to native code. NativeCallFrameStructure describes the how we set up the stack
+ * in advance of the call. NativeFunctionCalleeSignature describes the callframe
+ * as the native code expects it. We do this as we are using the fastcall calling
+ * convention which results in the callee popping its arguments off the stack, but
+ * not the rest of the callframe so we need a nice way to ensure we increment the
+ * stack pointer by the right amount after the call.
+ */
+#if COMPILER(MSVC) || PLATFORM(LINUX)
+ struct NativeCallFrameStructure {
+ // CallFrame* callFrame; // passed in EDX
+ JSObject* callee;
+ JSValue thisValue;
+ ArgList* argPointer;
+ ArgList args;
+ JSValue result;
+ };
+ struct NativeFunctionCalleeSignature {
+ JSObject* callee;
+ JSValue thisValue;
+ ArgList* argPointer;
+ };
+#else
+ struct NativeCallFrameStructure {
+ // CallFrame* callFrame; // passed in ECX
+ // JSObject* callee; // passed in EDX
+ JSValue thisValue;
+ ArgList* argPointer;
+ ArgList args;
+ };
+ struct NativeFunctionCalleeSignature {
+ JSValue thisValue;
+ ArgList* argPointer;
+ };
+#endif
+ const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
+ // Allocate system stack frame
+ subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
+
+ // Set up arguments
+ subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+
+ // push argcount
+ storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
+
+ // Calculate the start of the callframe header, and store in regT1
+ addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
+
+ // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
+ mul32(Imm32(sizeof(Register)), regT0, regT0);
+ subPtr(regT0, regT1);
+ storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
+
+ // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
+ addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
+ storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
+
+ // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
+ loadPtr(Address(regT1, -(int)sizeof(Register)), regT1);
+ storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue)));
+
+#if COMPILER(MSVC) || PLATFORM(LINUX)
+ // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
+ addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86::ecx);
+
+ // Plant callee
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::eax);
+ storePtr(X86::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+
+ // Plant callframe
+ move(callFrameRegister, X86::edx);
+
+ call(Address(X86::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+
+ // JSValue is a non-POD type
+ loadPtr(Address(X86::eax), X86::eax);
+#else
+ // Plant callee
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::edx);
+
+ // Plant callframe
+ move(callFrameRegister, X86::ecx);
+ call(Address(X86::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
+#endif
+
+ // We've put a few temporaries on the stack in addition to the actual arguments
+ // so pull them off now
+ addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
+
+#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
+#else
+ breakpoint();
+#endif
+
+ // Check for an exception
+ loadPtr(&(globalData->exception), regT2);
+ Jump exceptionHandler = branchTestPtr(NonZero, regT2);
+
+ // Grab the return address.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+ // Restore our caller's "r".
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+ // Return.
+ restoreReturnAddressBeforeReturn(regT1);
+ ret();
+
+ // Handle an exception
+ exceptionHandler.link(this);
+ // Grab the return address.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+ move(ImmPtr(&globalData->exceptionLocation), regT2);
+ storePtr(regT1, regT2);
+ move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+ restoreReturnAddressBeforeReturn(regT2);
+ ret();
+
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
+ Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
+ Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
+#endif
+
+ // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
+ LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
+ patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
+#endif
+ patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callArityCheck3, FunctionPtr(cti_op_call_arityCheck));
+ patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
+ patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
+ patchBuffer.link(callJSFunction3, FunctionPtr(cti_op_call_JSFunction));
+ patchBuffer.link(callDontLazyLinkCall, FunctionPtr(cti_vm_dontLazyLinkCall));
+ patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
+
+ CodeRef finalCode = patchBuffer.finalizeCode();
+ *executablePool = finalCode.m_executablePool;
+
+ *ctiVirtualCallPreLink = trampolineAt(finalCode, virtualCallPreLinkBegin);
+ *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
+ *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
+ *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+ *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
+#else
+ UNUSED_PARAM(ctiStringLengthTrampoline);
+#endif
+}
+
+void JIT::emit_op_mov(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int src = currentInstruction[2].u.operand;
+
+ if (m_codeBlock->isConstantRegisterIndex(src)) {
+ storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));
+ if (dst == m_lastResultBytecodeRegister)
+ killLastResultRegister();
+ } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) {
+ // If either the src or dst is the cached register go though
+ // get/put registers to make sure we track this correctly.
+ emitGetVirtualRegister(src, regT0);
+ emitPutVirtualRegister(dst);
+ } else {
+ // Perform the copy via regT1; do not disturb any mapping in regT0.
+ loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1);
+ storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register)));
+ }
+}
+
+void JIT::emit_op_end(Instruction* currentInstruction)
+{
+ if (m_codeBlock->needsFullScopeChain())
+ JITStubCall(this, cti_op_end).call();
+ ASSERT(returnValueRegister != callFrameRegister);
+ emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
+ restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
+ ret();
+}
+
+void JIT::emit_op_jmp(Instruction* currentInstruction)
+{
+ unsigned target = currentInstruction[1].u.operand;
+ addJump(jump(), target + 1);
+ RECORD_JUMP_TARGET(target + 1);
+}
+
+void JIT::emit_op_loop(Instruction* currentInstruction)
+{
+ emitTimeoutCheck();
+
+ unsigned target = currentInstruction[1].u.operand;
+ addJump(jump(), target + 1);
+}
+
+void JIT::emit_op_loop_if_less(Instruction* currentInstruction)
+{
+ emitTimeoutCheck();
+
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(branch32(LessThan, regT0, Imm32(op2imm)), target + 3);
+ } else if (isOperandConstantImmediateInt(op1)) {
+ emitGetVirtualRegister(op2, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ int32_t op1imm = getConstantOperandImmediateInt(op1);
+#else
+ int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
+#endif
+ addJump(branch32(GreaterThan, regT0, Imm32(op1imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+ addJump(branch32(LessThan, regT0, regT1), target + 3);
+ }
+}
+
+void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
+{
+ emitTimeoutCheck();
+
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ emitGetVirtualRegister(op1, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+ int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+ addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target + 3);
+ } else {
+ emitGetVirtualRegisters(op1, regT0, op2, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+ addJump(branch32(LessThanOrEqual, regT0, regT1), target + 3);
+ }
+}
+
+void JIT::emit_op_new_object(Instruction* currentInstruction)
+{
+ JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_instanceof(Instruction* currentInstruction)
+{
+ // Load the operands (baseVal, proto, and value respectively) into registers.
+ // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
+ emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+ emitGetVirtualRegister(currentInstruction[4].u.operand, regT1);
+ emitGetVirtualRegister(currentInstruction[2].u.operand, regT2);
+
+ // Check that baseVal & proto are cells.
+ emitJumpSlowCaseIfNotJSCell(regT0);
+ emitJumpSlowCaseIfNotJSCell(regT1);
+
+ // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+ addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
+
+ // If value is not an Object, return false.
+ Jump valueIsImmediate = emitJumpIfNotJSCell(regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType));
+
+ // Check proto is object.
+ loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+ addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+
+ // Optimistically load the result true, and start looping.
+ // Initially, regT1 still contains proto and regT2 still contains value.
+ // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
+ move(ImmPtr(JSValue::encode(jsBoolean(true))), regT0);
+ Label loop(this);
+
+ // Load the prototype of the object in regT2. If this is equal to regT1 - WIN!
+ // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
+ Jump isInstance = branchPtr(Equal, regT2, regT1);
+ branchPtr(NotEqual, regT2, ImmPtr(JSValue::encode(jsNull())), loop);
+
+ // We get here either by dropping out of the loop, or if value was not an Object. Result is false.
+ valueIsImmediate.link(this);
+ valueIsNotObject.link(this);
+ move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0);
+
+ // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
+ isInstance.link(this);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_new_func(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_func);
+ stubCall.addArgument(ImmPtr(m_codeBlock->function(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_call(Instruction* currentInstruction)
+{
+ compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_call_eval(Instruction* currentInstruction)
+{
+ compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_load_varargs(Instruction* currentInstruction)
+{
+ int argCountDst = currentInstruction[1].u.operand;
+ int argsOffset = currentInstruction[2].u.operand;
+
+ JITStubCall stubCall(this, cti_op_load_varargs);
+ stubCall.addArgument(Imm32(argsOffset));
+ stubCall.call();
+ // Stores a naked int32 in the register file.
+ store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
+}
+
+void JIT::emit_op_call_varargs(Instruction* currentInstruction)
+{
+ compileOpCallVarargs(currentInstruction);
+}
+
+void JIT::emit_op_construct(Instruction* currentInstruction)
+{
+ compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+{
+ JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);
+ move(ImmPtr(globalObject), regT0);
+ emitGetVariableObjectRegister(regT0, currentInstruction[3].u.operand, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[3].u.operand, regT1);
+ JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);
+ move(ImmPtr(globalObject), regT0);
+ emitPutVariableObjectRegister(regT1, regT0, currentInstruction[2].u.operand);
+}
+
+void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
+{
+ int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+ while (skip--)
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
+ emitGetVariableObjectRegister(regT0, currentInstruction[2].u.operand, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+{
+ int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
+
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+ while (skip--)
+ loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
+
+ loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
+ emitPutVariableObjectRegister(regT0, regT1, currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_tear_off_activation);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.call();
+}
+
+void JIT::emit_op_tear_off_arguments(Instruction*)
+{
+ JITStubCall(this, cti_op_tear_off_arguments).call();
+}
+
+void JIT::emit_op_ret(Instruction* currentInstruction)
+{
+ // We could JIT generate the deref, only calling out to C when the refcount hits zero.
+ if (m_codeBlock->needsFullScopeChain())
+ JITStubCall(this, cti_op_ret_scopeChain).call();
+
+ ASSERT(callFrameRegister != regT1);
+ ASSERT(regT1 != returnValueRegister);
+ ASSERT(returnValueRegister != callFrameRegister);
+
+ // Return the result in %eax.
+ emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
+
+ // Grab the return address.
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+ // Restore our caller's "r".
+ emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+ // Return.
+ restoreReturnAddressBeforeReturn(regT1);
+ ret();
+}
+
+void JIT::emit_op_new_array(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_array);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_construct_verify(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+
+ emitJumpSlowCaseIfNotJSCell(regT0);
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
+
+}
+
+void JIT::emit_op_to_primitive(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int src = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src, regT0);
+
+ Jump isImm = emitJumpIfNotJSCell(regT0);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+ isImm.link(this);
+
+ if (dst != src)
+ emitPutVirtualRegister(dst);
+
+}
+
+void JIT::emit_op_strcat(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_strcat);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
+{
+ emitTimeoutCheck();
+
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+
+ Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
+ addJump(emitJumpIfImmediateInteger(regT0), target + 2);
+
+ addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);
+ addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
+
+ isZero.link(this);
+};
+void JIT::emit_op_resolve_base(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_skip);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve_global(Instruction* currentInstruction)
+{
+ // Fast case
+ void* globalObject = currentInstruction[2].u.jsCell;
+ Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
+
+ unsigned currentIndex = m_globalResolveInfoIndex++;
+ void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
+ void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
+
+ // Check Structure of global object
+ move(ImmPtr(globalObject), regT0);
+ loadPtr(structureAddress, regT1);
+ Jump noMatch = branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))); // Structures don't match
+
+ // Load cached property
+ // Assume that the global object always uses external storage.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT0);
+ load32(offsetAddr, regT1);
+ loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ Jump end = jump();
+
+ // Slow case
+ noMatch.link(this);
+ JITStubCall stubCall(this, cti_op_resolve_global);
+ stubCall.addArgument(ImmPtr(globalObject));
+ stubCall.addArgument(ImmPtr(ident));
+ stubCall.addArgument(Imm32(currentIndex));
+ stubCall.call(currentInstruction[1].u.operand);
+ end.link(this);
+}
+
+void JIT::emit_op_not(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
+ addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_jfalse(Instruction* currentInstruction)
+{
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+
+ addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target + 2);
+ Jump isNonZero = emitJumpIfImmediateInteger(regT0);
+
+ addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target + 2);
+ addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));
+
+ isNonZero.link(this);
+ RECORD_JUMP_TARGET(target + 2);
+};
+void JIT::emit_op_jeq_null(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src, regT0);
+ Jump isImmediate = emitJumpIfNotJSCell(regT0);
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(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), regT0);
+ addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);
+
+ wasNotImmediate.link(this);
+ RECORD_JUMP_TARGET(target + 2);
+};
+void JIT::emit_op_jneq_null(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ unsigned target = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src, regT0);
+ Jump isImmediate = emitJumpIfNotJSCell(regT0);
+
+ // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(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), regT0);
+ addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);
+
+ wasNotImmediate.link(this);
+ RECORD_JUMP_TARGET(target + 2);
+}
+
+void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
+{
+ unsigned src = currentInstruction[1].u.operand;
+ JSCell* ptr = currentInstruction[2].u.jsCell;
+ unsigned target = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegister(src, regT0);
+ addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target + 3);
+
+ RECORD_JUMP_TARGET(target + 3);
+}
+
+void JIT::emit_op_jsr(Instruction* currentInstruction)
+{
+ int retAddrDst = currentInstruction[1].u.operand;
+ int target = currentInstruction[2].u.operand;
+ DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
+ addJump(jump(), target + 2);
+ m_jsrSites.append(JSRInfo(storeLocation, label()));
+ killLastResultRegister();
+ RECORD_JUMP_TARGET(target + 2);
+}
+
+void JIT::emit_op_sret(Instruction* currentInstruction)
+{
+ jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
+ killLastResultRegister();
+}
+
+void JIT::emit_op_eq(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
+ set32(Equal, regT1, regT0, regT0);
+ emitTagAsBoolImmediate(regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_bitnot(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+ emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+ not32(regT0);
+ emitFastArithIntToImmNoCheck(regT0, regT0);
+#else
+ xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0);
+#endif
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_resolve_with_base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.call(currentInstruction[2].u.operand);
+}
+
+void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_func_exp);
+ stubCall.addArgument(ImmPtr(m_codeBlock->functionExpression(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_jtrue(Instruction* currentInstruction)
+{
+ unsigned target = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+
+ Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
+ addJump(emitJumpIfImmediateInteger(regT0), target + 2);
+
+ addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);
+ addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
+
+ isZero.link(this);
+ RECORD_JUMP_TARGET(target + 2);
+}
+
+void JIT::emit_op_neq(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
+ set32(NotEqual, regT1, regT0, regT0);
+ emitTagAsBoolImmediate(regT0);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+
+}
+
+void JIT::emit_op_bitxor(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
+ xorPtr(regT1, regT0);
+ emitFastArithReTagImmediate(regT0, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_new_regexp(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_regexp);
+ stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_bitor(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
+ orPtr(regT1, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_throw(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_throw);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.call();
+ ASSERT(regT0 == returnValueRegister);
+#ifndef NDEBUG
+ // cti_op_throw always changes it's return address,
+ // this point in the code should never be reached.
+ breakpoint();
+#endif
+}
+
+void JIT::emit_op_next_pname(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_next_pname);
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+ stubCall.call();
+ Jump endOfIter = branchTestPtr(Zero, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ addJump(jump(), currentInstruction[3].u.operand + 3);
+ endOfIter.link(this);
+}
+
+void JIT::emit_op_push_scope(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_push_scope);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_pop_scope(Instruction*)
+{
+ JITStubCall(this, cti_op_pop_scope).call();
+}
+
+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, regT0, src2, regT1);
+
+ // Jump to a slow case if either operand is a number, or if both are JSCell*s.
+ move(regT0, regT2);
+ orPtr(regT1, regT2);
+ addSlowCase(emitJumpIfJSCell(regT2));
+ addSlowCase(emitJumpIfImmediateNumber(regT2));
+
+ if (type == OpStrictEq)
+ set32(Equal, regT1, regT0, regT0);
+ else
+ set32(NotEqual, regT1, regT0, regT0);
+ emitTagAsBoolImmediate(regT0);
+
+ emitPutVirtualRegister(dst);
+}
+
+void JIT::emit_op_stricteq(Instruction* currentInstruction)
+{
+ compileOpStrictEq(currentInstruction, OpStrictEq);
+}
+
+void JIT::emit_op_nstricteq(Instruction* currentInstruction)
+{
+ compileOpStrictEq(currentInstruction, OpNStrictEq);
+}
+
+void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
+{
+ int srcVReg = currentInstruction[2].u.operand;
+ emitGetVirtualRegister(srcVReg, regT0);
+
+ Jump wasImmediate = emitJumpIfImmediateInteger(regT0);
+
+ emitJumpSlowCaseIfNotJSCell(regT0, srcVReg);
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType)));
+
+ wasImmediate.link(this);
+
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_push_new_scope);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_catch(Instruction* currentInstruction)
+{
+ killLastResultRegister(); // FIXME: Implicitly treat op_catch as a labeled statement, and remove this line of code.
+ peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_jmp_scopes);
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.call();
+ addJump(jump(), currentInstruction[2].u.operand + 2);
+ RECORD_JUMP_TARGET(currentInstruction[2].u.operand + 2);
+}
+
+void JIT::emit_op_switch_imm(Instruction* currentInstruction)
+{
+ 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());
+
+ JITStubCall stubCall(this, cti_op_switch_imm);
+ stubCall.addArgument(scrutinee, regT2);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_switch_char(Instruction* currentInstruction)
+{
+ 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());
+
+ JITStubCall stubCall(this, cti_op_switch_char);
+ stubCall.addArgument(scrutinee, regT2);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_switch_string(Instruction* currentInstruction)
+{
+ 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));
+
+ JITStubCall stubCall(this, cti_op_switch_string);
+ stubCall.addArgument(scrutinee, regT2);
+ stubCall.addArgument(Imm32(tableIndex));
+ stubCall.call();
+ jump(regT0);
+}
+
+void JIT::emit_op_new_error(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_new_error);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[3].u.operand))));
+ stubCall.addArgument(Imm32(m_bytecodeIndex));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_debug(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_debug);
+ stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+ stubCall.call();
+}
+
+void JIT::emit_op_eq_null(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src1, regT0);
+ Jump isImmediate = emitJumpIfNotJSCell(regT0);
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ setTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
+ setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
+
+ wasNotImmediate.link(this);
+
+ emitTagAsBoolImmediate(regT0);
+ emitPutVirtualRegister(dst);
+
+}
+
+void JIT::emit_op_neq_null(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned src1 = currentInstruction[2].u.operand;
+
+ emitGetVirtualRegister(src1, regT0);
+ Jump isImmediate = emitJumpIfNotJSCell(regT0);
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ setTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
+
+ Jump wasNotImmediate = jump();
+
+ isImmediate.link(this);
+
+ andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
+ setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
+
+ wasNotImmediate.link(this);
+
+ emitTagAsBoolImmediate(regT0);
+ emitPutVirtualRegister(dst);
+
+}
+
+void JIT::emit_op_enter(Instruction*)
+{
+ // 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;
+ for (size_t j = 0; j < count; ++j)
+ emitInitRegister(j);
+
+}
+
+void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+{
+ // 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;
+ for (size_t j = 0; j < count; ++j)
+ emitInitRegister(j);
+
+ JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_create_arguments(Instruction*)
+{
+ Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
+ if (m_codeBlock->m_numParameters == 1)
+ JITStubCall(this, cti_op_create_arguments_no_params).call();
+ else
+ JITStubCall(this, cti_op_create_arguments).call();
+ argsCreated.link(this);
+}
+
+void JIT::emit_op_init_arguments(Instruction*)
+{
+ storePtr(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
+}
+
+void JIT::emit_op_convert_this(Instruction* currentInstruction)
+{
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+
+ emitJumpSlowCaseIfNotJSCell(regT0);
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
+ addSlowCase(branchTest32(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
+
+}
+
+void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+{
+ peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ Jump noProfiler = branchTestPtr(Zero, Address(regT1));
+
+ JITStubCall stubCall(this, cti_op_profile_will_call);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT1);
+ stubCall.call();
+ noProfiler.link(this);
+
+}
+
+void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+{
+ peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ Jump noProfiler = branchTestPtr(Zero, Address(regT1));
+
+ JITStubCall stubCall(this, cti_op_profile_did_call);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT1);
+ stubCall.call();
+ noProfiler.link(this);
+}
+
+
+// Slow cases
+
+void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_convert_this);
+ stubCall.addArgument(regT0);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_to_primitive);
+ stubCall.addArgument(regT0);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ // The slow void JIT::emitSlow_that handles accesses to arrays (below) may jump back up to here.
+ Label beginGetByValSlow(this);
+
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitFastArithIntToImmNoCheck(regT1, regT1);
+
+ notImm.link(this);
+ JITStubCall stubCall(this, cti_op_get_by_val);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(currentInstruction[1].u.operand);
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
+
+ // This is slow void JIT::emitSlow_that handles accesses to arrays above the fast cut-off.
+ // First, check if this is an access to the vector
+ linkSlowCase(iter);
+ branch32(AboveOrEqual, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength)), beginGetByValSlow);
+
+ // okay, missed the fast region, but it is still in the vector. Get the value.
+ loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT2);
+ // Check whether the value loaded is zero; if so we need to return undefined.
+ branchTestPtr(Zero, regT2, beginGetByValSlow);
+ move(regT2, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
+}
+
+void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op1 = currentInstruction[1].u.operand;
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_loop_if_less);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(op2, regT2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+ } else if (isOperandConstantImmediateInt(op1)) {
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_loop_if_less);
+ stubCall.addArgument(op1, regT2);
+ stubCall.addArgument(regT0);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_loop_if_less);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+ }
+}
+
+void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned op2 = currentInstruction[2].u.operand;
+ unsigned target = currentInstruction[3].u.operand;
+ if (isOperandConstantImmediateInt(op2)) {
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_loop_if_lesseq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+ } else {
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_loop_if_lesseq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+ }
+}
+
+void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ // Normal slow cases - either is not an immediate imm, or is an array.
+ Jump notImm = getSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ emitFastArithIntToImmNoCheck(regT1, regT1);
+
+ notImm.link(this); {
+ JITStubCall stubCall(this, cti_op_put_by_val);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call();
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val));
+ }
+
+ // slow cases for immediate int accesses to arrays
+ linkSlowCase(iter);
+ linkSlowCase(iter); {
+ JITStubCall stubCall(this, cti_op_put_by_val_array);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call();
+ }
+}
+
+void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(regT0);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2);
+}
+
+void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
+ JITStubCall stubCall(this, cti_op_not);
+ stubCall.addArgument(regT0);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(regT0);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand + 2); // inverted!
+}
+
+void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_bitnot);
+ stubCall.addArgument(regT0);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_jtrue);
+ stubCall.addArgument(regT0);
+ stubCall.call();
+ emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2);
+}
+
+void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_bitxor);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_bitor);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_eq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ emitTagAsBoolImmediate(regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_eq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call();
+ xor32(Imm32(0x1), regT0);
+ emitTagAsBoolImmediate(regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_stricteq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_nstricteq);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_instanceof);
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.addArgument(currentInstruction[4].u.operand, regT2);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
+}
+
+void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
+}
+
+void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallVarargsSlowCase(currentInstruction, iter);
+}
+
+void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
+}
+
+void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_to_jsnumber);
+ stubCall.addArgument(regT0);
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
+#endif // USE(JSVALUE32_64)
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
#include "CodeBlock.h"
#include "JITInlineMethods.h"
+#include "JITStubCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "Interpreter.h"
+#include "LinkBuffer.h"
+#include "RepatchBuffer.h"
#include "ResultType.h"
#include "SamplingTool.h"
namespace JSC {
+#if USE(JSVALUE32_64)
+
+void JIT::emit_op_put_by_index(Instruction* currentInstruction)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned value = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_put_by_index);
+ stubCall.addArgument(base);
+ stubCall.addArgument(Imm32(property));
+ stubCall.addArgument(value);
+ stubCall.call();
+}
+
+void JIT::emit_op_put_getter(Instruction* currentInstruction)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned function = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_put_getter);
+ stubCall.addArgument(base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+ stubCall.addArgument(function);
+ stubCall.call();
+}
+
+void JIT::emit_op_put_setter(Instruction* currentInstruction)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned function = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_put_setter);
+ stubCall.addArgument(base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+ stubCall.addArgument(function);
+ stubCall.call();
+}
+
+void JIT::emit_op_del_by_id(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned base = currentInstruction[2].u.operand;
+ unsigned property = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_del_by_id);
+ stubCall.addArgument(base);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+ stubCall.call(dst);
+}
+
+
#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned)
+/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+
+// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
+void JIT::emit_op_method_check(Instruction*) {}
+void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
+#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+#error "JIT_OPTIMIZE_METHOD_CALLS requires JIT_OPTIMIZE_PROPERTY_ACCESS"
+#endif
+
+void JIT::emit_op_get_by_val(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned base = currentInstruction[2].u.operand;
+ unsigned property = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_get_by_val);
+ stubCall.addArgument(base);
+ stubCall.addArgument(property);
+ stubCall.call(dst);
+}
+
+void JIT::emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::emit_op_put_by_val(Instruction* currentInstruction)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned value = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_put_by_val);
+ stubCall.addArgument(base);
+ stubCall.addArgument(property);
+ stubCall.addArgument(value);
+ stubCall.call();
+}
+
+void JIT::emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::emit_op_get_by_id(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int base = currentInstruction[2].u.operand;
+ int ident = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_get_by_id_generic);
+ stubCall.addArgument(base);
+ stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+ stubCall.call(dst);
+
+ m_propertyAccessInstructionIndex++;
+}
+
+void JIT::emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ m_propertyAccessInstructionIndex++;
+ ASSERT_NOT_REACHED();
+}
+
+void JIT::emit_op_put_by_id(Instruction* currentInstruction)
+{
+ int base = currentInstruction[1].u.operand;
+ int ident = currentInstruction[2].u.operand;
+ int value = currentInstruction[3].u.operand;
+
+ JITStubCall stubCall(this, cti_op_put_by_id_generic);
+ stubCall.addArgument(base);
+ stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+ stubCall.addArgument(value);
+ stubCall.call();
+
+ m_propertyAccessInstructionIndex++;
+}
+
+void JIT::emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
+{
+ m_propertyAccessInstructionIndex++;
+ ASSERT_NOT_REACHED();
+}
+
+#else // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+
+#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+
+void JIT::emit_op_method_check(Instruction* currentInstruction)
+{
+ // Assert that the following instruction is a get_by_id.
+ ASSERT(m_interpreter->getOpcodeID((currentInstruction + OPCODE_LENGTH(op_method_check))->u.opcode) == op_get_by_id);
+
+ currentInstruction += OPCODE_LENGTH(op_method_check);
+
+ // Do the method check - check the object & its prototype's structure inline (this is the common case).
+ m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
+ MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
+
+ int dst = currentInstruction[1].u.operand;
+ int base = currentInstruction[2].u.operand;
+
+ emitLoad(base, regT1, regT0);
+ emitJumpSlowCaseIfNotJSCell(base, regT1);
+
+ Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+ DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2);
+ Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+
+ // This will be relinked to load the function without doing a load.
+ DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+ move(Imm32(JSValue::CellTag), regT1);
+ Jump match = jump();
+
+ ASSERT(differenceBetween(info.structureToCompare, protoObj) == patchOffsetMethodCheckProtoObj);
+ ASSERT(differenceBetween(info.structureToCompare, protoStructureToCompare) == patchOffsetMethodCheckProtoStruct);
+ ASSERT(differenceBetween(info.structureToCompare, putFunction) == patchOffsetMethodCheckPutFunction);
+
+ // Link the failure cases here.
+ structureCheck.link(this);
+ protoStructureCheck.link(this);
+
+ // Do a regular(ish) get_by_id (the slow case will be link to
+ // cti_op_get_by_id_method_check instead of cti_op_get_by_id.
+ compileGetByIdHotPath();
+
+ match.link(this);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_method_check), dst, regT1, regT0);
+
+ // We've already generated the following get_by_id, so make sure it's skipped over.
+ m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+}
+
+void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ currentInstruction += OPCODE_LENGTH(op_method_check);
+
+ int dst = currentInstruction[1].u.operand;
+ int base = currentInstruction[2].u.operand;
+ int ident = currentInstruction[3].u.operand;
+
+ compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
+
+ // We've already generated the following get_by_id, so make sure it's skipped over.
+ m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+}
+
+#else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+
+// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
+void JIT::emit_op_method_check(Instruction*) {}
+void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
+
+#endif
+
+void JIT::emit_op_get_by_val(Instruction* currentInstruction)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned base = currentInstruction[2].u.operand;
+ unsigned property = currentInstruction[3].u.operand;
+
+ emitLoad2(base, regT1, regT0, property, regT3, regT2);
+
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ emitJumpSlowCaseIfNotJSCell(base, regT1);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+ addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff))));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT0);
+ load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
+ load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned dst = currentInstruction[1].u.operand;
+ unsigned base = currentInstruction[2].u.operand;
+ unsigned property = currentInstruction[3].u.operand;
+
+ // The slow void JIT::emitSlow_that handles accesses to arrays (below) may jump back up to here.
+ Label callGetByValJITStub(this);
+
+ linkSlowCase(iter); // property int32 check
+ linkSlowCaseIfNotJSCell(iter, base); // base cell check
+ linkSlowCase(iter); // base array check
+
+ JITStubCall stubCall(this, cti_op_get_by_val);
+ stubCall.addArgument(base);
+ stubCall.addArgument(property);
+ stubCall.call(dst);
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
+
+ linkSlowCase(iter); // array fast cut-off check
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT0);
+ branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength)), callGetByValJITStub);
+
+ // Missed the fast region, but it is still in the vector.
+ load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
+ load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
+
+ // FIXME: Maybe we can optimize this comparison to JSValue().
+ Jump skip = branch32(NotEqual, regT0, Imm32(0));
+ branch32(Equal, regT1, Imm32(JSValue::CellTag), callGetByValJITStub);
+
+ skip.link(this);
+ emitStore(dst, regT1, regT0);
+}
+
+void JIT::emit_op_put_by_val(Instruction* currentInstruction)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned value = currentInstruction[3].u.operand;
+
+ emitLoad2(base, regT1, regT0, property, regT3, regT2);
+
+ addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+ emitJumpSlowCaseIfNotJSCell(base, regT1);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
+
+ Jump inFastVector = branch32(Below, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff)));
+
+ // Check if the access is within the vector.
+ addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, OBJECT_OFFSETOF(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.
+ Jump skip = branch32(NotEqual, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::CellTag));
+ addSlowCase(branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), Imm32(0)));
+ skip.link(this);
+
+ inFastVector.link(this);
+
+ emitLoad(value, regT1, regT0);
+ store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); // payload
+ store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4)); // tag
+}
+
+void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned base = currentInstruction[1].u.operand;
+ unsigned property = currentInstruction[2].u.operand;
+ unsigned value = currentInstruction[3].u.operand;
+
+ linkSlowCase(iter); // property int32 check
+ linkSlowCaseIfNotJSCell(iter, base); // base cell check
+ linkSlowCase(iter); // base not array check
+
+ JITStubCall stubPutByValCall(this, cti_op_put_by_val);
+ stubPutByValCall.addArgument(base);
+ stubPutByValCall.addArgument(property);
+ stubPutByValCall.addArgument(value);
+ stubPutByValCall.call();
+
+ emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
+
+ // Slow cases for immediate int accesses to arrays.
+ linkSlowCase(iter); // in vector check
+ linkSlowCase(iter); // written to slot check
+
+ JITStubCall stubCall(this, cti_op_put_by_val_array);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(regT2);
+ stubCall.addArgument(value);
+ stubCall.call();
+}
+
+void JIT::emit_op_get_by_id(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int base = currentInstruction[2].u.operand;
+
+ emitLoad(base, regT1, regT0);
+ emitJumpSlowCaseIfNotJSCell(base, regT1);
+ compileGetByIdHotPath();
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
+}
+
+void JIT::compileGetByIdHotPath()
+{
+ // 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.
+ Label hotPathBegin(this);
+ m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
+ m_propertyAccessInstructionIndex++;
+
+ DataLabelPtr structureToCompare;
+ Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+ addSlowCase(structureCheck);
+ ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
+ ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
+
+ Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT2);
+ Label externalLoadComplete(this);
+ ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
+ ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
+
+ DataLabel32 displacementLabel1 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetGetByIdPropertyMapOffset1);
+ DataLabel32 displacementLabel2 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetGetByIdPropertyMapOffset2);
+
+ Label putResult(this);
+ ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+}
+
+void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int dst = currentInstruction[1].u.operand;
+ int base = currentInstruction[2].u.operand;
+ int ident = currentInstruction[3].u.operand;
+
+ compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
+}
+
+void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
+{
+ // 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, base);
+ linkSlowCase(iter);
+
+ Label coldPathBegin(this);
+
+ JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(ImmPtr(ident));
+ Call call = stubCall.call(dst);
+
+ ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
+
+ // Track the location of the call; this will be used to recover patch information.
+ m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
+ m_propertyAccessInstructionIndex++;
+}
+
+void JIT::emit_op_put_by_id(Instruction* currentInstruction)
+{
+ // 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.
+
+ int base = currentInstruction[1].u.operand;
+ int value = currentInstruction[3].u.operand;
+
+ emitLoad2(base, regT1, regT0, value, regT3, regT2);
+
+ emitJumpSlowCaseIfNotJSCell(base, regT1);
+
+ Label hotPathBegin(this);
+ m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
+ m_propertyAccessInstructionIndex++;
+
+ // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
+ DataLabelPtr structureToCompare;
+ addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(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.
+ Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
+ Label externalLoadComplete(this);
+ ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
+ ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
+
+ DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
+ DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetPutByIdPropertyMapOffset1);
+ ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetPutByIdPropertyMapOffset2);
+}
+
+void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ int base = currentInstruction[1].u.operand;
+ int ident = currentInstruction[2].u.operand;
+
+ linkSlowCaseIfNotJSCell(iter, base);
+ linkSlowCase(iter);
+
+ JITStubCall stubCall(this, cti_op_put_by_id);
+ stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+ stubCall.addArgument(regT3, regT2);
+ Call call = stubCall.call();
+
+ // Track the location of the call; this will be used to recover patch information.
+ m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
+ m_propertyAccessInstructionIndex++;
+}
+
+// Compile a store into an object's property storage. May overwrite base.
+void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset)
+{
+ int offset = cachedOffset;
+ if (structure->isUsingInlineStorage())
+ offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) / sizeof(Register);
+ else
+ loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+ emitStore(offset, valueTag, valuePayload, base);
+}
+
+// Compile a load from an object's property storage. May overwrite base.
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset)
+{
+ int offset = cachedOffset;
+ if (structure->isUsingInlineStorage())
+ offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) / sizeof(Register);
+ else
+ loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+ emitLoad(offset, resultTag, resultPayload, base);
+}
+
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
+{
+ if (base->isUsingInlineStorage()) {
+ load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]), resultPayload);
+ load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + 4, resultTag);
+ return;
+ }
+
+ size_t offset = cachedOffset * sizeof(JSValue);
+
+ PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
+ loadPtr(static_cast<void*>(protoPropertyStorage), temp);
+ load32(Address(temp, offset), resultPayload);
+ load32(Address(temp, offset + 4), resultTag);
+}
+
+void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
+{
+ // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag. The value can be found on the stack.
+
+ JumpList failureCases;
+ failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(oldStructure)));
+
+ // Verify that nothing in the prototype chain has a setter for this property.
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(it->get())));
+ }
+
+ // Reallocate property storage if needed.
+ Call callTarget;
+ bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
+ if (willNeedStorageRealloc) {
+ // This trampoline was called to like a JIT stub; before we can can call again we need to
+ // remove the return address from the stack, to prevent the stack from becoming misaligned.
+ preserveReturnAddressAfterCall(regT3);
+
+ JITStubCall stubCall(this, cti_op_put_by_id_transition_realloc);
+ stubCall.skipArgument(); // base
+ stubCall.skipArgument(); // ident
+ stubCall.skipArgument(); // value
+ stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
+ stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
+ stubCall.call(regT0);
+
+ restoreReturnAddressBeforeReturn(regT3);
+ }
+
+ sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount()));
+ add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
+ storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)));
+
+ load32(Address(stackPointerRegister, offsetof(struct JITStackFrame, args[2]) + sizeof(void*)), regT3);
+ load32(Address(stackPointerRegister, offsetof(struct JITStackFrame, args[2]) + sizeof(void*) + 4), regT2);
+
+ // Write the value
+ compilePutDirectOffset(regT0, regT2, regT3, newStructure, cachedOffset);
+
+ ret();
+
+ ASSERT(!failureCases.empty());
+ failureCases.link(this);
+ restoreArgumentReferenceForTrampoline();
+ Call failureCall = tailRecursiveCall();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
+
+ if (willNeedStorageRealloc) {
+ ASSERT(m_calls.size() == 1);
+ patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
+ }
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relinkCallerToTrampoline(returnAddress, entryLabel);
+}
+
+void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ // We don't want to patch more than once - in future go to cti_op_get_by_id_generic.
+ // Should probably go to JITStubs::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
+
+ int offset = sizeof(JSValue) * cachedOffset;
+
+ // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
+ // and makes the subsequent load's offset automatically correct
+ if (structure->isUsingInlineStorage())
+ repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
+
+ // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset); // payload
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + 4); // tag
+}
+
+void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ ASSERT(!methodCallLinkInfo.cachedStructure);
+ methodCallLinkInfo.cachedStructure = structure;
+ structure->ref();
+
+ Structure* prototypeStructure = proto->structure();
+ ASSERT(!methodCallLinkInfo.cachedPrototypeStructure);
+ methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure;
+ prototypeStructure->ref();
+
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
+}
+
+void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ // Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+
+ int offset = sizeof(JSValue) * cachedOffset;
+
+ // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
+ // and makes the subsequent load's offset automatically correct
+ if (structure->isUsingInlineStorage())
+ repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
+
+ // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset); // payload
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + 4); // tag
+}
+
+void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
+{
+ StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
+
+ // regT0 holds a JSCell*
+
+ // Check for array
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr));
+
+ // Checks out okay! - get the length from the storage
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+ load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
+
+ Jump failureCases2 = branch32(Above, regT2, Imm32(INT_MAX));
+ move(regT2, regT0);
+ move(Imm32(JSValue::Int32Tag), regT1);
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-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.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ // Track the stub we have created so that it will be deleted later.
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
+}
+
+void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
+{
+ // regT0 holds a JSCell*
+
+ // 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));
+
+ Jump failureCases1 = checkStructure(regT0, structure);
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(prototypeStructure), regT3);
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
+#else
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+#endif
+
+ // Checks out okay! - getDirectOffset
+ compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-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.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ // Track the stub we have created so that it will be deleted later.
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+}
+
+
+void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
+{
+ // regT0 holds a JSCell*
+
+ Jump failureCase = checkStructure(regT0, structure);
+ compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset);
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
+ if (!lastProtoBegin)
+ lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-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.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+
+ structure->ref();
+ polymorphicStructures->list[currentIndex].set(entryLabel, structure);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+}
+
+void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
+{
+ // regT0 holds a JSCell*
+
+ // 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));
+
+ // Check eax is an object of the right Structure.
+ Jump failureCases1 = checkStructure(regT0, structure);
+
+ // Check the prototype object's Structure had not changed.
+ Structure** prototypeStructureAddress = &(protoObject->m_structure);
+#if PLATFORM(X86_64)
+ move(ImmPtr(prototypeStructure), regT3);
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
+#else
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+#endif
+
+ compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ CodeLocationLabel 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.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+
+ structure->ref();
+ prototypeStructure->ref();
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+}
+
+void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
{
- // 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.
+ // regT0 holds a JSCell*
+
+ ASSERT(count);
+
+ JumpList bucketsOfFail;
- emitGetVirtualRegister(baseVReg, X86::eax);
+ // Check eax is an object of the right Structure.
+ bucketsOfFail.append(checkStructure(regT0, structure));
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArgConstant(ident, 2);
- emitCTICall(Interpreter::cti_op_get_by_id_generic);
- emitPutVirtualRegister(resultVReg);
+ 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), regT3);
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
+#else
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+#endif
+ }
+ ASSERT(protoObject);
+
+ compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ CodeLocationLabel 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.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+
+ // Track the stub we have created so that it will be deleted later.
+ structure->ref();
+ chain->ref();
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+}
+
+void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
+{
+ // regT0 holds a JSCell*
+
+ ASSERT(count);
+
+ JumpList bucketsOfFail;
+
+ // Check eax is an object of the right Structure.
+ bucketsOfFail.append(checkStructure(regT0, 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), regT3);
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
+#else
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+#endif
+ }
+ ASSERT(protoObject);
+
+ compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+ Jump success = jump();
+
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
+
+ // Use the patch information to link the failure cases back to the original slow case routine.
+ patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall));
+
+ // On success return back to the hot patch code, at a point it will perform the store to dest for us.
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ // Track the stub we have created so that it will be deleted later.
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
+
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
+
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+}
+
+/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+
+#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+#else // USE(JSVALUE32_64)
+
+void JIT::emit_op_get_by_val(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+ // 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(regT1, regT1);
+#else
+ emitFastArithImmToInt(regT1);
+#endif
+ emitJumpSlowCaseIfNotJSCell(regT0);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+
+ // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+ addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff))));
+
+ // Get the value from the vector
+ loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_put_by_val(Instruction* currentInstruction)
+{
+ emitGetVirtualRegisters(currentInstruction[1].u.operand, regT0, currentInstruction[2].u.operand, regT1);
+ emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+ // See comment in op_get_by_val.
+ zeroExtend32ToPtr(regT1, regT1);
+#else
+ emitFastArithImmToInt(regT1);
+#endif
+ emitJumpSlowCaseIfNotJSCell(regT0);
+ addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+
+ // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+ Jump inFastVector = branch32(Below, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff)));
+ // No; oh well, check if the access if within the vector - if so, we may still be okay.
+ addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, OBJECT_OFFSETOF(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(branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
+
+ // All good - put the value into the array.
+ inFastVector.link(this);
+ emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+ storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+}
+
+void JIT::emit_op_put_by_index(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_put_by_index);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call();
+}
+
+void JIT::emit_op_put_getter(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_put_getter);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call();
+}
+
+void JIT::emit_op_put_setter(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_put_setter);
+ stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+ stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+ stubCall.call();
+}
+
+void JIT::emit_op_del_by_id(Instruction* currentInstruction)
+{
+ JITStubCall stubCall(this, cti_op_del_by_id);
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+ stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
}
-void JIT::compileGetByIdSlowCase(int, int, Identifier*, Vector<SlowCaseEntry>::iterator&, unsigned)
+#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+
+// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
+void JIT::emit_op_method_check(Instruction*) {}
+void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
+#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+#error "JIT_OPTIMIZE_METHOD_CALLS requires JIT_OPTIMIZE_PROPERTY_ACCESS"
+#endif
+
+void JIT::emit_op_get_by_id(Instruction* currentInstruction)
+{
+ unsigned resultVReg = currentInstruction[1].u.operand;
+ unsigned baseVReg = currentInstruction[2].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ emitGetVirtualRegister(baseVReg, regT0);
+ JITStubCall stubCall(this, cti_op_get_by_id_generic);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(ImmPtr(ident));
+ stubCall.call(resultVReg);
+
+ m_propertyAccessInstructionIndex++;
+}
+
+void JIT::emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
{
ASSERT_NOT_REACHED();
}
-void JIT::compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned)
+void JIT::emit_op_put_by_id(Instruction* currentInstruction)
{
- // 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.
+ unsigned baseVReg = currentInstruction[1].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ unsigned valueVReg = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);
- emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx);
+ JITStubCall stubCall(this, cti_op_put_by_id_generic);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(ImmPtr(ident));
+ stubCall.addArgument(regT1);
+ stubCall.call();
- emitPutJITStubArgConstant(ident, 2);
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArg(X86::edx, 3);
- emitCTICall(Interpreter::cti_op_put_by_id_generic);
+ m_propertyAccessInstructionIndex++;
}
-void JIT::compilePutByIdSlowCase(int, Identifier*, int, Vector<SlowCaseEntry>::iterator&, unsigned)
+void JIT::emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
{
ASSERT_NOT_REACHED();
}
-#else
+#else // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+
+#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+
+void JIT::emit_op_method_check(Instruction* currentInstruction)
+{
+ // Assert that the following instruction is a get_by_id.
+ ASSERT(m_interpreter->getOpcodeID((currentInstruction + OPCODE_LENGTH(op_method_check))->u.opcode) == op_get_by_id);
+
+ currentInstruction += OPCODE_LENGTH(op_method_check);
+ unsigned resultVReg = currentInstruction[1].u.operand;
+ unsigned baseVReg = currentInstruction[2].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ emitGetVirtualRegister(baseVReg, regT0);
+
+ // Do the method check - check the object & its prototype's structure inline (this is the common case).
+ m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
+ MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
+ Jump notCell = emitJumpIfNotJSCell(regT0);
+ Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+ DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1);
+ Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+
+ // This will be relinked to load the function without doing a load.
+ DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+ Jump match = jump();
+
+ ASSERT(differenceBetween(info.structureToCompare, protoObj) == patchOffsetMethodCheckProtoObj);
+ ASSERT(differenceBetween(info.structureToCompare, protoStructureToCompare) == patchOffsetMethodCheckProtoStruct);
+ ASSERT(differenceBetween(info.structureToCompare, putFunction) == patchOffsetMethodCheckPutFunction);
+
+ // Link the failure cases here.
+ notCell.link(this);
+ structureCheck.link(this);
+ protoStructureCheck.link(this);
+
+ // Do a regular(ish) get_by_id (the slow case will be link to
+ // cti_op_get_by_id_method_check instead of cti_op_get_by_id.
+ compileGetByIdHotPath(resultVReg, baseVReg, ident, m_propertyAccessInstructionIndex++);
+
+ match.link(this);
+ emitPutVirtualRegister(resultVReg);
+
+ // We've already generated the following get_by_id, so make sure it's skipped over.
+ m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+}
-void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex)
+void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ currentInstruction += OPCODE_LENGTH(op_method_check);
+ unsigned resultVReg = currentInstruction[1].u.operand;
+ unsigned baseVReg = currentInstruction[2].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
+
+ // We've already generated the following get_by_id, so make sure it's skipped over.
+ m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+}
+
+#else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
+
+// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
+void JIT::emit_op_method_check(Instruction*) {}
+void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
+
+#endif
+
+void JIT::emit_op_get_by_id(Instruction* currentInstruction)
+{
+ unsigned resultVReg = currentInstruction[1].u.operand;
+ unsigned baseVReg = currentInstruction[2].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ emitGetVirtualRegister(baseVReg, regT0);
+ compileGetByIdHotPath(resultVReg, baseVReg, ident, m_propertyAccessInstructionIndex++);
+ emitPutVirtualRegister(resultVReg);
+}
+
+void JIT::compileGetByIdHotPath(int, 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);
+ emitJumpSlowCaseIfNotJSCell(regT0, 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)));
+ Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(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);
+ Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
+ Label externalLoadComplete(this);
+ ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
+ ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
+
+ DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);
Label putResult(this);
ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
- emitPutVirtualRegister(resultVReg);
}
+void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ unsigned resultVReg = currentInstruction[1].u.operand;
+ unsigned baseVReg = currentInstruction[2].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+
+ compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, false);
+}
-void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
+void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
{
// 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
#ifndef NDEBUG
Label coldPathBegin(this);
#endif
- emitPutJITStubArg(X86::eax, 1);
- emitPutJITStubArgConstant(ident, 2);
- Jump call = emitCTICall(Interpreter::cti_op_get_by_id);
- emitPutVirtualRegister(resultVReg);
+ JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(ImmPtr(ident));
+ Call call = stubCall.call(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;
+ m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
+ m_propertyAccessInstructionIndex++;
}
-void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsigned propertyAccessInstructionIndex)
+void JIT::emit_op_put_by_id(Instruction* currentInstruction)
{
+ unsigned baseVReg = currentInstruction[1].u.operand;
+ unsigned valueVReg = currentInstruction[3].u.operand;
+
+ unsigned propertyAccessInstructionIndex = m_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);
+ emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);
// Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
- emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg);
+ emitJumpSlowCaseIfNotJSCell(regT0, 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))));
+ addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(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));
+ Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
+ Label externalLoadComplete(this);
+ ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
+ ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
+
+ DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
}
-void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
+void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ unsigned baseVReg = currentInstruction[1].u.operand;
+ Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+
+ unsigned propertyAccessInstructionIndex = m_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);
+ JITStubCall stubCall(this, cti_op_put_by_id);
+ stubCall.addArgument(regT0);
+ stubCall.addArgument(ImmPtr(ident));
+ stubCall.addArgument(regT1);
+ Call call = stubCall.call();
// 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)
+// Compile a store into an object's property storage. May overwrite the
+// value in objectReg.
+void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset)
+{
+ int offset = cachedOffset * sizeof(JSValue);
+ if (structure->isUsingInlineStorage())
+ offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
+ else
+ loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+ storePtr(value, Address(base, offset));
+}
+
+// Compile a load from an object's property storage. May overwrite base.
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset)
{
- baseObject->allocatePropertyStorage(oldSize, newSize);
- return baseObject;
+ int offset = cachedOffset * sizeof(JSValue);
+ if (structure->isUsingInlineStorage())
+ offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
+ else
+ loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+ loadPtr(Address(base, offset), result);
}
-static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
{
- return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
+ if (base->isUsingInlineStorage())
+ loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
+ else {
+ PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
+ loadPtr(static_cast<void*>(protoPropertyStorage), temp);
+ loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
+ }
}
-void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
+void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr 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)));
+ failureCases.append(emitJumpIfNotJSCell(regT0));
+ failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
JumpList successCases;
- // ecx = baseObject
- loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
+ // ecx = baseObject
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
// proto(ecx) = baseObject->structure()->prototype()
- failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
+ failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
- loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
// 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()))));
+ successCases.append(branchPtr(Equal, regT2, ImmPtr(JSValue::encode(jsNull()))));
// Check the structure id
- failureCases.append(jnePtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(it->get())));
+ failureCases.append(branchPtr(NotEqual, Address(regT2, OBJECT_OFFSETOF(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);
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+ failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
+ loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
}
successCases.link(this);
- Jump callTarget;
+ Call 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);
+ bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
+ if (willNeedStorageRealloc) {
+ // This trampoline was called to like a JIT stub; before we can can call again we need to
+ // remove the return address from the stack, to prevent the stack from becoming misaligned.
+ preserveReturnAddressAfterCall(regT3);
+
+ JITStubCall stubCall(this, cti_op_put_by_id_transition_realloc);
+ stubCall.skipArgument(); // base
+ stubCall.skipArgument(); // ident
+ stubCall.skipArgument(); // value
+ stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
+ stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
+ stubCall.call(regT0);
+ emitGetJITStubArg(3, regT1);
+
+ restoreReturnAddressBeforeReturn(regT3);
}
// 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)));
+ storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(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)));
+ compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset);
ret();
- Jump failureJump;
- bool plantedFailureJump = false;
- if (!failureCases.empty()) {
- failureCases.link(this);
- restoreArgumentReferenceForTrampoline();
- failureJump = jump();
- plantedFailureJump = true;
- }
+ ASSERT(!failureCases.empty());
+ failureCases.link(this);
+ restoreArgumentReferenceForTrampoline();
+ Call failureCall = tailRecursiveCall();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
- if (plantedFailureJump)
- patchBuffer.link(failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
+ patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
- if (transitionWillNeedStorageRealloc(oldStructure, newStructure))
- patchBuffer.link(callTarget, reinterpret_cast<void*>(resizePropertyStorage));
-
- stubInfo->stubRoutine = code;
+ if (willNeedStorageRealloc) {
+ ASSERT(m_calls.size() == 1);
+ patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
+ }
- Jump::patch(returnAddress, code);
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relinkCallerToTrampoline(returnAddress, entryLabel);
}
-void JIT::patchGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
{
+ RepatchBuffer repatchBuffer(codeBlock);
+
// 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));
+ // Should probably go to cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
+
+ int offset = sizeof(JSValue) * cachedOffset;
+
+ // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
+ // and makes the subsequent load's offset automatically correct
+ if (structure->isUsingInlineStorage())
+ repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
// 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));
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
+}
+
+void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ ASSERT(!methodCallLinkInfo.cachedStructure);
+ methodCallLinkInfo.cachedStructure = structure;
+ structure->ref();
+
+ Structure* prototypeStructure = proto->structure();
+ ASSERT(!methodCallLinkInfo.cachedPrototypeStructure);
+ methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure;
+ prototypeStructure->ref();
+
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
+ repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
}
-void JIT::patchPutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
+void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
{
+ RepatchBuffer repatchBuffer(codeBlock);
+
// 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));
+ // Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+
+ int offset = sizeof(JSValue) * cachedOffset;
+
+ // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
+ // and makes the subsequent load's offset automatically correct
+ if (structure->isUsingInlineStorage())
+ repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
// 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));
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
+ repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset), offset);
}
-void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
+void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr 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));
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->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);
+ loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+ load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
- Jump failureCases2 = ja32(X86::ecx, Imm32(JSImmediate::maxImmediateInt));
+ Jump failureCases2 = branch32(Above, regT2, Imm32(JSImmediate::maxImmediateInt));
- emitFastArithIntToImmNoCheck(X86::ecx, X86::eax);
+ emitFastArithIntToImmNoCheck(regT2, regT0);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// Use the patch information to link the failure cases back to the original slow case routine.
- void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+ CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-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);
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
// 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();
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
- 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;
+ // Finally patch the jump to slow case back in the hot path to jump here instead.
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
- Jump::patch(returnAddress, code);
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
}
-void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
+void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr 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);
+ Jump failureCases1 = checkStructure(regT0, 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));
+ move(ImmPtr(prototypeStructure), regT3);
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
#else
- Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
// Checks out okay! - getDirectOffset
- loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// Use the patch information to link the failure cases back to the original slow case routine.
- void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+ CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-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));
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = code;
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
// 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);
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
- 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
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
}
-#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 failureCase = checkStructure(regT0, structure);
+ compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- ASSERT(code);
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// Use the patch information to link the failure cases back to the original slow case routine.
- void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
+ CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
if (!lastProtoBegin)
- lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
+ lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-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));
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
structure->ref();
- polymorphicStructures->list[currentIndex].set(code, structure);
+ polymorphicStructures->list[currentIndex].set(entryLabel, 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);
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
}
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);
+ Jump failureCases1 = checkStructure(regT0, 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));
+ move(ImmPtr(prototypeStructure), regT3);
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
#else
- Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
+ Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
// Checks out okay! - getDirectOffset
- loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
+ compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// Use the patch information to link the failure cases back to the original slow case routine.
- void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+ CodeLocationLabel 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));
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
structure->ref();
prototypeStructure->ref();
- prototypeStructures->list[currentIndex].set(code, structure, prototypeStructure);
+ prototypeStructures->list[currentIndex].set(entryLabel, 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);
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
}
void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
JumpList bucketsOfFail;
// Check eax is an object of the right Structure.
- Jump baseObjectCheck = checkStructure(X86::eax, structure);
+ Jump baseObjectCheck = checkStructure(regT0, structure);
bucketsOfFail.append(baseObjectCheck);
Structure* currStructure = structure;
// 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)));
+ move(ImmPtr(currStructure), regT3);
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
#else
- bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+ bucketsOfFail.append(branchPtr(NotEqual, 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);
+ compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// Use the patch information to link the failure cases back to the original slow case routine.
- void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+ CodeLocationLabel 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));
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
- prototypeStructures->list[currentIndex].set(code, structure, chain);
+ prototypeStructures->list[currentIndex].set(entryLabel, 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);
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
}
-#endif
-void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
+void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr 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));
+ bucketsOfFail.append(checkStructure(regT0, structure));
Structure* currStructure = structure;
RefPtr<Structure>* chainEntries = chain->head();
// 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)));
+ move(ImmPtr(currStructure), regT3);
+ bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
#else
- bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
+ bucketsOfFail.append(branchPtr(NotEqual, 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);
+ compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
Jump success = jump();
- void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
- PatchBuffer patchBuffer(code);
+ LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
// 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);
+ patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall));
// 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));
+ patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
// Track the stub we have created so that it will be deleted later.
- stubInfo->stubRoutine = code;
+ CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+ stubInfo->stubRoutine = entryLabel;
// 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);
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(jumpLocation, entryLabel);
- 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
+ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
}
-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));
+/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
- stubInfo->stubRoutine = code;
-
- Jump::patch(returnAddress, code);
-}
+#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-#endif
+#endif // USE(JSVALUE32_64)
} // 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 JITStubCall_h
+#define JITStubCall_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+ class JITStubCall {
+ public:
+ JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Cell)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+ JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Cell)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+ JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(VoidPtr)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+ JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Int)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+ JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Int)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+ JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Void)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+
+#if USE(JSVALUE32_64)
+ JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Value)
+ , m_stackIndex(stackIndexStart)
+ {
+ }
+#endif
+
+ // Arguments are added first to last.
+
+ void skipArgument()
+ {
+ m_stackIndex += stackIndexStep;
+ }
+
+ void addArgument(JIT::Imm32 argument)
+ {
+ m_jit->poke(argument, m_stackIndex);
+ m_stackIndex += stackIndexStep;
+ }
+
+ void addArgument(JIT::ImmPtr argument)
+ {
+ m_jit->poke(argument, m_stackIndex);
+ m_stackIndex += stackIndexStep;
+ }
+
+ void addArgument(JIT::RegisterID argument)
+ {
+ m_jit->poke(argument, m_stackIndex);
+ m_stackIndex += stackIndexStep;
+ }
+
+ void addArgument(const JSValue& value)
+ {
+ m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex);
+ m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1);
+ m_stackIndex += stackIndexStep;
+ }
+
+ void addArgument(JIT::RegisterID tag, JIT::RegisterID payload)
+ {
+ m_jit->poke(payload, m_stackIndex);
+ m_jit->poke(tag, m_stackIndex + 1);
+ m_stackIndex += stackIndexStep;
+ }
+
+#if USE(JSVALUE32_64)
+ void addArgument(unsigned srcVirtualRegister)
+ {
+ if (m_jit->m_codeBlock->isConstantRegisterIndex(srcVirtualRegister)) {
+ addArgument(m_jit->getConstantOperand(srcVirtualRegister));
+ return;
+ }
+
+ m_jit->emitLoad(srcVirtualRegister, JIT::regT1, JIT::regT0);
+ addArgument(JIT::regT1, JIT::regT0);
+ }
+
+ void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
+ {
+ size_t stackIndex = stackIndexStart + (argumentNumber * stackIndexStep);
+ m_jit->peek(payload, stackIndex);
+ m_jit->peek(tag, stackIndex + 1);
+ }
+#else
+ void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
+ {
+ if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
+ addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
+ else {
+ m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
+ addArgument(scratchRegister);
+ }
+ m_jit->killLastResultRegister();
+ }
+#endif
+
+ JIT::Call call()
+ {
+#if ENABLE(OPCODE_SAMPLING)
+ if (m_jit->m_bytecodeIndex != (unsigned)-1)
+ m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, true);
+#endif
+
+ m_jit->restoreArgumentReference();
+ JIT::Call call = m_jit->call();
+ m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub));
+
+#if ENABLE(OPCODE_SAMPLING)
+ if (m_jit->m_bytecodeIndex != (unsigned)-1)
+ m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, false);
+#endif
+
+#if USE(JSVALUE32_64)
+ m_jit->unmap();
+#else
+ m_jit->killLastResultRegister();
+#endif
+ return call;
+ }
+
+#if USE(JSVALUE32_64)
+ JIT::Call call(unsigned dst) // dst is a virtual register.
+ {
+ ASSERT(m_returnType == Value || m_returnType == Cell);
+ JIT::Call call = this->call();
+ if (m_returnType == Value)
+ m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
+ else
+ m_jit->emitStoreCell(dst, JIT::returnValueRegister);
+ return call;
+ }
+#else
+ JIT::Call call(unsigned dst) // dst is a virtual register.
+ {
+ ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
+ JIT::Call call = this->call();
+ m_jit->emitPutVirtualRegister(dst);
+ return call;
+ }
+#endif
+
+ JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
+ {
+#if USE(JSVALUE32_64)
+ ASSERT(m_returnType == Value || m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
+#else
+ ASSERT(m_returnType == VoidPtr || m_returnType == Int || m_returnType == Cell);
+#endif
+ JIT::Call call = this->call();
+ if (dst != JIT::returnValueRegister)
+ m_jit->move(JIT::returnValueRegister, dst);
+ return call;
+ }
+
+ private:
+ static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
+ static const size_t stackIndexStart = 1; // Index 0 is reserved for restoreArgumentReference().
+
+ JIT* m_jit;
+ void* m_stub;
+ enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
+ size_t m_stackIndex;
+ };
+}
+
+#endif // ENABLE(JIT)
+
+#endif // JITStubCall_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 "JITStubs.h"
+
+#if ENABLE(JIT)
+
+#include "Arguments.h"
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "Collector.h"
+#include "Debugger.h"
+#include "ExceptionHelpers.h"
+#include "GlobalEvalFunction.h"
+#include "JIT.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 "Operations.h"
+#include "Parser.h"
+#include "Profiler.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "Register.h"
+#include "SamplingTool.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+using namespace std;
+
+namespace JSC {
+
+#if PLATFORM(DARWIN) || PLATFORM(WIN_OS)
+#define SYMBOL_STRING(name) "_" #name
+#else
+#define SYMBOL_STRING(name) #name
+#endif
+
+#if USE(JSVALUE32_64)
+
+#if COMPILER(GCC) && PLATFORM(X86)
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
+
+asm volatile (
+".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 $0x3c, %esp" "\n"
+ "movl $512, %esi" "\n"
+ "movl 0x58(%esp), %edi" "\n"
+ "call *0x50(%esp)" "\n"
+ "addl $0x3c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+#if !USE(JIT_STUB_ARGUMENT_VA_LIST)
+ "movl %esp, %ecx" "\n"
+#endif
+ "call " SYMBOL_STRING(cti_vm_throw) "\n"
+ "addl $0x3c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "addl $0x3c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+#elif COMPILER(GCC) && PLATFORM(X86_64)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
+#endif
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
+
+asm volatile (
+".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"
+ "call *0x80(%rsp)" "\n"
+ "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 volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+ "movq %rsp, %rdi" "\n"
+ "call " SYMBOL_STRING(cti_vm_throw) "\n"
+ "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 volatile (
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "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(GCC) && PLATFORM_ARM_ARCH(7)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
+#endif
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+ "sub sp, sp, #0x3c" "\n"
+ "str lr, [sp, #0x20]" "\n"
+ "str r4, [sp, #0x24]" "\n"
+ "str r5, [sp, #0x28]" "\n"
+ "str r6, [sp, #0x2c]" "\n"
+ "str r1, [sp, #0x30]" "\n"
+ "str r2, [sp, #0x34]" "\n"
+ "str r3, [sp, #0x38]" "\n"
+ "cpy r5, r2" "\n"
+ "mov r6, #512" "\n"
+ "blx r0" "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+ "cpy r0, sp" "\n"
+ "bl " SYMBOL_STRING(cti_vm_throw) "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+#elif COMPILER(MSVC)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
+#endif
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
+
+extern "C" {
+
+ __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
+ {
+ __asm {
+ push ebp;
+ mov ebp, esp;
+ push esi;
+ push edi;
+ push ebx;
+ sub esp, 0x3c;
+ mov esi, 512;
+ mov ecx, esp;
+ mov edi, [esp + 0x58];
+ call [esp + 0x50];
+ add esp, 0x3c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+ __declspec(naked) void ctiVMThrowTrampoline()
+ {
+ __asm {
+ mov ecx, esp;
+ call cti_vm_throw;
+ add esp, 0x3c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+ __declspec(naked) void ctiOpThrowNotCaught()
+ {
+ __asm {
+ add esp, 0x3c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+}
+
+#endif // COMPILER(GCC) && PLATFORM(X86)
+
+#else // USE(JSVALUE32_64)
+
+#if COMPILER(GCC) && PLATFORM(X86)
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+
+asm volatile (
+".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"
+ "call *0x30(%esp)" "\n"
+ "addl $0x1c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+#if !USE(JIT_STUB_ARGUMENT_VA_LIST)
+ "movl %esp, %ecx" "\n"
+#endif
+ "call " SYMBOL_STRING(cti_vm_throw) "\n"
+ "addl $0x1c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "addl $0x1c, %esp" "\n"
+ "popl %ebx" "\n"
+ "popl %edi" "\n"
+ "popl %esi" "\n"
+ "popl %ebp" "\n"
+ "ret" "\n"
+);
+
+#elif COMPILER(GCC) && PLATFORM(X86_64)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
+#endif
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+
+asm volatile (
+".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"
+ "call *0x80(%rsp)" "\n"
+ "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 volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+ "movq %rsp, %rdi" "\n"
+ "call " SYMBOL_STRING(cti_vm_throw) "\n"
+ "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 volatile (
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "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(GCC) && PLATFORM_ARM_ARCH(7)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
+#endif
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+ "sub sp, sp, #0x3c" "\n"
+ "str lr, [sp, #0x20]" "\n"
+ "str r4, [sp, #0x24]" "\n"
+ "str r5, [sp, #0x28]" "\n"
+ "str r6, [sp, #0x2c]" "\n"
+ "str r1, [sp, #0x30]" "\n"
+ "str r2, [sp, #0x34]" "\n"
+ "str r3, [sp, #0x38]" "\n"
+ "cpy r5, r2" "\n"
+ "mov r6, #512" "\n"
+ "blx r0" "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+ "cpy r0, sp" "\n"
+ "bl " SYMBOL_STRING(cti_vm_throw) "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+asm volatile (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+".thumb" "\n"
+".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+ "ldr r6, [sp, #0x2c]" "\n"
+ "ldr r5, [sp, #0x28]" "\n"
+ "ldr r4, [sp, #0x24]" "\n"
+ "ldr lr, [sp, #0x20]" "\n"
+ "add sp, sp, #0x3c" "\n"
+ "bx lr" "\n"
+);
+
+#elif COMPILER(MSVC)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
+#endif
+
+// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
+// need to change the assembly trampolines below to match.
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+
+extern "C" {
+
+ __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* 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];
+ add esp, 0x1c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+ __declspec(naked) void ctiVMThrowTrampoline()
+ {
+ __asm {
+ mov ecx, esp;
+ call cti_vm_throw;
+ add esp, 0x1c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+
+ __declspec(naked) void ctiOpThrowNotCaught()
+ {
+ __asm {
+ add esp, 0x1c;
+ pop ebx;
+ pop edi;
+ pop esi;
+ pop ebp;
+ ret;
+ }
+ }
+}
+
+#endif // COMPILER(GCC) && PLATFORM(X86)
+
+#endif // USE(JSVALUE32_64)
+
+#if ENABLE(OPCODE_SAMPLING)
+ #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
+#else
+ #define CTI_SAMPLER 0
+#endif
+
+JITThunks::JITThunks(JSGlobalData* globalData)
+{
+ JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallPreLink, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
+
+#if PLATFORM_ARM_ARCH(7)
+ // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
+ // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
+ // macros.
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 0x20);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == 0x24);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == 0x28);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == 0x2c);
+
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 0x30);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34);
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38);
+ // The fifth argument is the first item already on the stack.
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x3c);
+
+ ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C);
+#endif
+}
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue 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(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ return;
+ }
+
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = baseCell->structure();
+
+ if (structure->isUncacheableDictionary()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ return;
+ }
+
+ // If baseCell != base, then baseCell must be a proxy for another object.
+ if (baseCell != slot.base()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(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);
+ if (!prototypeChain->isCacheable() || structure->isDictionary()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ return;
+ }
+ stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
+ JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
+ return;
+ }
+
+ stubInfo->initPutByIdReplace(structure);
+
+ JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
+}
+
+NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue 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(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+ return;
+ }
+
+ JSGlobalData* globalData = &callFrame->globalData();
+
+ if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+ JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
+ return;
+ }
+
+ if (isJSString(globalData, 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(codeBlock, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline());
+ return;
+ }
+
+ // Uncacheable: give up.
+ if (!slot.isCacheable()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+ return;
+ }
+
+ JSCell* baseCell = asCell(baseValue);
+ Structure* structure = baseCell->structure();
+
+ if (structure->isUncacheableDictionary()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(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);
+
+ JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
+ return;
+ }
+
+ if (structure->isDictionary()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+ return;
+ }
+
+ if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
+ ASSERT(slot.slotBase().isObject());
+
+ JSObject* slotBaseObject = asObject(slot.slotBase());
+ size_t offset = slot.cachedOffset();
+
+ // 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->flattenDictionaryObject();
+ offset = slotBaseObject->structure()->get(propertyName);
+ }
+
+ stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
+
+ JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress);
+ return;
+ }
+
+ size_t offset = slot.cachedOffset();
+ size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
+ if (!count) {
+ stubInfo->opcodeID = op_get_by_id_generic;
+ return;
+ }
+
+ StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ if (!prototypeChain->isCacheable()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+ return;
+ }
+ stubInfo->initGetByIdChain(structure, prototypeChain);
+ JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress);
+}
+
+#endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
+#else
+#define SETUP_VA_LISTL_ARGS
+#endif
+
+#ifndef NDEBUG
+
+extern "C" {
+
+static void jscGeneratedNativeCode()
+{
+ // When executing a JIT stub 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(JITStackFrame& stackFrame)
+ : stackFrame(stackFrame)
+ , savedReturnAddress(*stackFrame.returnAddressSlot())
+ {
+ *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
+ }
+
+ ALWAYS_INLINE ~StackHack()
+ {
+ *stackFrame.returnAddressSlot() = savedReturnAddress;
+ }
+
+ JITStackFrame& stackFrame;
+ ReturnAddressPtr savedReturnAddress;
+};
+
+#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
+#define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
+#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
+
+#else
+
+#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
+#define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
+#define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
+
+#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, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
+{
+ ASSERT(globalData->exception);
+ globalData->exceptionLocation = exceptionLocation;
+ returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
+}
+
+static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& 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_AT_END() \
+ returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
+
+#define CHECK_FOR_EXCEPTION() \
+ do { \
+ if (UNLIKELY(stackFrame.globalData->exception)) \
+ VM_THROW_EXCEPTION(); \
+ } while (0)
+#define CHECK_FOR_EXCEPTION_AT_END() \
+ do { \
+ if (UNLIKELY(stackFrame.globalData->exception)) \
+ VM_THROW_EXCEPTION_AT_END(); \
+ } while (0)
+#define CHECK_FOR_EXCEPTION_VOID() \
+ do { \
+ if (UNLIKELY(stackFrame.globalData->exception)) { \
+ VM_THROW_EXCEPTION_AT_END(); \
+ return; \
+ } \
+ } while (0)
+
+#if PLATFORM_ARM_ARCH(7)
+
+#define DEFINE_STUB_FUNCTION(rtype, op) \
+ extern "C" { \
+ rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
+ }; \
+ asm volatile ( \
+ ".text" "\n" \
+ ".align 2" "\n" \
+ ".globl " SYMBOL_STRING(cti_##op) "\n" \
+ ".thumb" "\n" \
+ ".thumb_func " SYMBOL_STRING(cti_##op) "\n" \
+ SYMBOL_STRING(cti_##op) ":" "\n" \
+ "str lr, [sp, #0x1c]" "\n" \
+ "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
+ "ldr lr, [sp, #0x1c]" "\n" \
+ "bx lr" "\n" \
+ ); \
+ rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
+
+#else
+#define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
+#endif
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v1 = stackFrame.args[0].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSObject* result = v1.toThisObject(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(void, op_end)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain();
+ ASSERT(scopeChain->refCount > 1);
+ scopeChain->deref();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v1 = stackFrame.args[0].jsValue();
+ JSValue v2 = stackFrame.args[1].jsValue();
+
+ double left;
+ double right = 0.0;
+
+ bool rightIsNumber = v2.getNumber(right);
+ if (rightIsNumber && v1.getNumber(left))
+ return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
+
+ CallFrame* callFrame = stackFrame.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 JSValue::encode(jsString(stackFrame.globalData, value.release()));
+ }
+
+ if (rightIsNumber & leftIsString) {
+ RefPtr<UString::Rep> value = v2.isInt32() ?
+ concatenate(asString(v1)->value().rep(), v2.asInt32()) :
+ concatenate(asString(v1)->value().rep(), right);
+
+ if (UNLIKELY(!value)) {
+ throwOutOfMemoryError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ return JSValue::encode(jsString(stackFrame.globalData, value.release()));
+ }
+
+ // All other cases are pretty uncommon
+ JSValue result = jsAddSlowCase(callFrame, v1, v2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) + 1);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(int, timeout_check)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSGlobalData* globalData = stackFrame.globalData;
+ TimeoutChecker& timeoutChecker = globalData->timeoutChecker;
+
+ if (timeoutChecker.didTimeOut(stackFrame.callFrame)) {
+ globalData->exception = createInterruptedExecutionException(globalData);
+ VM_THROW_EXCEPTION_AT_END();
+ }
+
+ return timeoutChecker.ticksUntilNextCheck();
+}
+
+DEFINE_STUB_FUNCTION(void, register_file_check)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ if (LIKELY(stackFrame.registerFile->grow(&stackFrame.callFrame->registers()[stackFrame.callFrame->codeBlock()->m_numCalleeRegisters])))
+ return;
+
+ // Rewind to the previous call frame because op_call already optimistically
+ // moved the call frame forward.
+ CallFrame* oldCallFrame = stackFrame.callFrame->callerFrame();
+ stackFrame.callFrame = oldCallFrame;
+ throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
+}
+
+DEFINE_STUB_FUNCTION(int, op_loop_if_less)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = jsLessEq(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return constructEmptyObject(stackFrame.callFrame);
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+DEFINE_STUB_FUNCTION(void, op_put_by_id)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_id_second)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
+ JITThunks::tryCachePutByID(stackFrame.callFrame, stackFrame.callFrame->codeBlock(), STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot);
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ int32_t oldSize = stackFrame.args[3].int32();
+ int32_t newSize = stackFrame.args[4].int32();
+
+ ASSERT(baseValue.isObject());
+ JSObject* base = asObject(baseValue);
+ base->allocatePropertyStorage(oldSize, newSize);
+
+ return base;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_second)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ CHECK_FOR_EXCEPTION();
+
+ // If we successfully got something, then the base from which it is being accessed must
+ // be an object. (Assertion to ensure asObject() call below is safe, which comes after
+ // an isCacheable() chceck.
+ ASSERT(!slot.isCacheable() || slot.slotBase().isObject());
+
+ // Check that:
+ // * We're dealing with a JSCell,
+ // * the property is cachable,
+ // * it's not a dictionary
+ // * there is a function cached.
+ Structure* structure;
+ JSCell* specific;
+ JSObject* slotBaseObject;
+ if (baseValue.isCell()
+ && slot.isCacheable()
+ && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary()
+ && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
+ && specific
+ ) {
+
+ JSFunction* callee = (JSFunction*)specific;
+
+ // 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->flattenDictionaryObject();
+
+ // The result fetched should always be the callee!
+ ASSERT(result == JSValue(callee));
+ MethodCallLinkInfo& methodCallLinkInfo = callFrame->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
+
+ // Check to see if the function is on the object's prototype. Patch up the code to optimize.
+ if (slot.slotBase() == structure->prototypeForLookup(callFrame))
+ JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject);
+ // Check to see if the function is on the object itself.
+ // Since we generate the method-check to check both the structure and a prototype-structure (since this
+ // is the common case) we have a problem - we need to patch the prototype structure check to do something
+ // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
+ // for now. For now it performs a check on a special object on the global object only used for this
+ // purpose. The object is in no way exposed, and as such the check will always pass.
+ else if (slot.slotBase() == baseValue)
+ JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy());
+
+ // For now let any other case be cached as a normal get_by_id.
+ }
+
+ // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
+
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_second)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ JITThunks::tryCacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, ident, slot);
+
+ CHECK_FOR_EXCEPTION();
+
+ if (baseValue.isCell()
+ && slot.isCacheable()
+ && !asCell(baseValue)->structure()->isUncacheableDictionary()
+ && 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(CodeLocationLabel(), 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(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
+ } else
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
+ return JSValue::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 = CodeLocationLabel();
+ 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 = CodeLocationLabel();
+ 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;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ const Identifier& propertyName = stackFrame.args[1].identifier();
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(callFrame, propertyName, slot);
+
+ CHECK_FOR_EXCEPTION();
+
+ if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isUncacheableDictionary()) {
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+ return JSValue::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());
+
+ size_t offset = slot.cachedOffset();
+
+ if (slot.slotBase() == baseValue)
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(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->flattenDictionaryObject();
+ offset = slotBaseObject->structure()->get(propertyName);
+ }
+
+ int listIndex;
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+
+ JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset);
+
+ if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
+ } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+ return JSValue::encode(result);
+ }
+
+ int listIndex;
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+ JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset);
+
+ if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
+ } else
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+#endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue value = stackFrame.args[0].jsValue();
+ JSValue baseVal = stackFrame.args[1].jsValue();
+ JSValue proto = stackFrame.args[2].jsValue();
+
+ // 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);
+
+
+ // ECMA-262 15.3.5.3:
+ // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
+ TypeInfo typeInfo(UnspecifiedType, 0);
+ if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+ ASSERT(typeInfo.type() != UnspecifiedType);
+
+ if (!typeInfo.overridesHasInstance()) {
+ if (!value.isObject())
+ return JSValue::encode(jsBoolean(false));
+
+ if (!proto.isObject()) {
+ throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
+ VM_THROW_EXCEPTION();
+ }
+ }
+
+ JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
+
+ JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValue::encode(jsNumber(stackFrame.globalData, left * right));
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return stackFrame.args[0].funcDeclNode()->makeFunction(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
+}
+
+DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+#ifndef NDEBUG
+ CallData callData;
+ ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS);
+#endif
+
+ JSFunction* function = asFunction(stackFrame.args[0].jsValue());
+ ASSERT(!function->isHostFunction());
+ FunctionBodyNode* body = function->body();
+ ScopeChainNode* callDataScopeChain = function->scope().node();
+ body->jitCode(callDataScopeChain);
+
+ return &(body->generatedBytecode());
+}
+
+DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* newCodeBlock = stackFrame.args[3].codeBlock();
+ ASSERT(newCodeBlock->codeType() != NativeCode);
+ int argCount = stackFrame.args[2].int32();
+
+ 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 (!stackFrame.registerFile->grow(newEnd)) {
+ // Rewind to the previous call frame because op_call already optimistically
+ // moved the call frame forward.
+ stackFrame.callFrame = oldCallFrame;
+ throwStackOverflowError(oldCallFrame, stackFrame.globalData, stackFrame.args[1].returnAddress(), STUB_RETURN_ADDRESS);
+ RETURN_POINTER_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_POINTER_PAIR(newCodeBlock, callFrame);
+}
+
+#if ENABLE(JIT_OPTIMIZE_CALL)
+DEFINE_STUB_FUNCTION(void*, vm_dontLazyLinkCall)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSGlobalData* globalData = stackFrame.globalData;
+ JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+
+ ctiPatchNearCallByReturnAddress(stackFrame.callFrame->callerFrame()->codeBlock(), stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());
+
+ return callee->body()->generatedJITCode().addressForCall().executableAddress();
+}
+
+DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+ JITCode& jitCode = callee->body()->generatedJITCode();
+
+ CodeBlock* codeBlock = 0;
+ if (!callee->isHostFunction())
+ codeBlock = &callee->body()->bytecode(callee->scope().node());
+ else
+ codeBlock = &callee->body()->generatedBytecode();
+
+ CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
+ JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
+
+ return jitCode.addressForCall().executableAddress();
+}
+#endif // !ENABLE(JIT_OPTIMIZE_CALL)
+
+DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionBodyNode*>(stackFrame.callFrame->codeBlock()->ownerNode()));
+ stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
+ return activation;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue funcVal = stackFrame.args[0].jsValue();
+
+ CallData callData;
+ CallType callType = funcVal.getCallData(callData);
+
+ ASSERT(callType != CallTypeJS);
+
+ if (callType == CallTypeHost) {
+ int registerOffset = stackFrame.args[1].int32();
+ int argCount = stackFrame.args[2].int32();
+ CallFrame* previousCallFrame = stackFrame.callFrame;
+ CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
+
+ callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
+ stackFrame.callFrame = callFrame;
+
+ Register* argv = stackFrame.callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
+ ArgList argList(argv + 1, argCount - 1);
+
+ JSValue returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+
+ // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
+ JSValue thisValue = argv[0].jsValue();
+ if (thisValue == jsNull())
+ thisValue = callFrame->globalThisValue();
+
+ returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
+ }
+ stackFrame.callFrame = previousCallFrame;
+ CHECK_FOR_EXCEPTION();
+
+ return JSValue::encode(returnValue);
+ }
+
+ ASSERT(callType == CallTypeNone);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+DEFINE_STUB_FUNCTION(void, op_create_arguments)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
+ stackFrame.callFrame->setCalleeArguments(arguments);
+ stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
+}
+
+DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
+ stackFrame.callFrame->setCalleeArguments(arguments);
+ stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
+}
+
+DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
+ asActivation(stackFrame.args[0].jsValue())->copyRegisters(stackFrame.callFrame->optionalCalleeArguments());
+}
+
+DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
+ if (stackFrame.callFrame->optionalCalleeArguments())
+ stackFrame.callFrame->optionalCalleeArguments()->copyRegisters();
+}
+
+DEFINE_STUB_FUNCTION(void, op_profile_will_call)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ASSERT(*stackFrame.enabledProfilerReference);
+ (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+}
+
+DEFINE_STUB_FUNCTION(void, op_profile_did_call)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ASSERT(*stackFrame.enabledProfilerReference);
+ (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+}
+
+DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
+ stackFrame.callFrame->scopeChain()->deref();
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
+ return constructArray(stackFrame.callFrame, argList);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+
+ Identifier& ident = stackFrame.args[0].identifier();
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValue result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+ }
+ } while (++iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSFunction* constructor = asFunction(stackFrame.args[0].jsValue());
+ if (constructor->isHostFunction()) {
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createNotAConstructorError(callFrame, constructor, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+
+#ifndef NDEBUG
+ ConstructData constructData;
+ ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
+#endif
+
+ Structure* structure;
+ if (stackFrame.args[3].jsValue().isObject())
+ structure = asObject(stackFrame.args[3].jsValue())->inheritorID();
+ else
+ structure = constructor->scope().node()->globalObject()->emptyObjectStructure();
+ return new (stackFrame.globalData) JSObject(structure);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue constrVal = stackFrame.args[0].jsValue();
+ int argCount = stackFrame.args[2].int32();
+ int thisRegister = stackFrame.args[4].int32();
+
+ ConstructData constructData;
+ ConstructType constructType = constrVal.getConstructData(constructData);
+
+ if (constructType == ConstructTypeHost) {
+ ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
+
+ JSValue returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+ returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
+ }
+ CHECK_FOR_EXCEPTION();
+
+ return JSValue::encode(returnValue);
+ }
+
+ ASSERT(constructType == ConstructTypeNone);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSValue subscript = stackFrame.args[1].jsValue();
+
+ JSValue result;
+
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSArray(globalData, baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canGetIndex(i))
+ result = jsArray->getIndex(i);
+ else
+ result = jsArray->JSArray::get(callFrame, i);
+ } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
+ result = asString(baseValue)->getIndex(stackFrame.globalData, i);
+ } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
+ return JSValue::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 JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSValue subscript = stackFrame.args[1].jsValue();
+
+ JSValue result;
+
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
+ result = asString(baseValue)->getIndex(stackFrame.globalData, i);
+ else {
+ result = baseValue.get(callFrame, i);
+ if (!isJSString(globalData, baseValue))
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
+ }
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ result = baseValue.get(callFrame, property);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSValue subscript = stackFrame.args[1].jsValue();
+
+ JSValue result;
+
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
+ return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
+ }
+
+ result = baseValue.get(callFrame, i);
+ if (!isJSByteArray(globalData, baseValue))
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ result = baseValue.get(callFrame, property);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValue::encode(jsNumber(stackFrame.globalData, left - right));
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_val)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSValue subscript = stackFrame.args[1].jsValue();
+ JSValue value = stackFrame.args[2].jsValue();
+
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSArray(globalData, baseValue)) {
+ JSArray* jsArray = asArray(baseValue);
+ if (jsArray->canSetIndex(i))
+ jsArray->setIndex(i, value);
+ else
+ jsArray->JSArray::put(callFrame, i, value);
+ } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ JSByteArray* jsByteArray = asByteArray(baseValue);
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(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.isInt32()) {
+ jsByteArray->setIndex(i, value.asInt32());
+ 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 (!stackFrame.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();
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_val_array)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ int i = stackFrame.args[1].int32();
+ JSValue value = stackFrame.args[2].jsValue();
+
+ ASSERT(isJSArray(stackFrame.globalData, baseValue));
+
+ if (LIKELY(i >= 0))
+ asArray(baseValue)->JSArray::put(callFrame, i, value);
+ else {
+ Identifier property(callFrame, UString::from(i));
+ PutPropertySlot slot;
+ baseValue.put(callFrame, property, value, slot);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSValue subscript = stackFrame.args[1].jsValue();
+ JSValue value = stackFrame.args[2].jsValue();
+
+ if (LIKELY(subscript.isUInt32())) {
+ uint32_t i = subscript.asUInt32();
+ if (isJSByteArray(globalData, 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.isInt32()) {
+ jsByteArray->setIndex(i, value.asInt32());
+ return;
+ } else {
+ double dValue = 0;
+ if (value.getNumber(dValue)) {
+ jsByteArray->setIndex(i, dValue);
+ return;
+ }
+ }
+ }
+
+ if (!isJSByteArray(globalData, baseValue))
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
+ baseValue.put(callFrame, i, value);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame));
+ if (!stackFrame.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();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(int, op_loop_if_true)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = src1.toBoolean(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(int, op_load_varargs)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ RegisterFile* registerFile = stackFrame.registerFile;
+ int argsOffset = stackFrame.args[0].int32();
+ JSValue arguments = callFrame->registers()[argsOffset].jsValue();
+ uint32_t argCount = 0;
+ if (!arguments) {
+ int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
+ argCount = providedParams;
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ stackFrame.globalData->exception = createStackOverflowError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ int32_t expectedParams = callFrame->callee()->body()->parameterCount();
+ int32_t inplaceArgs = min(providedParams, expectedParams);
+
+ Register* inplaceArgsDst = callFrame->registers() + argsOffset;
+
+ Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs;
+ Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams;
+
+ Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams;
+ Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs;
+
+ // First step is to copy the "expected" parameters from their normal location relative to the callframe
+ while (inplaceArgsDst < inplaceArgsEnd)
+ *inplaceArgsDst++ = *inplaceArgsSrc++;
+
+ // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
+ while (inplaceArgsDst < inplaceArgsEnd2)
+ *inplaceArgsDst++ = *inplaceArgsSrc2++;
+
+ } else if (!arguments.isUndefinedOrNull()) {
+ if (!arguments.isObject()) {
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+ if (asObject(arguments)->classInfo() == &Arguments::info) {
+ Arguments* argsObject = asArguments(arguments);
+ argCount = argsObject->numProvidedArguments(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ stackFrame.globalData->exception = createStackOverflowError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (isJSArray(&callFrame->globalData(), arguments)) {
+ JSArray* array = asArray(arguments);
+ argCount = array->length();
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ stackFrame.globalData->exception = createStackOverflowError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (asObject(arguments)->inherits(&JSArray::info)) {
+ JSObject* argObject = asObject(arguments);
+ argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ stackFrame.globalData->exception = createStackOverflowError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ Register* argsBuffer = callFrame->registers() + argsOffset;
+ for (unsigned i = 0; i < argCount; ++i) {
+ argsBuffer[i] = asObject(arguments)->get(callFrame, i);
+ CHECK_FOR_EXCEPTION();
+ }
+ } else {
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+ }
+
+ return argCount + 1;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src = stackFrame.args[0].jsValue();
+
+ double v;
+ if (src.getNumber(v))
+ return JSValue::encode(jsNumber(stackFrame.globalData, -v));
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, -src.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ int skip = stackFrame.args[1].int32();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+ ASSERT(iter != end);
+ while (skip--) {
+ ++iter;
+ ASSERT(iter != end);
+ }
+ Identifier& ident = stackFrame.args[0].identifier();
+ do {
+ JSObject* o = *iter;
+ PropertySlot slot(o);
+ if (o->getPropertySlot(callFrame, ident, slot)) {
+ JSValue result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+ }
+ } while (++iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSGlobalObject* globalObject = stackFrame.args[0].globalObject();
+ Identifier& ident = stackFrame.args[1].identifier();
+ unsigned globalResolveInfoIndex = stackFrame.args[2].int32();
+ ASSERT(globalObject->isGlobalObject());
+
+ PropertySlot slot(globalObject);
+ if (globalObject->getPropertySlot(callFrame, ident, slot)) {
+ JSValue result = slot.getValue(callFrame, ident);
+ if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
+ GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
+ if (globalResolveInfo.structure)
+ globalResolveInfo.structure->deref();
+ globalObject->structure()->ref();
+ globalResolveInfo.structure = globalObject->structure();
+ globalResolveInfo.offset = slot.cachedOffset();
+ return JSValue::encode(result);
+ }
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+ }
+
+ unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
+ VM_THROW_EXCEPTION();
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ double left;
+ double right;
+ if (src1.getNumber(left) && src2.getNumber(right))
+ return JSValue::encode(jsNumber(stackFrame.globalData, left / right));
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) - 1);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(int, op_jless)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = jsLess(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(int, op_jlesseq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = jsLessEq(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_not)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue result = jsBoolean(!src.toBoolean(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(int, op_jtrue)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = src1.toBoolean(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue number = v.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() + 1);
+ return JSValue::encode(number);
+}
+
+#if USE(JSVALUE32_64)
+
+DEFINE_STUB_FUNCTION(int, op_eq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ start:
+ if (src2.isUndefined()) {
+ return src1.isNull() ||
+ (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
+ src1.isUndefined();
+ }
+
+ if (src2.isNull()) {
+ return src1.isUndefined() ||
+ (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
+ src1.isNull();
+ }
+
+ if (src1.isInt32()) {
+ if (src2.isDouble())
+ return src1.asInt32() == src2.asDouble();
+ double d = src2.toNumber(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ return src1.asInt32() == d;
+ }
+
+ if (src1.isDouble()) {
+ if (src2.isInt32())
+ return src1.asDouble() == src2.asInt32();
+ double d = src2.toNumber(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ return src1.asDouble() == d;
+ }
+
+ if (src1.isTrue()) {
+ if (src2.isFalse())
+ return false;
+ double d = src2.toNumber(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ return d == 1.0;
+ }
+
+ if (src1.isFalse()) {
+ if (src2.isTrue())
+ return false;
+ double d = src2.toNumber(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ return d == 0.0;
+ }
+
+ if (src1.isUndefined())
+ return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
+
+ if (src1.isNull())
+ return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
+
+ ASSERT(src1.isCell());
+
+ JSCell* cell1 = asCell(src1);
+
+ if (cell1->isString()) {
+ if (src2.isInt32())
+ return static_cast<JSString*>(cell1)->value().toDouble() == src2.asInt32();
+
+ if (src2.isDouble())
+ return static_cast<JSString*>(cell1)->value().toDouble() == src2.asDouble();
+
+ if (src2.isTrue())
+ return static_cast<JSString*>(cell1)->value().toDouble() == 1.0;
+
+ if (src2.isFalse())
+ return static_cast<JSString*>(cell1)->value().toDouble() == 0.0;
+
+ ASSERT(src2.isCell());
+ JSCell* cell2 = asCell(src2);
+ if (cell2->isString())
+ return static_cast<JSString*>(cell1)->value() == static_cast<JSString*>(cell2)->value();
+
+ ASSERT(cell2->isObject());
+ src2 = static_cast<JSObject*>(cell2)->toPrimitive(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ goto start;
+ }
+
+ ASSERT(cell1->isObject());
+ if (src2.isObject())
+ return static_cast<JSObject*>(cell1) == asObject(src2);
+ src1 = static_cast<JSObject*>(cell1)->toPrimitive(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ goto start;
+}
+
+DEFINE_STUB_FUNCTION(int, op_eq_strings)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSString* string1 = stackFrame.args[0].jsString();
+ JSString* string2 = stackFrame.args[1].jsString();
+
+ ASSERT(string1->isString());
+ ASSERT(string2->isString());
+ return string1->value() == string2->value();
+}
+
+#else // USE(JSVALUE32_64)
+
+DEFINE_STUB_FUNCTION(int, op_eq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return result;
+}
+
+#endif // USE(JSVALUE32_64)
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue val = stackFrame.args[0].jsValue();
+ JSValue shift = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ ASSERT(!src1.isInt32() || !src2.isInt32());
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue val = stackFrame.args[0].jsValue();
+ JSValue shift = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src = stackFrame.args[0].jsValue();
+
+ ASSERT(!src.isInt32());
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, ~src.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+
+ ScopeChainIterator iter = scopeChain->begin();
+ ScopeChainIterator end = scopeChain->end();
+
+ // FIXME: add scopeDepthIsZero optimization
+
+ ASSERT(iter != end);
+
+ Identifier& ident = stackFrame.args[0].identifier();
+ JSObject* base;
+ do {
+ base = *iter;
+ PropertySlot slot(base);
+ if (base->getPropertySlot(callFrame, ident, slot)) {
+ JSValue result = slot.getValue(callFrame, ident);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
+ return JSValue::encode(result);
+ }
+ ++iter;
+ } while (iter != end);
+
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION_AT_END();
+ return JSValue::encode(JSValue());
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return stackFrame.args[0].funcExprNode()->makeFunction(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue dividendValue = stackFrame.args[0].jsValue();
+ JSValue divisorValue = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ double d = dividendValue.toNumber(callFrame);
+ JSValue result = jsNumber(stackFrame.globalData, fmod(d, divisorValue.toNumber(callFrame)));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v = stackFrame.args[0].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue number = v.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+
+ callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() - 1);
+ return JSValue::encode(number);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue val = stackFrame.args[0].jsValue();
+ JSValue shift = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue result = jsNumber(stackFrame.globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp());
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ RegisterFile* registerFile = stackFrame.registerFile;
+
+ Interpreter* interpreter = stackFrame.globalData->interpreter;
+
+ JSValue funcVal = stackFrame.args[0].jsValue();
+ int registerOffset = stackFrame.args[1].int32();
+ int argCount = stackFrame.args[2].int32();
+
+ Register* newCallFrame = callFrame->registers() + registerOffset;
+ Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
+ JSValue thisValue = argv[0].jsValue();
+ JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
+
+ if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
+ JSValue exceptionValue;
+ JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
+ if (UNLIKELY(exceptionValue)) {
+ stackFrame.globalData->exception = exceptionValue;
+ VM_THROW_EXCEPTION_AT_END();
+ }
+ return JSValue::encode(result);
+ }
+
+ return JSValue::encode(JSValue());
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+
+ JSValue exceptionValue = stackFrame.args[0].jsValue();
+ ASSERT(exceptionValue);
+
+ HandlerInfo* handler = stackFrame.globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
+
+ if (!handler) {
+ *stackFrame.exception = exceptionValue;
+ STUB_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiOpThrowNotCaught));
+ return JSValue::encode(jsNull());
+ }
+
+ stackFrame.callFrame = callFrame;
+ void* catchRoutine = handler->nativeCode.executableAddress();
+ ASSERT(catchRoutine);
+ STUB_SET_RETURN_ADDRESS(catchRoutine);
+ return JSValue::encode(exceptionValue);
+}
+
+DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSPropertyNameIterator::create(stackFrame.callFrame, stackFrame.args[0].jsValue());
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_next_pname)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSPropertyNameIterator* it = stackFrame.args[0].propertyNameIterator();
+ JSValue temp = it->next(stackFrame.callFrame);
+ if (!temp)
+ it->invalidate();
+ return JSValue::encode(temp);
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
+ CHECK_FOR_EXCEPTION();
+ stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
+ return o;
+}
+
+DEFINE_STUB_FUNCTION(void, op_pop_scope)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue v = stackFrame.args[0].jsValue();
+ return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ return JSValue::encode(jsBoolean(JSValue::strictEqual(src1, src2)));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ return JSValue::encode(concatenateStrings(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src1 = stackFrame.args[0].jsValue();
+ JSValue src2 = stackFrame.args[1].jsValue();
+
+ return JSValue::encode(jsBoolean(!JSValue::strictEqual(src1, src2)));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue src = stackFrame.args[0].jsValue();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue result = src.toJSNumber(callFrame);
+ CHECK_FOR_EXCEPTION_AT_END();
+ return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ JSValue baseVal = stackFrame.args[1].jsValue();
+
+ if (!baseVal.isObject()) {
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
+ stackFrame.globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
+ VM_THROW_EXCEPTION();
+ }
+
+ JSValue propName = stackFrame.args[0].jsValue();
+ JSObject* baseObj = asObject(baseVal);
+
+ uint32_t i;
+ if (propName.getUInt32(i))
+ return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
+
+ Identifier property(callFrame, propName.toString(callFrame));
+ CHECK_FOR_EXCEPTION();
+ return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
+ return scope;
+}
+
+DEFINE_STUB_FUNCTION(void, op_jmp_scopes)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ unsigned count = stackFrame.args[0].int32();
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ ScopeChainNode* tmp = callFrame->scopeChain();
+ while (count--)
+ tmp = tmp->pop();
+ callFrame->setScopeChain(tmp);
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_by_index)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ unsigned property = stackFrame.args[1].int32();
+
+ stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
+}
+
+DEFINE_STUB_FUNCTION(void*, op_switch_imm)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue scrutinee = stackFrame.args[0].jsValue();
+ unsigned tableIndex = stackFrame.args[1].int32();
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ if (scrutinee.isInt32())
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
+ else {
+ double value;
+ int32_t intValue;
+ if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
+ else
+ return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
+ }
+}
+
+DEFINE_STUB_FUNCTION(void*, op_switch_char)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue scrutinee = stackFrame.args[0].jsValue();
+ unsigned tableIndex = stackFrame.args[1].int32();
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
+
+ if (scrutinee.isString()) {
+ UString::Rep* value = asString(scrutinee)->value().rep();
+ if (value->size() == 1)
+ result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
+ }
+
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(void*, op_switch_string)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ JSValue scrutinee = stackFrame.args[0].jsValue();
+ unsigned tableIndex = stackFrame.args[1].int32();
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+
+ void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
+
+ if (scrutinee.isString()) {
+ UString::Rep* value = asString(scrutinee)->value().rep();
+ result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
+ }
+
+ return result;
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ JSValue baseValue = stackFrame.args[0].jsValue();
+ JSObject* baseObj = baseValue.toObject(callFrame); // may throw
+
+ JSValue subscript = stackFrame.args[1].jsValue();
+ JSValue 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 JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_getter)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ ASSERT(stackFrame.args[0].jsValue().isObject());
+ JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
+ ASSERT(stackFrame.args[2].jsValue().isObject());
+ baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
+}
+
+DEFINE_STUB_FUNCTION(void, op_put_setter)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ ASSERT(stackFrame.args[0].jsValue().isObject());
+ JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
+ ASSERT(stackFrame.args[2].jsValue().isObject());
+ baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
+}
+
+DEFINE_STUB_FUNCTION(JSObject*, op_new_error)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ unsigned type = stackFrame.args[0].int32();
+ JSValue message = stackFrame.args[1].jsValue();
+ unsigned bytecodeOffset = stackFrame.args[2].int32();
+
+ unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+ return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+}
+
+DEFINE_STUB_FUNCTION(void, op_debug)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+
+ int debugHookID = stackFrame.args[0].int32();
+ int firstLine = stackFrame.args[1].int32();
+ int lastLine = stackFrame.args[2].int32();
+
+ stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ JSGlobalData* globalData = stackFrame.globalData;
+
+ unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
+
+ JSValue exceptionValue = globalData->exception;
+ ASSERT(exceptionValue);
+ globalData->exception = JSValue();
+
+ HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
+
+ if (!handler) {
+ *stackFrame.exception = exceptionValue;
+ return JSValue::encode(jsNull());
+ }
+
+ stackFrame.callFrame = callFrame;
+ void* catchRoutine = handler->nativeCode.executableAddress();
+ ASSERT(catchRoutine);
+ STUB_SET_RETURN_ADDRESS(catchRoutine);
+ return JSValue::encode(exceptionValue);
+}
+
+} // 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.
+ * 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 JITStubs_h
+#define JITStubs_h
+
+#include <wtf/Platform.h>
+
+#include "MacroAssemblerCodeRef.h"
+#include "Register.h"
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+ class CodeBlock;
+ class ExecutablePool;
+ class Identifier;
+ class JSGlobalData;
+ class JSGlobalData;
+ class JSObject;
+ class JSPropertyNameIterator;
+ class JSValue;
+ class JSValueEncodedAsPointer;
+ class Profiler;
+ class PropertySlot;
+ class PutPropertySlot;
+ class RegisterFile;
+ class FuncDeclNode;
+ class FuncExprNode;
+ class JSGlobalObject;
+ class RegExp;
+
+ union JITStubArg {
+ void* asPointer;
+ EncodedJSValue asEncodedJSValue;
+ int32_t asInt32;
+
+ JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
+ Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
+ int32_t int32() { return asInt32; }
+ CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
+ FuncDeclNode* funcDeclNode() { return static_cast<FuncDeclNode*>(asPointer); }
+ FuncExprNode* funcExprNode() { return static_cast<FuncExprNode*>(asPointer); }
+ RegExp* regExp() { return static_cast<RegExp*>(asPointer); }
+ JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
+ JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
+ JSString* jsString() { return static_cast<JSString*>(asPointer); }
+ ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
+ };
+
+#if PLATFORM(X86_64)
+ struct JITStackFrame {
+ void* reserved; // Unused
+ JITStubArg args[6];
+ void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill).
+
+ void* savedRBX;
+ void* savedR15;
+ void* savedR14;
+ void* savedR13;
+ void* savedR12;
+ void* savedRBP;
+ void* savedRIP;
+
+ void* code;
+ RegisterFile* registerFile;
+ CallFrame* callFrame;
+ JSValue* exception;
+ Profiler** enabledProfilerReference;
+ JSGlobalData* globalData;
+
+ // When JIT code makes a call, it pushes its return address just below the rest of the stack.
+ ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
+ };
+#elif PLATFORM(X86)
+#if COMPILER(MSVC)
+#pragma pack(push)
+#pragma pack(4)
+#endif // COMPILER(MSVC)
+ struct JITStackFrame {
+ void* reserved; // Unused
+ JITStubArg args[6];
+#if USE(JSVALUE32_64)
+ void* padding[2]; // Maintain 16-byte stack alignment.
+#endif
+
+ void* savedEBX;
+ void* savedEDI;
+ void* savedESI;
+ void* savedEBP;
+ void* savedEIP;
+
+ void* code;
+ RegisterFile* registerFile;
+ CallFrame* callFrame;
+ JSValue* exception;
+ Profiler** enabledProfilerReference;
+ JSGlobalData* globalData;
+
+ // When JIT code makes a call, it pushes its return address just below the rest of the stack.
+ ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
+ };
+#if COMPILER(MSVC)
+#pragma pack(pop)
+#endif // COMPILER(MSVC)
+#elif PLATFORM_ARM_ARCH(7)
+ struct JITStackFrame {
+ void* reserved; // Unused
+ JITStubArg args[6];
+#if USE(JSVALUE32_64)
+ void* padding[2]; // Maintain 16-byte stack alignment.
+#endif
+
+ ReturnAddressPtr thunkReturnAddress;
+
+ void* preservedReturnAddress;
+ void* preservedR4;
+ void* preservedR5;
+ void* preservedR6;
+
+ // These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved)
+ RegisterFile* registerFile;
+ CallFrame* callFrame;
+ JSValue* exception;
+
+ // These arguments passed on the stack.
+ Profiler** enabledProfilerReference;
+ JSGlobalData* globalData;
+
+ ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
+ };
+#else
+#error "JITStackFrame not defined for this platform."
+#endif
+
+#if USE(JIT_STUB_ARGUMENT_VA_LIST)
+ #define STUB_ARGS_DECLARATION void* args, ...
+ #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1)
+
+ #if COMPILER(MSVC)
+ #define JIT_STUB __cdecl
+ #else
+ #define JIT_STUB
+ #endif
+#else
+ #define STUB_ARGS_DECLARATION void** args
+ #define STUB_ARGS (args)
+
+ #if PLATFORM(X86) && COMPILER(MSVC)
+ #define JIT_STUB __fastcall
+ #elif PLATFORM(X86) && COMPILER(GCC)
+ #define JIT_STUB __attribute__ ((fastcall))
+ #else
+ #define JIT_STUB
+ #endif
+#endif
+
+#if PLATFORM(X86_64)
+ struct VoidPtrPair {
+ void* first;
+ void* second;
+ };
+ #define RETURN_POINTER_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
+#else
+ // MSVC doesn't support returning a two-value struct in two registers, so
+ // we cast the struct to int64_t instead.
+ typedef uint64_t VoidPtrPair;
+ union VoidPtrPairUnion {
+ struct { void* first; void* second; } s;
+ VoidPtrPair i;
+ };
+ #define RETURN_POINTER_PAIR(a,b) VoidPtrPairUnion pair = {{ a, b }}; return pair.i
+#endif
+
+ extern "C" void ctiVMThrowTrampoline();
+ extern "C" void ctiOpThrowNotCaught();
+ extern "C" EncodedJSValue 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*, JSValue* exception, Profiler**, JSGlobalData*);
+
+ class JITThunks {
+ public:
+ JITThunks(JSGlobalData*);
+
+ static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
+ static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&);
+
+ MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_ctiStringLengthTrampoline; }
+ MacroAssemblerCodePtr ctiVirtualCallPreLink() { return m_ctiVirtualCallPreLink; }
+ MacroAssemblerCodePtr ctiVirtualCallLink() { return m_ctiVirtualCallLink; }
+ MacroAssemblerCodePtr ctiVirtualCall() { return m_ctiVirtualCall; }
+ MacroAssemblerCodePtr ctiNativeCallThunk() { return m_ctiNativeCallThunk; }
+
+ private:
+ RefPtr<ExecutablePool> m_executablePool;
+
+ MacroAssemblerCodePtr m_ctiStringLengthTrampoline;
+ MacroAssemblerCodePtr m_ctiVirtualCallPreLink;
+ MacroAssemblerCodePtr m_ctiVirtualCallLink;
+ MacroAssemblerCodePtr m_ctiVirtualCall;
+ MacroAssemblerCodePtr m_ctiNativeCallThunk;
+ };
+
+extern "C" {
+ EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_bitnot(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_method_check_second(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_second(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_boolean(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_function(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_number(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_object(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_string(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_next_pname(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_post_inc(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_pre_dec(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION);
+ JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION);
+ JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION);
+ VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION);
+#if USE(JSVALUE32_64)
+ int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION);
+#endif
+ int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_loop_if_less(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION);
+ int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_second(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_val_array(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_vm_dontLazyLinkCall(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
+} // extern "C"
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JITStubs_h
#include "Completion.h"
#include "InitializeThreading.h"
#include "JSArray.h"
+#include "JSFunction.h"
#include "JSLock.h"
#include "PrototypeFunction.h"
#include "SamplingTool.h"
#include <sys/time.h>
#endif
-#if PLATFORM(UNIX)
+#if HAVE(SIGNAL_H)
#include <signal.h>
#endif
-#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
+#if COMPILER(MSVC) && !PLATFORM(WINCE)
#include <crtdbg.h>
#include <windows.h>
+#include <mmsystem.h>
#endif
#if PLATFORM(QT)
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&);
+static JSValue JSC_HOST_CALL functionPrint(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionDebug(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionGC(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionRun(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionLoad(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionCheckSyntax(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionReadline(ExecState*, JSObject*, JSValue, const ArgList&);
+static NO_RETURN JSValue JSC_HOST_CALL functionQuit(ExecState*, JSObject*, JSValue, const ArgList&);
+
+#if ENABLE(SAMPLING_FLAGS)
+static JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
+#endif
+
+struct Script {
+ bool isFile;
+ char *argument;
+
+ Script(bool isFile, char *argument)
+ : isFile(isFile)
+ , argument(argument)
+ {
+ }
+};
struct Options {
Options()
bool interactive;
bool dump;
- Vector<UString> fileNames;
+ Vector<Script> scripts;
Vector<UString> arguments;
};
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));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
+
+#if ENABLE(SAMPLING_FLAGS)
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
+ putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
+#endif
JSObject* array = constructEmptyArray(globalExec());
for (size_t i = 0; i < arguments.size(); ++i)
putDirect(Identifier(globalExec(), "arguments"), array);
}
-JSValuePtr functionPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, 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());
+ printf("%s", args.at(i).toString(exec).UTF8String().c_str());
}
putchar('\n');
return jsUndefined();
}
-JSValuePtr functionDebug(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- fprintf(stderr, "--> %s\n", args.at(exec, 0).toString(exec).UTF8String().c_str());
+ fprintf(stderr, "--> %s\n", args.at(0).toString(exec).UTF8String().c_str());
return jsUndefined();
}
-JSValuePtr functionGC(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
JSLock lock(false);
exec->heap()->collect();
return jsUndefined();
}
-JSValuePtr functionVersion(ExecState*, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, 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)
+JSValue JSC_HOST_CALL functionRun(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
StopWatch stopWatch;
- UString fileName = args.at(exec, 0).toString(exec);
+ UString fileName = args.at(0).toString(exec);
Vector<char> script;
if (!fillBufferWithContentsOfFile(fileName, script))
return throwError(exec, GeneralError, "Could not open file.");
return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
}
-JSValuePtr functionLoad(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL functionLoad(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
{
- UString fileName = args.at(exec, 0).toString(exec);
+ UNUSED_PARAM(o);
+ UNUSED_PARAM(v);
+ UString fileName = args.at(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));
+ Completion result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+ if (result.complType() == Throw)
+ exec->setException(result.value());
+ return result.value();
+}
- return jsUndefined();
+JSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
+{
+ UNUSED_PARAM(o);
+ UNUSED_PARAM(v);
+ UString fileName = args.at(0).toString(exec);
+ Vector<char> script;
+ if (!fillBufferWithContentsOfFile(fileName, script))
+ return throwError(exec, GeneralError, "Could not open file.");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
+ if (result.complType() == Throw)
+ exec->setException(result.value());
+ return result.value();
}
-JSValuePtr functionReadline(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+#if ENABLE(SAMPLING_FLAGS)
+JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ for (unsigned i = 0; i < args.size(); ++i) {
+ unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+ if ((flag >= 1) && (flag <= 32))
+ SamplingFlags::setFlag(flag);
+ }
+ return jsNull();
+}
+
+JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ for (unsigned i = 0; i < args.size(); ++i) {
+ unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+ if ((flag >= 1) && (flag <= 32))
+ SamplingFlags::clearFlag(flag);
+ }
+ return jsNull();
+}
+#endif
+
+JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
Vector<char, 256> line;
int c;
return jsString(exec, line.data());
}
-JSValuePtr functionQuit(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
cleanupGlobalData(&exec->globalData());
exit(EXIT_SUCCESS);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
#endif
+#if COMPILER(MSVC) && !PLATFORM(WINCE)
+ timeBeginPeriod(1);
+#endif
+
#if PLATFORM(QT)
QCoreApplication app(argc, argv);
#endif
globalData->deref();
}
-static bool runWithScripts(GlobalObject* globalObject, const Vector<UString>& fileNames, bool dump)
+static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
{
- Vector<char> script;
+ UString script;
+ UString fileName;
+ Vector<char> scriptBuffer;
if (dump)
BytecodeGenerator::setDumpsGeneratedCode(true);
#if ENABLE(OPCODE_SAMPLING)
Interpreter* interpreter = globalObject->globalData()->interpreter;
interpreter->setSampler(new SamplingTool(interpreter));
+ interpreter->sampler()->setup();
+#endif
+#if ENABLE(SAMPLING_FLAGS)
+ SamplingFlags::start();
#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
+ for (size_t i = 0; i < scripts.size(); i++) {
+ if (scripts[i].isFile) {
+ fileName = scripts[i].argument;
+ if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
+ return false; // fail early so we can catch missing files
+ script = scriptBuffer.data();
+ } else {
+ script = scripts[i].argument;
+ fileName = "[Command Line]";
+ }
-#if ENABLE(OPCODE_SAMPLING)
- interpreter->sampler()->start();
+#if ENABLE(SAMPLING_THREAD)
+ SamplingThread::start();
#endif
- Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+
+ Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
success = success && completion.complType() != Throw;
if (dump) {
if (completion.complType() == Throw)
printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
}
- globalObject->globalExec()->clearException();
-
-#if ENABLE(OPCODE_SAMPLING)
- interpreter->sampler()->stop();
+#if ENABLE(SAMPLING_THREAD)
+ SamplingThread::stop();
#endif
+
+ globalObject->globalExec()->clearException();
}
+#if ENABLE(SAMPLING_FLAGS)
+ SamplingFlags::stop();
+#endif
#if ENABLE(OPCODE_SAMPLING)
interpreter->sampler()->dump(globalObject->globalExec());
delete interpreter->sampler();
+#endif
+#if ENABLE(SAMPLING_COUNTERS)
+ AbstractSamplingCounter::dump();
#endif
return success;
}
+#define RUNNING_FROM_XCODE 0
+
static void runInteractive(GlobalObject* globalObject)
{
while (true) {
-#if HAVE(READLINE)
+#if HAVE(READLINE) && !RUNNING_FROM_XCODE
char* line = readline(interactivePrompt);
if (!line)
break;
Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
free(line);
#else
- puts(interactivePrompt);
+ printf("%s", interactivePrompt);
Vector<char, 256> line;
int c;
while ((c = getchar()) != EOF) {
break;
line.append(c);
}
+ if (line.isEmpty())
+ break;
line.append('\0');
Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
#endif
printf("\n");
}
-static NO_RETURN void printUsageStatement()
+static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false)
{
fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
+ fprintf(stderr, " -e Evaluate argument as script code\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");
+#if HAVE(SIGNAL_H)
fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
- exit(EXIT_FAILURE);
+#endif
+
+ cleanupGlobalData(globalData);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
-static void parseArguments(int argc, char** argv, Options& options)
+static void parseArguments(int argc, char** argv, Options& options, JSGlobalData* globalData)
{
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]);
+ printUsageStatement(globalData);
+ options.scripts.append(Script(true, argv[i]));
+ continue;
+ }
+ if (strcmp(arg, "-e") == 0) {
+ if (++i == argc)
+ printUsageStatement(globalData);
+ options.scripts.append(Script(false, argv[i]));
continue;
}
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
- printUsageStatement();
+ printUsageStatement(globalData, true);
}
if (strcmp(arg, "-i") == 0) {
options.interactive = true;
continue;
}
if (strcmp(arg, "-s") == 0) {
-#if PLATFORM(UNIX)
+#if HAVE(SIGNAL_H)
signal(SIGILL, _exit);
signal(SIGFPE, _exit);
signal(SIGBUS, _exit);
++i;
break;
}
- options.fileNames.append(argv[i]);
+ options.scripts.append(Script(true, argv[i]));
}
- if (options.fileNames.isEmpty())
+ if (options.scripts.isEmpty())
options.interactive = true;
for (; i < argc; ++i)
JSLock lock(false);
Options options;
- parseArguments(argc, argv, options);
+ parseArguments(argc, argv, options, globalData);
GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
- bool success = runWithScripts(globalObject, options.fileNames, options.dump);
+ bool success = runWithScripts(globalObject, options.scripts, options.dump);
if (options.interactive && success)
runInteractive(globalObject);
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
isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/..
include($$OUTPUT_DIR/config.pri)
-OBJECTS_DIR = tmp
-OBJECTS_DIR_WTR = $$OBJECTS_DIR/
-win32-*: OBJECTS_DIR_WTR ~= s|/|\|
+CONFIG(debug, debug|release) {
+ OBJECTS_DIR = obj/debug
+} else { # Release
+ OBJECTS_DIR = obj/release
+}
+OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
include($$PWD/JavaScriptCore.pri)
lessThan(QT_MINOR_VERSION, 4) {
$(JSCORE_VM_SOURCES)
$(JSCORE_WTF_SOURCES)
</sources>
+
+ <set var="ASSEMBLER_SOURCES">
+ <if cond="WX_PORT=='gtk2'">
+ $(JSCORE_VM_SOURCES_POSIX)
+ </if>
+ <if cond="PLATFORM_OS=='mac'">
+ $(JSCORE_VM_SOURCES_POSIX)
+ </if>
+ <if cond="WX_PORT=='msw'">
+ $(JSCORE_VM_SOURCES_WIN)
+ </if>
+ </set>
+
+ <sources>
+ $(ASSEMBLER_SOURCES)
+ </sources>
<install-to>$(WKOUTPUTDIR)</install-to>
<pic>on</pic>
<threading>multi</threading>
<include>$(SRCDIR)</include>
<include>$(SRCDIR)/..</include>
<include>$(SRCDIR)/API</include>
+ <include>$(SRCDIR)/assembler</include>
<include>$(SRCDIR)/bytecompiler</include>
<include>$(SRCDIR)/DerivedSources/JavaScriptCore</include>
<include>$(SRCDIR)/ForwardingHeaders</include>
<!-- FIXME: we need proper configure checks -->
<define>HAVE_FUNC_ISNAN</define>
<!-- check for undefined symbols for debugging reasons -->
- <ldflags>-Wl,--no-undefined</ldflags>
+ <ldflags>-Wl</ldflags>
</if>
<if cond="PLATFORM_WIN32=='1'">
<depends>jscore</depends>
<include>$(SRCDIR)</include>
<include>$(WK_ROOT)/JavaScriptCore</include>
+ <include>$(WK_ROOT)/JavaScriptCore/assembler</include>
<include>$(WK_ROOT)/JavaScriptCore/bytecompiler</include>
<include>$(WK_ROOT)/JavaScriptCore/debugger</include>
<include>$(WK_ROOT)/JavaScriptCore/parser</include>
<include>$(WK_ROOT)/JavaScriptCore/wtf</include>
<dirname>$(WKOUTPUTDIR)</dirname>
<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>
<sys-lib>winmm</sys-lib> <!-- for timeGetTime -->
<lib-path>$(WKOUTPUTDIR)</lib-path>
<lib-path>$(WK_ROOT)/WebKitLibraries/win/lib</lib-path>
#include <stdlib.h>
#include "JSValue.h"
#include "JSObject.h"
-#include "Nodes.h"
+#include "NodeConstructors.h"
#include "Lexer.h"
#include "JSString.h"
#include "JSGlobalData.h"
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);
+static ExpressionNode* combineCommaNodes(void*, ExpressionNode* list, ExpressionNode* init);
#if COMPILER(MSVC)
#define YYPARSE_PARAM globalPtr
#define YYLEX_PARAM globalPtr
-template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
- ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls,
+template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserArenaData<DeclarationStacks::VarStack>* varDecls,
+ ParserArenaData<DeclarationStacks::FunctionStack>* funcDecls,
CodeFeatures info,
int numConstants)
{
ASSERT((info & ~AllFeatures) == 0);
- NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info, numConstants};
+ 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};
+ NodeInfo<T> result = { node, info, numConstants };
return result;
}
-template <typename T> T mergeDeclarationLists(T decls1, T decls2)
+template <typename T> inline T mergeDeclarationLists(T decls1, T decls2)
{
// decls1 or both are null
if (!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();
+ // Manually release as much as possible from the now-defunct declaration lists
+ // to avoid accumulating so many unused heap allocated vectors.
+ decls2->data.clear();
+
return decls1;
}
-static void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
+static void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
{
if (!varDecls)
- varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ varDecls = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
varDecls->data.append(make_pair(ident, attrs));
}
-static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
+static inline void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
{
unsigned attrs = DeclarationStacks::IsConstant;
- if (decl->m_init)
+ if (decl->hasInitializer())
attrs |= DeclarationStacks::HasInitializer;
- appendToVarDeclarationList(globalPtr, varDecls, decl->m_ident, attrs);
+ appendToVarDeclarationList(globalPtr, varDecls, decl->ident(), attrs);
}
%}
%token ANDEQUAL MODEQUAL /* &= and %= */
%token XOREQUAL OREQUAL /* ^= and |= */
%token <intValue> OPENBRACE /* { (with char offset) */
-%token <intValue> CLOSEBRACE /* { (with char offset) */
+%token <intValue> CLOSEBRACE /* } (with char offset) */
/* terminal types */
%token <doubleValue> NUMBER
%type <expressionNode> Initializer InitializerNoIn
%type <statementNode> FunctionDeclaration
%type <funcExprNode> FunctionExpr
-%type <functionBodyNode> FunctionBody
+%type <functionBodyNode> FunctionBody
%type <sourceElements> SourceElements
%type <parameterList> FormalParameterList
%type <op> AssignmentOperator
// 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); }
+ NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NullNode(GLOBAL_DATA), 0, 1); }
+ | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, true), 0, 1); }
+ | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | STRING { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); }
| '/' /* regexp */ {
Lexer& l = *LEXER;
if (!l.scanRegExp())
YYABORT;
- RegExpNode* node = new RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
+ RegExpNode* node = new (GLOBAL_DATA) 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);
Lexer& l = *LEXER;
if (!l.scanRegExp())
YYABORT;
- RegExpNode* node = new RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
+ RegExpNode* node = new (GLOBAL_DATA) 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 ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) 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
{
;
PropertyList:
- Property { $$.m_node.head = new PropertyListNode(GLOBAL_DATA, $1.m_node);
+ Property { $$.m_node.head = new (GLOBAL_DATA) 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_node.tail = new (GLOBAL_DATA) 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); }
+ | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA), 0, 0); }
+ | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
;
PrimaryExprNoBrace:
- THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new ThisNode(GLOBAL_DATA), ThisFeature, 0); }
+ THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | IDENT { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); }
+ | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+ | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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);
+ ElisionOpt AssignmentExpr { $$.m_node.head = new (GLOBAL_DATA) 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_node.tail = new (GLOBAL_DATA) 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; }
;
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);
+ | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) 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);
+ | MemberExpr '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) 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);
+ | NEW MemberExpr Arguments { NewExprNode* node = new (GLOBAL_DATA) 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);
+ | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) 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);
+ | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) 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);
+ | NEW MemberExpr Arguments { NewExprNode* node = new (GLOBAL_DATA) 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);
+ | NEW NewExpr { NewExprNode* node = new (GLOBAL_DATA) 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);
+ | NEW NewExpr { NewExprNode* node = new (GLOBAL_DATA) 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);
+ | CallExpr '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) 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);
+ | CallExpr '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) 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);
+ | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) 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);
+ | CallExprNoBF '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) 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); }
+ '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA), 0, 0); }
+ | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) 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);
+ AssignmentExpr { $$.m_node.head = new (GLOBAL_DATA) 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_node.tail = new (GLOBAL_DATA) 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; }
;
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); }
+ | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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*>(new (GLOBAL_DATA) 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 { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
UnaryExpr:
PostfixExpr
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); }
+ | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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:
| 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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:
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); }
+ | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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);
+ | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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);
+ | RelationalExpr INTOKEN ShiftExpr { InNode* node = new (GLOBAL_DATA) 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 '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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);
+ { InstanceOfNode* node = new (GLOBAL_DATA) 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 '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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);
+ { InstanceOfNode* node = new (GLOBAL_DATA) 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);
+ { InNode* node = new (GLOBAL_DATA) 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); }
+ | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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 (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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 (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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); }
+ { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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:
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); }
+ | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(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); }
+ | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(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); }
+ | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
;
Statement:
;
Block:
- OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
+ OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
DBG($$.m_node, @1, @3); }
;
VariableDeclarationList:
IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
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);
+ | IDENT Initializer { AssignResolveNode* node = new (GLOBAL_DATA) 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);
+ $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
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 = $1.m_numConstants;
}
| VariableDeclarationList ',' IDENT Initializer
- { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ { AssignResolveNode* node = new (GLOBAL_DATA) 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_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
$$.m_varDeclarations = $1.m_varDeclarations;
appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
VariableDeclarationListNoIn:
IDENT { $$.m_node = 0;
- $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
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);
+ | IDENT InitializerNoIn { AssignResolveNode* node = new (GLOBAL_DATA) 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);
+ $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
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 = $1.m_numConstants;
}
| VariableDeclarationListNoIn ',' IDENT InitializerNoIn
- { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ { AssignResolveNode* node = new (GLOBAL_DATA) 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_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
$$.m_varDeclarations = $1.m_varDeclarations;
appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
;
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);
+ CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
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;
+ { $$.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;
;
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); }
+ IDENT { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
+ | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); }
;
Initializer:
;
EmptyStatement:
- ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); }
+ ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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),
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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);
+ | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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,
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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),
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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,
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);
+ ForInNode* node = new (GLOBAL_DATA) 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,
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);
+ { ForInNode *forIn = new (GLOBAL_DATA) 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);
+ { ForInNode *forIn = new (GLOBAL_DATA) 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,
;
ContinueStatement:
- CONTINUE ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
+ CONTINUE ';' { ContinueNode* node = new (GLOBAL_DATA) 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);
+ | CONTINUE error { ContinueNode* node = new (GLOBAL_DATA) 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);
+ | CONTINUE IDENT ';' { ContinueNode* node = new (GLOBAL_DATA) 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);
+ | CONTINUE IDENT error { ContinueNode* node = new (GLOBAL_DATA) 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);
+ BREAK ';' { BreakNode* node = new (GLOBAL_DATA) 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);
+ | BREAK error { BreakNode* node = new (GLOBAL_DATA) 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);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | BREAK IDENT ';' { BreakNode* node = new (GLOBAL_DATA) 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);
+ | BREAK IDENT error { BreakNode* node = new (GLOBAL_DATA) 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; }
+ $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
;
ReturnStatement:
- RETURN ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
+ RETURN ';' { ReturnNode* node = new (GLOBAL_DATA) 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);
+ | RETURN error { ReturnNode* node = new (GLOBAL_DATA) 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);
+ | RETURN Expr ';' { ReturnNode* node = new (GLOBAL_DATA) 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);
+ | RETURN Expr error { ReturnNode* node = new (GLOBAL_DATA) 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),
+ WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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,
+ SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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 CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) 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),
+ { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) 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,
;
CaseClauses:
- CaseClause { $$.m_node.head = new ClauseListNode(GLOBAL_DATA, $1.m_node);
+ CaseClause { $$.m_node.head = new (GLOBAL_DATA) 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_node.tail = new (GLOBAL_DATA) 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;
;
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); }
+ CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); }
+ | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) 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); }
+ DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); }
+ | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) 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);
+ IDENT ':' Statement { LabelNode* node = new (GLOBAL_DATA) 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);
+ THROW Expr ';' { ThrowNode* node = new (GLOBAL_DATA) 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);
+ | THROW Expr error { ThrowNode* node = new (GLOBAL_DATA) 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),
+ TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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),
+ | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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),
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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,
;
DebuggerStatement:
- DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
DBG($$.m_node, @1, @2); }
- | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) 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 '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$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);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $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);
+ IDENT { $$.m_node.head = new (GLOBAL_DATA) 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); }
+ $$.m_node.tail = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); }
;
FunctionBody:
;
Program:
- /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); }
+ /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new (GLOBAL_DATA) 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);
+ Statement { $$.m_node = new (GLOBAL_DATA) SourceElements(GLOBAL_DATA);
$$.m_node->append($1.m_node);
$$.m_varDeclarations = $1.m_varDeclarations;
$$.m_funcDeclarations = $1.m_funcDeclarations;
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);
+ return new (GLOBAL_DATA) 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);
+ AssignResolveNode* node = new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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());
+ return new (GLOBAL_DATA) 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);
+ ReadModifyBracketNode* node = new (GLOBAL_DATA) 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());
+ return new (GLOBAL_DATA) 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);
+ ReadModifyDotNode* node = new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ PrefixBracketNode* node = new (GLOBAL_DATA) 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);
+ PrefixDotNode* node = new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ PostfixBracketNode* node = new (GLOBAL_DATA) 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);
+ PostfixDotNode* node = new (GLOBAL_DATA) PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
node->setSubexpressionInfo(dot->divot(), dot->endOffset());
return node;
}
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);
+ return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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);
+ return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
+ return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) 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);
+ FunctionCallBracketNode* node = new (GLOBAL_DATA) 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);
+ FunctionCallDotNode* node;
+ if (dot->identifier() == GLOBAL_DATA->propertyNames->call)
+ node = new (GLOBAL_DATA) CallFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+ else if (dot->identifier() == GLOBAL_DATA->propertyNames->apply)
+ node = new (GLOBAL_DATA) ApplyFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+ else
+ node = new (GLOBAL_DATA) 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);
}
{
if (expr->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(expr);
- return new TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
+ return new (GLOBAL_DATA) TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
}
- return new TypeOfValueNode(GLOBAL_DATA, expr);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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)
type = PropertyNode::Setter;
else
return 0;
- return new PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
+ return new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
}
static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
}
}
- return new NegateNode(GLOBAL_DATA, n);
+ return new (GLOBAL_DATA) NegateNode(GLOBAL_DATA, n);
}
static NumberNode* makeNumberNode(void* globalPtr, double d)
{
- return new NumberNode(GLOBAL_DATA, d);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) BitwiseNotNode(GLOBAL_DATA, expr);
}
static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
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);
+ return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr2);
if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
- return new UnaryPlusNode(GLOBAL_DATA, expr1);
+ return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr1);
- return new MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+ return new (GLOBAL_DATA) MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
}
static ExpressionNode* makeDivNode(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 DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
}
static ExpressionNode* makeSubNode(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 SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) 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);
+ return new (GLOBAL_DATA) RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
}
/* called by yyparse on error */
return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
}
-static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* list, AssignResolveNode* init)
+static ExpressionNode* combineCommaNodes(void* globalPtr, ExpressionNode* list, ExpressionNode* init)
{
if (!list)
return init;
- return new VarDeclCommaNode(GLOBAL_DATA, list, init);
+ if (list->isCommaNode()) {
+ static_cast<CommaNode*>(list)->append(init);
+ return list;
+ }
+ return new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, list, init);
}
// We turn variable declarations into either assignments or empty
static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr)
{
if (!expr)
- return new EmptyStatementNode(GLOBAL_DATA);
- return new VarStatementNode(GLOBAL_DATA, expr);
+ return new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA);
+ return new (GLOBAL_DATA) VarStatementNode(GLOBAL_DATA, expr);
}
#undef GLOBAL_DATA
#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
+// We can't specify the namespace in yacc's C output, so do it here instead.
using namespace JSC;
#ifndef KDE_USE_FINAL
#include "Lookup.h"
#include "Lexer.lut.h"
-// a bridge for yacc from the C world to C++
+// A bridge for yacc from the C world to the C++ world.
int jscyylex(void* lvalp, void* llocp, void* globalData)
{
return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
namespace JSC {
-static bool isDecimalDigit(int);
+static const UChar byteOrderMark = 0xFEFF;
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_isReparsing(false)
, m_globalData(globalData)
- , m_mainTable(JSC::mainTable)
+ , m_keywordTable(JSC::mainTable)
{
m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
m_buffer16.reserveInitialCapacity(initialReadBufferCapacity);
Lexer::~Lexer()
{
- m_mainTable.deleteTable();
+ m_keywordTable.deleteTable();
+}
+
+inline const UChar* Lexer::currentCharacter() const
+{
+ return m_code - 4;
+}
+
+inline int Lexer::currentOffset() const
+{
+ return currentCharacter() - m_codeStart;
+}
+
+ALWAYS_INLINE void Lexer::shift1()
+{
+ m_current = m_next1;
+ m_next1 = m_next2;
+ m_next2 = m_next3;
+ if (LIKELY(m_code < m_codeEnd))
+ m_next3 = m_code[0];
+ else
+ m_next3 = -1;
+
+ ++m_code;
+}
+
+ALWAYS_INLINE void Lexer::shift2()
+{
+ m_current = m_next2;
+ m_next1 = m_next3;
+ if (LIKELY(m_code + 1 < m_codeEnd)) {
+ m_next2 = m_code[0];
+ m_next3 = m_code[1];
+ } else {
+ m_next2 = m_code < m_codeEnd ? m_code[0] : -1;
+ m_next3 = -1;
+ }
+
+ m_code += 2;
+}
+
+ALWAYS_INLINE void Lexer::shift3()
+{
+ m_current = m_next3;
+ if (LIKELY(m_code + 2 < m_codeEnd)) {
+ m_next1 = m_code[0];
+ m_next2 = m_code[1];
+ m_next3 = m_code[2];
+ } else {
+ m_next1 = m_code < m_codeEnd ? m_code[0] : -1;
+ m_next2 = m_code + 1 < m_codeEnd ? m_code[1] : -1;
+ m_next3 = -1;
+ }
+
+ m_code += 3;
+}
+
+ALWAYS_INLINE void Lexer::shift4()
+{
+ if (LIKELY(m_code + 3 < m_codeEnd)) {
+ m_current = m_code[0];
+ m_next1 = m_code[1];
+ m_next2 = m_code[2];
+ m_next3 = m_code[3];
+ } else {
+ m_current = m_code < m_codeEnd ? m_code[0] : -1;
+ m_next1 = m_code + 1 < m_codeEnd ? m_code[1] : -1;
+ m_next2 = m_code + 2 < m_codeEnd ? m_code[2] : -1;
+ m_next3 = -1;
+ }
+
+ m_code += 4;
}
void Lexer::setCode(const SourceCode& source)
{
- yylineno = source.firstLine();
- m_restrKeyword = false;
+ m_lineNumber = source.firstLine();
m_delimited = false;
- m_eatNextIdentifier = false;
- m_stackToken = -1;
m_lastToken = -1;
- m_position = source.startOffset();
+ const UChar* data = source.provider()->data();
+
m_source = &source;
- m_code = source.provider()->data();
- m_length = source.endOffset();
- m_skipLF = false;
- m_skipCR = false;
+ m_codeStart = data;
+ m_code = data + source.startOffset();
+ m_codeEnd = data + source.endOffset();
m_error = false;
m_atLineStart = true;
- // read first characters
- shift(4);
+ // ECMA-262 calls for stripping all Cf characters, but we only strip BOM characters.
+ // See <https://bugs.webkit.org/show_bug.cgi?id=4931> for details.
+ if (source.provider()->hasBOMs()) {
+ for (const UChar* p = m_codeStart; p < m_codeEnd; ++p) {
+ if (UNLIKELY(*p == byteOrderMark)) {
+ copyCodeWithoutBOMs();
+ break;
+ }
+ }
+ }
+
+ // Read the first characters into the 4-character buffer.
+ shift4();
+ ASSERT(currentOffset() == source.startOffset());
}
-void Lexer::shift(unsigned p)
+void Lexer::copyCodeWithoutBOMs()
{
- // 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);
+ // Note: In this case, the character offset data for debugging will be incorrect.
+ // If it's important to correctly debug code with extraneous BOMs, then the caller
+ // should strip the BOMs when creating the SourceProvider object and do its own
+ // mapping of offsets within the stripped text to original text offset.
+
+ m_codeWithoutBOMs.reserveCapacity(m_codeEnd - m_code);
+ for (const UChar* p = m_code; p < m_codeEnd; ++p) {
+ UChar c = *p;
+ if (c != byteOrderMark)
+ m_codeWithoutBOMs.append(c);
+ }
+ ptrdiff_t startDelta = m_codeStart - m_code;
+ m_code = m_codeWithoutBOMs.data();
+ m_codeStart = m_code + startDelta;
+ m_codeEnd = m_codeWithoutBOMs.data() + m_codeWithoutBOMs.size();
+}
+
+void Lexer::shiftLineTerminator()
+{
+ ASSERT(isLineTerminator(m_current));
+
+ // Allow both CRLF and LFCR.
+ if (m_current + m_next1 == '\n' + '\r')
+ shift2();
+ else
+ shift1();
+
+ ++m_lineNumber;
+}
+
+ALWAYS_INLINE Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
+{
+ m_identifiers.append(Identifier(m_globalData, characters, length));
+ return &m_identifiers.last();
+}
+
+inline bool Lexer::lastTokenWasRestrKeyword() const
+{
+ return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW;
+}
+
+static NEVER_INLINE bool isNonASCIIIdentStart(int c)
+{
+ return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other);
+}
+
+static inline bool isIdentStart(int c)
+{
+ return isASCII(c) ? isASCIIAlpha(c) || c == '$' || c == '_' : isNonASCIIIdentStart(c);
+}
+
+static NEVER_INLINE bool isNonASCIIIdentPart(int c)
+{
+ return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
+ | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector);
+}
+
+static inline bool isIdentPart(int c)
+{
+ return isASCII(c) ? isASCIIAlphanumeric(c) || c == '$' || c == '_' : isNonASCIIIdentPart(c);
+}
+
+static inline int singleEscape(int 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;
+ default:
+ return c;
}
}
-// called on each new line
-void Lexer::nextLine()
+inline void Lexer::record8(int c)
{
- yylineno++;
- m_atLineStart = true;
+ ASSERT(c >= 0);
+ ASSERT(c <= 0xFF);
+ m_buffer8.append(static_cast<char>(c));
}
-void Lexer::setDone(State s)
+inline void Lexer::record16(UChar c)
{
- m_state = s;
- m_done = true;
+ m_buffer16.append(c);
+}
+
+inline void Lexer::record16(int c)
+{
+ ASSERT(c >= 0);
+ ASSERT(c <= USHRT_MAX);
+ record16(UChar(static_cast<unsigned short>(c)));
}
int Lexer::lex(void* p1, void* p2)
{
+ ASSERT(!m_error);
+ ASSERT(m_buffer8.isEmpty());
+ ASSERT(m_buffer16.isEmpty());
+
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);
+
+start:
+ while (isWhiteSpace(m_current))
+ shift1();
+
+ int startOffset = currentOffset();
+
+ if (m_current == -1) {
+ if (!m_terminator && !m_delimited && !m_isReparsing) {
+ // automatic semicolon insertion if program incomplete
+ token = ';';
+ goto doneSemicolon;
}
- 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);
+ return 0;
+ }
+
+ m_delimited = false;
+ switch (m_current) {
+ case '>':
+ if (m_next1 == '>' && m_next2 == '>') {
+ if (m_next3 == '=') {
+ shift4();
+ token = URSHIFTEQUAL;
+ break;
}
+ shift3();
+ token = URSHIFT;
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);
+ }
+ if (m_next1 == '>') {
+ if (m_next2 == '=') {
+ shift3();
+ token = RSHIFTEQUAL;
+ break;
+ }
+ shift2();
+ token = RSHIFT;
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;
+ }
+ if (m_next1 == '=') {
+ shift2();
+ token = GE;
+ break;
+ }
+ shift1();
+ token = '>';
+ break;
+ case '=':
+ if (m_next1 == '=') {
+ if (m_next2 == '=') {
+ shift3();
+ token = STREQ;
+ break;
}
+ shift2();
+ token = EQEQ;
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;
+ }
+ shift1();
+ token = '=';
+ break;
+ case '!':
+ if (m_next1 == '=') {
+ if (m_next2 == '=') {
+ shift3();
+ token = STRNEQ;
+ break;
}
+ shift2();
+ token = NE;
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);
+ }
+ shift1();
+ token = '!';
+ break;
+ case '<':
+ if (m_next1 == '!' && m_next2 == '-' && m_next3 == '-') {
+ // <!-- marks the beginning of a line comment (for www usage)
+ shift4();
+ goto inSingleLineComment;
+ }
+ if (m_next1 == '<') {
+ if (m_next2 == '=') {
+ shift3();
+ token = LSHIFTEQUAL;
+ break;
+ }
+ shift2();
+ token = LSHIFT;
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);
+ }
+ if (m_next1 == '=') {
+ shift2();
+ token = LE;
break;
- case InMultiLineComment:
- if (m_current == -1)
- setDone(Bad);
- else if (isLineTerminator())
- nextLine();
- else if (m_current == '*' && m_next1 == '/') {
- m_state = Start;
- shift(1);
+ }
+ shift1();
+ token = '<';
+ break;
+ case '+':
+ if (m_next1 == '+') {
+ shift2();
+ if (m_terminator) {
+ token = AUTOPLUSPLUS;
+ break;
}
+ token = PLUSPLUS;
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);
+ }
+ if (m_next1 == '=') {
+ shift2();
+ token = PLUSEQUAL;
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);
+ }
+ shift1();
+ token = '+';
+ break;
+ case '-':
+ if (m_next1 == '-') {
+ if (m_atLineStart && m_next2 == '>') {
+ shift3();
+ goto inSingleLineComment;
+ }
+ shift2();
+ if (m_terminator) {
+ token = AUTOMINUSMINUS;
+ break;
+ }
+ token = MINUSMINUS;
break;
- case InHex:
- if (isHexDigit(m_current))
- record8(m_current);
- else
- setDone(Hex);
+ }
+ if (m_next1 == '=') {
+ shift2();
+ token = MINUSEQUAL;
break;
- case InOctal:
- if (isOctalDigit(m_current))
- record8(m_current);
- else if (isDecimalDigit(m_current)) {
- record8(m_current);
- m_state = InDecimal;
- } else
- setDone(Octal);
+ }
+ shift1();
+ token = '-';
+ break;
+ case '*':
+ if (m_next1 == '=') {
+ shift2();
+ token = MULTEQUAL;
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);
+ }
+ shift1();
+ token = '*';
+ break;
+ case '/':
+ if (m_next1 == '/') {
+ shift2();
+ goto inSingleLineComment;
+ }
+ if (m_next1 == '*')
+ goto inMultiLineComment;
+ if (m_next1 == '=') {
+ shift2();
+ token = DIVEQUAL;
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);
+ }
+ shift1();
+ token = '/';
+ break;
+ case '&':
+ if (m_next1 == '&') {
+ shift2();
+ token = AND;
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);
+ }
+ if (m_next1 == '=') {
+ shift2();
+ token = ANDEQUAL;
break;
- case InExponent:
- if (isDecimalDigit(m_current))
- record8(m_current);
- else
- setDone(Number);
+ }
+ shift1();
+ token = '&';
+ break;
+ case '^':
+ if (m_next1 == '=') {
+ shift2();
+ token = XOREQUAL;
break;
- case InIdentifierStartUnicodeEscapeStart:
- if (m_current == 'u')
- m_state = InIdentifierStartUnicodeEscape;
- else
- setDone(Bad);
+ }
+ shift1();
+ token = '^';
+ break;
+ case '%':
+ if (m_next1 == '=') {
+ shift2();
+ token = MODEQUAL;
break;
- case InIdentifierPartUnicodeEscapeStart:
- if (m_current == 'u')
- m_state = InIdentifierPartUnicodeEscape;
- else
- setDone(Bad);
+ }
+ shift1();
+ token = '%';
+ break;
+ case '|':
+ if (m_next1 == '=') {
+ shift2();
+ token = OREQUAL;
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;
+ }
+ if (m_next1 == '|') {
+ shift2();
+ token = OR;
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;
+ }
+ shift1();
+ token = '|';
+ break;
+ case '.':
+ if (isASCIIDigit(m_next1)) {
+ record8('.');
+ shift1();
+ goto inNumberAfterDecimalPoint;
+ }
+ token = '.';
+ shift1();
+ break;
+ case ',':
+ case '~':
+ case '?':
+ case ':':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ token = m_current;
+ shift1();
+ break;
+ case ';':
+ shift1();
+ m_delimited = true;
+ token = ';';
+ break;
+ case '{':
+ lvalp->intValue = currentOffset();
+ shift1();
+ token = OPENBRACE;
+ break;
+ case '}':
+ lvalp->intValue = currentOffset();
+ shift1();
+ m_delimited = true;
+ token = CLOSEBRACE;
+ break;
+ case '\\':
+ goto startIdentifierWithBackslash;
+ case '0':
+ goto startNumberWithZeroDigit;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ goto startNumber;
+ case '"':
+ case '\'':
+ goto startString;
+ default:
+ if (isIdentStart(m_current))
+ goto startIdentifierOrKeyword;
+ if (isLineTerminator(m_current)) {
+ shiftLineTerminator();
+ m_atLineStart = true;
+ m_terminator = true;
+ if (lastTokenWasRestrKeyword()) {
+ token = ';';
+ goto doneSemicolon;
}
- 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;
+ goto start;
+ }
+ goto returnError;
}
- // 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;
+ m_atLineStart = false;
+ goto returnToken;
- // 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
+startString: {
+ int stringQuoteCharacter = m_current;
+ shift1();
- 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);
+ const UChar* stringStart = currentCharacter();
+ while (m_current != stringQuoteCharacter) {
+ // Fast check for characters that require special handling.
+ // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
+ // as possible, and lets through all common ASCII characters.
+ if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
+ m_buffer16.append(stringStart, currentCharacter() - stringStart);
+ goto inString;
+ }
+ shift1();
+ }
+ lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
+ shift1();
+ m_atLineStart = false;
+ m_delimited = false;
+ token = STRING;
+ goto returnToken;
+
+inString:
+ while (m_current != stringQuoteCharacter) {
+ if (m_current == '\\')
+ goto inStringEscapeSequence;
+ if (UNLIKELY(isLineTerminator(m_current)))
+ goto returnError;
+ if (UNLIKELY(m_current == -1))
+ goto returnError;
+ record16(m_current);
+ shift1();
+ }
+ goto doneString;
+
+inStringEscapeSequence:
+ shift1();
+ if (m_current == 'x') {
+ shift1();
+ if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1)) {
+ record16(convertHex(m_current, m_next1));
+ shift2();
+ goto inString;
}
+ record16('x');
+ if (m_current == stringQuoteCharacter)
+ goto doneString;
+ goto inString;
+ }
+ if (m_current == 'u') {
+ shift1();
+ if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1) && isASCIIHexDigit(m_next2) && isASCIIHexDigit(m_next3)) {
+ record16(convertUnicode(m_current, m_next1, m_next2, m_next3));
+ shift4();
+ goto inString;
+ }
+ if (m_current == stringQuoteCharacter) {
+ record16('u');
+ goto doneString;
+ }
+ goto returnError;
+ }
+ if (isASCIIOctalDigit(m_current)) {
+ if (m_current >= '0' && m_current <= '3' && isASCIIOctalDigit(m_next1) && isASCIIOctalDigit(m_next2)) {
+ record16((m_current - '0') * 64 + (m_next1 - '0') * 8 + m_next2 - '0');
+ shift3();
+ goto inString;
+ }
+ if (isASCIIOctalDigit(m_next1)) {
+ record16((m_current - '0') * 8 + m_next1 - '0');
+ shift2();
+ goto inString;
+ }
+ record16(m_current - '0');
+ shift1();
+ goto inString;
+ }
+ if (isLineTerminator(m_current)) {
+ shiftLineTerminator();
+ goto inString;
+ }
+ record16(singleEscape(m_current));
+ shift1();
+ goto inString;
+}
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16);
+startIdentifierWithBackslash:
+ shift1();
+ if (UNLIKELY(m_current != 'u'))
+ goto returnError;
+ shift1();
+ if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3)))
+ goto returnError;
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ if (UNLIKELY(!isIdentStart(token)))
+ goto returnError;
+ goto inIdentifierAfterCharacterCheck;
+
+startIdentifierOrKeyword: {
+ const UChar* identifierStart = currentCharacter();
+ shift1();
+ while (isIdentPart(m_current))
+ shift1();
+ if (LIKELY(m_current != '\\')) {
+ lvalp->ident = makeIdentifier(identifierStart, currentCharacter() - identifierStart);
+ goto doneIdentifierOrKeyword;
+ }
+ m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
+}
- 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';
+ do {
+ shift1();
+ if (UNLIKELY(m_current != 'u'))
+ goto returnError;
+ shift1();
+ if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3)))
+ goto returnError;
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ if (UNLIKELY(!isIdentPart(token)))
+ goto returnError;
+inIdentifierAfterCharacterCheck:
+ record16(token);
+ shift4();
+
+ while (isIdentPart(m_current)) {
+ record16(m_current);
+ shift1();
}
+ } while (UNLIKELY(m_current == '\\'));
+ goto doneIdentifier;
- if (dval >= mantissaOverflowLowerBound)
- dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8);
-
- m_state = Number;
+inSingleLineComment:
+ while (!isLineTerminator(m_current)) {
+ if (UNLIKELY(m_current == -1))
+ return 0;
+ shift1();
}
-
-#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)");
+ shiftLineTerminator();
+ m_atLineStart = true;
+ m_terminator = true;
+ if (lastTokenWasRestrKeyword())
+ goto doneSemicolon;
+ goto start;
+
+inMultiLineComment:
+ shift2();
+ while (m_current != '*' || m_next1 != '/') {
+ if (isLineTerminator(m_current))
+ shiftLineTerminator();
+ else {
+ shift1();
+ if (UNLIKELY(m_current == -1))
+ goto returnError;
+ }
}
-#endif
+ shift2();
+ m_atLineStart = false;
+ goto start;
+
+startNumberWithZeroDigit:
+ shift1();
+ if ((m_current | 0x20) == 'x' && isASCIIHexDigit(m_next1)) {
+ shift1();
+ goto inHex;
+ }
+ if (m_current == '.') {
+ record8('0');
+ record8('.');
+ shift1();
+ goto inNumberAfterDecimalPoint;
+ }
+ if ((m_current | 0x20) == 'e') {
+ record8('0');
+ record8('e');
+ shift1();
+ goto inExponentIndicator;
+ }
+ if (isASCIIOctalDigit(m_current))
+ goto inOctal;
+ if (isASCIIDigit(m_current))
+ goto startNumber;
+ lvalp->doubleValue = 0;
+ goto doneNumeric;
+
+inNumberAfterDecimalPoint:
+ while (isASCIIDigit(m_current)) {
+ record8(m_current);
+ shift1();
+ }
+ if ((m_current | 0x20) == 'e') {
+ record8('e');
+ shift1();
+ goto inExponentIndicator;
+ }
+ goto doneNumber;
+
+inExponentIndicator:
+ if (m_current == '+' || m_current == '-') {
+ record8(m_current);
+ shift1();
+ }
+ if (!isASCIIDigit(m_current))
+ goto returnError;
+ do {
+ record8(m_current);
+ shift1();
+ } while (isASCIIDigit(m_current));
+ goto doneNumber;
+
+inOctal: {
+ do {
+ record8(m_current);
+ shift1();
+ } while (isASCIIOctalDigit(m_current));
+ if (isASCIIDigit(m_current))
+ goto startNumber;
- if (m_state != Identifier)
- m_eatNextIdentifier = false;
+ double dval = 0;
- 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;
+ const char* end = m_buffer8.end();
+ for (const char* p = m_buffer8.data(); p < end; ++p) {
+ dval *= 8;
+ dval += *p - '0';
}
- m_lastToken = token;
- return token;
-}
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 8);
-bool Lexer::isWhiteSpace() const
-{
- return m_current == '\t' || m_current == 0x0b || m_current == 0x0c || isSeparatorSpace(m_current);
-}
+ m_buffer8.resize(0);
-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;
+ lvalp->doubleValue = dval;
+ goto doneNumeric;
}
-bool Lexer::isIdentStart(int c)
-{
- return isASCIIAlpha(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)));
-}
+inHex: {
+ do {
+ record8(m_current);
+ shift1();
+ } while (isASCIIHexDigit(m_current));
-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)));
-}
+ double dval = 0;
-static bool isDecimalDigit(int c)
-{
- return isASCIIDigit(c);
-}
+ const char* end = m_buffer8.end();
+ for (const char* p = m_buffer8.data(); p < end; ++p) {
+ dval *= 16;
+ dval += toASCIIHexValue(*p);
+ }
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 16);
-bool Lexer::isHexDigit(int c)
-{
- return isASCIIHexDigit(c);
-}
+ m_buffer8.resize(0);
-bool Lexer::isOctalDigit(int c)
-{
- return isASCIIOctalDigit(c);
+ lvalp->doubleValue = dval;
+ goto doneNumeric;
}
-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;
+startNumber:
+ record8(m_current);
+ shift1();
+ while (isASCIIDigit(m_current)) {
+ record8(m_current);
+ shift1();
}
- if (c1 == '&' && c2 == '&') {
- shift(2);
- return AND;
+ if (m_current == '.') {
+ record8('.');
+ shift1();
+ goto inNumberAfterDecimalPoint;
}
- if (c1 == '|' && c2 == '|') {
- shift(2);
- return OR;
+ if ((m_current | 0x20) == 'e') {
+ record8('e');
+ shift1();
+ goto inExponentIndicator;
}
- 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;
- }
-}
+ // Fall through into doneNumber.
-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;
- }
-}
+doneNumber:
+ // Null-terminate string for strtod.
+ m_buffer8.append('\0');
+ lvalp->doubleValue = WTF::strtod(m_buffer8.data(), 0);
+ m_buffer8.resize(0);
-unsigned short Lexer::convertOctal(int c1, int c2, int c3)
-{
- return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
-}
+ // Fall through into doneNumeric.
-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);
-}
+doneNumeric:
+ // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
+ if (UNLIKELY(isIdentStart(m_current)))
+ goto returnError;
-unsigned char Lexer::convertHex(int c1, int c2)
-{
- return ((convertHex(c1) << 4) + convertHex(c2));
-}
+ m_atLineStart = false;
+ m_delimited = false;
+ token = NUMBER;
+ goto returnToken;
-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);
-}
+doneSemicolon:
+ token = ';';
+ m_delimited = true;
+ goto returnToken;
-void Lexer::record8(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= 0xff);
- m_buffer8.append(static_cast<char>(c));
+doneIdentifier:
+ m_atLineStart = false;
+ m_delimited = false;
+ lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+ m_buffer16.resize(0);
+ token = IDENT;
+ goto returnToken;
+
+doneIdentifierOrKeyword: {
+ m_atLineStart = false;
+ m_delimited = false;
+ m_buffer16.resize(0);
+ const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
+ token = entry ? entry->lexerValue() : IDENT;
+ goto returnToken;
}
-void Lexer::record16(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c <= USHRT_MAX);
- record16(UChar(static_cast<unsigned short>(c)));
+doneString:
+ // Atomize constant strings in case they're later used in property lookup.
+ shift1();
+ m_atLineStart = false;
+ m_delimited = false;
+ lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+ m_buffer16.resize(0);
+ token = STRING;
+
+ // Fall through into returnToken.
+
+returnToken: {
+ int lineNumber = m_lineNumber;
+ llocp->first_line = lineNumber;
+ llocp->last_line = lineNumber;
+ llocp->first_column = startOffset;
+ llocp->last_column = currentOffset();
+
+ m_lastToken = token;
+ return token;
}
-void Lexer::record16(UChar c)
-{
- m_buffer16.append(c);
+returnError:
+ m_error = true;
+ return -1;
}
bool Lexer::scanRegExp()
{
- m_buffer16.clear();
+ ASSERT(m_buffer16.isEmpty());
+
bool lastWasEscape = false;
bool inBrackets = false;
- while (1) {
- if (isLineTerminator() || m_current == -1)
+ while (true) {
+ if (isLineTerminator(m_current) || m_current == -1)
return false;
- else if (m_current != '/' || lastWasEscape == true || inBrackets == true) {
+ if (m_current != '/' || lastWasEscape || inBrackets) {
// keep track of '[' and ']'
if (!lastWasEscape) {
- if ( m_current == '[' && !inBrackets )
+ if (m_current == '[' && !inBrackets)
inBrackets = true;
- if ( m_current == ']' && inBrackets )
+ if (m_current == ']' && inBrackets)
inBrackets = false;
}
record16(m_current);
- lastWasEscape =
- !lastWasEscape && (m_current == '\\');
+ lastWasEscape = !lastWasEscape && m_current == '\\';
} else { // end of regexp
m_pattern = UString(m_buffer16);
- m_buffer16.clear();
- shift(1);
+ m_buffer16.resize(0);
+ shift1();
break;
}
- shift(1);
+ shift1();
}
while (isIdentPart(m_current)) {
record16(m_current);
- shift(1);
+ shift1();
}
m_flags = UString(m_buffer16);
+ m_buffer16.resize(0);
return true;
}
void Lexer::clear()
{
m_identifiers.clear();
+ m_codeWithoutBOMs.clear();
Vector<char> newBuffer8;
newBuffer8.reserveInitialCapacity(initialReadBufferCapacity);
m_isReparsing = false;
- m_pattern = 0;
- m_flags = 0;
+ m_pattern = UString();
+ m_flags = UString();
+}
+
+SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
+{
+ if (m_codeWithoutBOMs.isEmpty())
+ return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
+
+ const UChar* data = m_source->provider()->data();
+
+ ASSERT(openBrace < closeBrace);
+
+ int numBOMsBeforeOpenBrace = 0;
+ int numBOMsBetweenBraces = 0;
+
+ int i;
+ for (i = m_source->startOffset(); i < openBrace; ++i)
+ numBOMsBeforeOpenBrace += data[i] == byteOrderMark;
+ for (; i < closeBrace; ++i)
+ numBOMsBetweenBraces += data[i] == byteOrderMark;
+
+ return SourceCode(m_source->provider(), openBrace + numBOMsBeforeOpenBrace,
+ closeBrace + numBOMsBeforeOpenBrace + numBOMsBetweenBraces + 1, firstLine);
}
} // namespace JSC
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2002, 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 Library General Public
#ifndef Lexer_h
#define Lexer_h
-#include "Identifier.h"
#include "Lookup.h"
-#include "SegmentedVector.h"
#include "SourceCode.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/SegmentedVector.h>
#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
namespace JSC {
class Lexer : Noncopyable {
public:
+ // Character manipulation functions.
+ static bool isWhiteSpace(int character);
+ static bool isLineTerminator(int character);
+ static unsigned char convertHex(int c1, int c2);
+ static UChar convertUnicode(int c1, int c2, int c3, int c4);
+
+ // Functions to set up parsing.
void setCode(const SourceCode&);
void setIsReparsing() { m_isReparsing = true; }
- int lex(void* lvalp, void* llocp);
-
- int lineNo() const { return yylineno; }
+ // Functions for the parser itself.
+ int lex(void* lvalp, void* llocp);
+ int lineNumber() const { return m_lineNumber; }
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
- };
-
+ SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
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);
-
+ // Functions for use after parsing.
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 shift1();
+ void shift2();
+ void shift3();
+ void shift4();
+ void shiftLineTerminator();
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();
- }
+ void copyCodeWithoutBOMs();
+
+ int currentOffset() const;
+ const UChar* currentCharacter() const;
+
+ JSC::Identifier* makeIdentifier(const UChar* buffer, size_t length);
+
+ bool lastTokenWasRestrKeyword() const;
static const size_t initialReadBufferCapacity = 32;
static const size_t initialIdentifierTableCapacity = 64;
- int yylineno;
- int yycolumn;
+ int m_lineNumber;
- 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;
+ const UChar* m_codeStart;
+ const UChar* m_codeEnd;
bool m_isReparsing;
- int m_atLineStart;
+ bool m_atLineStart;
bool m_error;
// current and following unicode characters (int to allow for -1 for end-of-file marker)
int m_next2;
int m_next3;
- int m_currentOffset;
- int m_nextOffset1;
- int m_nextOffset2;
- int m_nextOffset3;
-
- SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
+ WTF::SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
JSGlobalData* m_globalData;
UString m_pattern;
UString m_flags;
- const HashTable m_mainTable;
+ const HashTable m_keywordTable;
+
+ Vector<UChar> m_codeWithoutBOMs;
};
+ inline bool Lexer::isWhiteSpace(int ch)
+ {
+ return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : WTF::Unicode::isSeparatorSpace(ch);
+ }
+
+ inline bool Lexer::isLineTerminator(int ch)
+ {
+ return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028;
+ }
+
+ inline unsigned char Lexer::convertHex(int c1, int c2)
+ {
+ return (toASCIIHexValue(c1) << 4) | toASCIIHexValue(c2);
+ }
+
+ inline UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
+ {
+ return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
+ }
+
} // namespace JSC
#endif // Lexer_h
--- /dev/null
+/*
+ * Copyright (C) 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 NodeConstructors_h
+#define NodeConstructors_h
+
+#include "Nodes.h"
+#include "Lexer.h"
+#include "Parser.h"
+
+namespace JSC {
+
+ inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
+ {
+ ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
+ globalData->parser->arena().deleteWithArena(deletable);
+ return deletable;
+ }
+
+ inline void* ParserArenaDeletable::operator new(size_t size)
+ {
+ return fastMalloc(size);
+ }
+
+ inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData)
+ {
+ globalData->parser->arena().derefWithArena(adoptRef(this));
+ }
+
+ inline Node::Node(JSGlobalData* globalData)
+ : m_line(globalData->lexer->lineNumber())
+ {
+ }
+
+ inline ExpressionNode::ExpressionNode(JSGlobalData* globalData, ResultType resultType)
+ : Node(globalData)
+ , m_resultType(resultType)
+ {
+ }
+
+ inline StatementNode::StatementNode(JSGlobalData* globalData)
+ : Node(globalData)
+ , m_lastLine(-1)
+ {
+ }
+
+ inline NullNode::NullNode(JSGlobalData* globalData)
+ : ExpressionNode(globalData, ResultType::nullType())
+ {
+ }
+
+ inline BooleanNode::BooleanNode(JSGlobalData* globalData, bool value)
+ : ExpressionNode(globalData, ResultType::booleanType())
+ , m_value(value)
+ {
+ }
+
+ inline NumberNode::NumberNode(JSGlobalData* globalData, double v)
+ : ExpressionNode(globalData, ResultType::numberType())
+ , m_double(v)
+ {
+ }
+
+ inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& v)
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_value(v)
+ {
+ }
+
+ inline RegExpNode::RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+ : ExpressionNode(globalData)
+ , m_pattern(pattern)
+ , m_flags(flags)
+ {
+ }
+
+ inline ThisNode::ThisNode(JSGlobalData* globalData)
+ : ExpressionNode(globalData)
+ {
+ }
+
+ inline ResolveNode::ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset)
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_startOffset(startOffset)
+ {
+ }
+
+ inline ElementNode::ElementNode(JSGlobalData*, int elision, ExpressionNode* node)
+ : m_next(0)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ }
+
+ inline ElementNode::ElementNode(JSGlobalData*, ElementNode* l, int elision, ExpressionNode* node)
+ : m_next(0)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ l->m_next = this;
+ }
+
+ inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision)
+ : ExpressionNode(globalData)
+ , m_element(0)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ inline ArrayNode::ArrayNode(JSGlobalData* globalData, ElementNode* element)
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(0)
+ , m_optional(false)
+ {
+ }
+
+ inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element)
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ inline PropertyNode::PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* assign, Type type)
+ : m_name(name)
+ , m_assign(assign)
+ , m_type(type)
+ {
+ }
+
+ inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node)
+ : Node(globalData)
+ , m_node(node)
+ , m_next(0)
+ {
+ }
+
+ inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list)
+ : Node(globalData)
+ , m_node(node)
+ , m_next(0)
+ {
+ list->m_next = this;
+ }
+
+ inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData)
+ : ExpressionNode(globalData)
+ , m_list(0)
+ {
+ }
+
+ inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list)
+ : ExpressionNode(globalData)
+ , m_list(list)
+ {
+ }
+
+ inline BracketAccessorNode::BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments)
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ {
+ }
+
+ inline DotAccessorNode::DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident)
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : Node(globalData)
+ , m_next(0)
+ , m_expr(expr)
+ {
+ }
+
+ inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr)
+ : Node(globalData)
+ , m_next(0)
+ , m_expr(expr)
+ {
+ listNode->m_next = this;
+ }
+
+ inline ArgumentsNode::ArgumentsNode(JSGlobalData*)
+ : m_listNode(0)
+ {
+ }
+
+ inline ArgumentsNode::ArgumentsNode(JSGlobalData*, ArgumentListNode* listNode)
+ : m_listNode(listNode)
+ {
+ }
+
+ inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ , m_args(0)
+ {
+ }
+
+ inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ inline EvalFunctionCallNode::EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_args(args)
+ {
+ }
+
+ inline FunctionCallValueNode::FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ inline FunctionCallResolveNode::FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ inline FunctionCallBracketNode::FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_args(args)
+ {
+ }
+
+ inline FunctionCallDotNode::FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ inline CallFunctionCallDotNode::CallFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset)
+ {
+ }
+
+ inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset)
+ {
+ }
+
+ inline PrePostResolveNode::PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre?
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ inline PostfixResolveNode::PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ inline PostfixBracketNode::PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ inline PostfixDotNode::PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ inline PostfixErrorNode::PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ inline DeleteResolveNode::DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ inline DeleteBracketNode::DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ {
+ }
+
+ inline DeleteDotNode::DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ inline DeleteValueNode::DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ inline VoidNode::VoidNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ inline TypeOfResolveNode::TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident)
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_ident(ident)
+ {
+ }
+
+ inline TypeOfValueNode::TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData, ResultType::stringType())
+ , m_expr(expr)
+ {
+ }
+
+ inline PrefixResolveNode::PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ inline PrefixBracketNode::PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ inline PrefixDotNode::PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ inline PrefixErrorNode::PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ inline UnaryOpNode::UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr, OpcodeID opcodeID)
+ : ExpressionNode(globalData, type)
+ , m_expr(expr)
+ , m_opcodeID(opcodeID)
+ {
+ }
+
+ inline UnaryPlusNode::UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : UnaryOpNode(globalData, ResultType::numberType(), expr, op_to_jsnumber)
+ {
+ }
+
+ inline NegateNode::NegateNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr, op_negate)
+ {
+ }
+
+ inline BitwiseNotNode::BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : UnaryOpNode(globalData, ResultType::forBitOp(), expr, op_bitnot)
+ {
+ }
+
+ inline LogicalNotNode::LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : UnaryOpNode(globalData, ResultType::booleanType(), expr, op_not)
+ {
+ }
+
+ inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : ExpressionNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_opcodeID(opcodeID)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : ExpressionNode(globalData, type)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_opcodeID(opcodeID)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments)
+ {
+ }
+
+ inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments)
+ {
+ }
+
+ inline MultNode::MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mul, rightHasAssignments)
+ {
+ }
+
+ inline DivNode::DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_div, rightHasAssignments)
+ {
+ }
+
+
+ inline ModNode::ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mod, rightHasAssignments)
+ {
+ }
+
+ inline AddNode::AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments)
+ {
+ }
+
+ inline SubNode::SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_sub, rightHasAssignments)
+ {
+ }
+
+ inline LeftShiftNode::LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments)
+ {
+ }
+
+ inline RightShiftNode::RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments)
+ {
+ }
+
+ inline UnsignedRightShiftNode::UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_urshift, rightHasAssignments)
+ {
+ }
+
+ inline LessNode::LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments)
+ {
+ }
+
+ inline GreaterNode::GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments)
+ {
+ }
+
+ inline LessEqNode::LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments)
+ {
+ }
+
+ inline GreaterEqNode::GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments)
+ {
+ }
+
+ inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments)
+ {
+ }
+
+ inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+ : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments)
+ {
+ }
+
+ inline InstanceOfNode::InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments)
+ {
+ }
+
+ inline InNode::InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ThrowableBinaryOpNode(globalData, expr1, expr2, op_in, rightHasAssignments)
+ {
+ }
+
+ inline EqualNode::EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments)
+ {
+ }
+
+ inline NotEqualNode::NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments)
+ {
+ }
+
+ inline StrictEqualNode::StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments)
+ {
+ }
+
+ inline NotStrictEqualNode::NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments)
+ {
+ }
+
+ inline BitAndNode::BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments)
+ {
+ }
+
+ inline BitOrNode::BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments)
+ {
+ }
+
+ inline BitXOrNode::BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments)
+ {
+ }
+
+ inline LogicalOpNode::LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper)
+ : ExpressionNode(globalData, ResultType::booleanType())
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_operator(oper)
+ {
+ }
+
+ inline ConditionalNode::ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2)
+ : ExpressionNode(globalData)
+ , m_logical(logical)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ {
+ }
+
+ inline ReadModifyResolveNode::ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline AssignResolveNode::AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments)
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline ReadModifyBracketNode::ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_operator(oper)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline AssignBracketNode::AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline AssignDotNode::AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline ReadModifyDotNode::ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ inline AssignErrorNode::AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_left(left)
+ , m_operator(oper)
+ , m_right(right)
+ {
+ }
+
+ inline CommaNode::CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2)
+ : ExpressionNode(globalData)
+ {
+ m_expressions.append(expr1);
+ m_expressions.append(expr2);
+ }
+
+ inline ConstStatementNode::ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next)
+ : StatementNode(globalData)
+ , m_next(next)
+ {
+ }
+
+ inline SourceElements::SourceElements(JSGlobalData*)
+ {
+ }
+
+ inline EmptyStatementNode::EmptyStatementNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ {
+ }
+
+ inline DebuggerStatementNode::DebuggerStatementNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ {
+ }
+
+ inline ExprStatementNode::ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ inline VarStatementNode::VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ inline IfNode::IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock)
+ : StatementNode(globalData)
+ , m_condition(condition)
+ , m_ifBlock(ifBlock)
+ {
+ }
+
+ inline IfElseNode::IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
+ : IfNode(globalData, condition, ifBlock)
+ , m_elseBlock(elseBlock)
+ {
+ }
+
+ inline DoWhileNode::DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr)
+ : StatementNode(globalData)
+ , m_statement(statement)
+ , m_expr(expr)
+ {
+ }
+
+ inline WhileNode::WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ {
+ }
+
+ inline ForNode::ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl)
+ : StatementNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_expr3(expr3)
+ , m_statement(statement)
+ , m_expr1WasVarDecl(expr1 && expr1WasVarDecl)
+ {
+ ASSERT(statement);
+ }
+
+ inline ContinueNode::ContinueNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ {
+ }
+
+ inline ContinueNode::ContinueNode(JSGlobalData* globalData, const Identifier& ident)
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ inline BreakNode::BreakNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ {
+ }
+
+ inline BreakNode::BreakNode(JSGlobalData* globalData, const Identifier& ident)
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ inline ReturnNode::ReturnNode(JSGlobalData* globalData, ExpressionNode* value)
+ : StatementNode(globalData)
+ , m_value(value)
+ {
+ }
+
+ inline WithNode::WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_divot(divot)
+ , m_expressionLength(expressionLength)
+ {
+ }
+
+ inline LabelNode::LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement)
+ : StatementNode(globalData)
+ , m_name(name)
+ , m_statement(statement)
+ {
+ }
+
+ inline ThrowNode::ThrowNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ inline TryNode::TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock)
+ : StatementNode(globalData)
+ , m_tryBlock(tryBlock)
+ , m_exceptionIdent(exceptionIdent)
+ , m_catchBlock(catchBlock)
+ , m_finallyBlock(finallyBlock)
+ , m_catchHasEval(catchHasEval)
+ {
+ }
+
+ inline ParameterNode::ParameterNode(JSGlobalData*, const Identifier& ident)
+ : m_ident(ident)
+ , m_next(0)
+ {
+ }
+
+ inline ParameterNode::ParameterNode(JSGlobalData*, ParameterNode* l, const Identifier& ident)
+ : m_ident(ident)
+ , m_next(0)
+ {
+ l->m_next = this;
+ }
+
+ inline FuncExprNode::FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
+ : ExpressionNode(globalData)
+ , ParserArenaRefCounted(globalData)
+ , m_ident(ident)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, parameter);
+ }
+
+ inline FuncDeclNode::FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
+ : StatementNode(globalData)
+ , ParserArenaRefCounted(globalData)
+ , m_ident(ident)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, parameter);
+ }
+
+ inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr)
+ : m_expr(expr)
+ {
+ }
+
+ inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* children)
+ : m_expr(expr)
+ {
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+ }
+
+ inline ClauseListNode::ClauseListNode(JSGlobalData*, CaseClauseNode* clause)
+ : m_clause(clause)
+ , m_next(0)
+ {
+ }
+
+ inline ClauseListNode::ClauseListNode(JSGlobalData*, ClauseListNode* clauseList, CaseClauseNode* clause)
+ : m_clause(clause)
+ , m_next(0)
+ {
+ clauseList->m_next = this;
+ }
+
+ inline CaseBlockNode::CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
+ : m_list1(list1)
+ , m_defaultClause(defaultClause)
+ , m_list2(list2)
+ {
+ }
+
+ inline SwitchNode::SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block)
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_block(block)
+ {
+ }
+
+ inline ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_next(0)
+ , m_init(init)
+ {
+ }
+
+ inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
+ : StatementNode(globalData)
+ {
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+ }
+
+ inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
+ : StatementNode(globalData)
+ , m_init(0)
+ , m_lexpr(l)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(false)
+ {
+ }
+
+ inline 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_init(0)
+ , m_lexpr(new (globalData) ResolveNode(globalData, ident, divot - startOffset))
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(true)
+ {
+ if (in) {
+ AssignResolveNode* node = new (globalData) AssignResolveNode(globalData, ident, in, true);
+ node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
+ m_init = node;
+ }
+ // for( var foo = bar in baz )
+ }
+
+} // namespace JSC
+
+#endif // NodeConstructors_h
template <typename T> struct NodeDeclarationInfo {
T m_node;
- ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
- ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
CodeFeatures m_features;
int m_numConstants;
};
#include "config.h"
#include "Nodes.h"
+#include "NodeConstructors.h"
#include "BytecodeGenerator.h"
#include "CallFrame.h"
+#include "Debugger.h"
+#include "JIT.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSStaticScopeObject.h"
#include "LabelScope.h"
+#include "Lexer.h"
+#include "Operations.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>
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();
-}
+static void substitute(UString& string, const UString& substring);
// ------------------------------ ThrowableExpressionData --------------------------------
generator.emitThrow(exception);
return exception;
}
-
-// ------------------------------ StatementNode --------------------------------
-StatementNode::StatementNode(JSGlobalData* globalData)
- : Node(globalData)
- , m_lastLine(-1)
-{
-}
+// ------------------------------ StatementNode --------------------------------
void StatementNode::setLoc(int firstLine, int lastLine)
{
// ------------------------------ SourceElements --------------------------------
-void SourceElements::append(PassRefPtr<StatementNode> statement)
+void SourceElements::append(StatementNode* statement)
{
if (statement->isEmptyStatement())
return;
-
m_statements.append(statement);
}
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()) {
+ for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
if (firstPutElement->elision())
break;
++length;
}
if (!firstPutElement && !m_elision)
- return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
+ return generator.emitNewArray(generator.finalDestination(dst), m_element);
- RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
+ RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
for (ElementNode* n = firstPutElement; n; n = n->next()) {
RegisterID* value = generator.emitNode(n->value());
return generator.moveToDestinationIfNeeded(dst, array.get());
}
-// ------------------------------ PropertyNode ----------------------------
-
-PropertyNode::~PropertyNode()
+bool ArrayNode::isSimpleArray() const
{
- NodeReleaser::releaseAllNodes(this);
+ if (m_elision || m_optional)
+ return false;
+ for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
+ if (ptr->elision())
+ return false;
+ }
+ return true;
}
-void PropertyNode::releaseNodes(NodeReleaser& releaser)
+ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
{
- releaser.release(m_assign);
+ ASSERT(!m_elision && !m_optional);
+ ElementNode* ptr = m_element;
+ if (!ptr)
+ return 0;
+ ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
+ ArgumentListNode* tail = head;
+ ptr = ptr->next();
+ for (; ptr; ptr = ptr->next()) {
+ ASSERT(!ptr->elision());
+ tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
+ }
+ return head;
}
// ------------------------------ 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) {
return 0;
return generator.emitNewObject(generator.finalDestination(dst));
}
- return generator.emitNode(dst, m_list.get());
+ return generator.emitNode(dst, m_list);
}
// ------------------------------ 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());
+ for (PropertyListNode* p = this; p; p = p->m_next) {
+ RegisterID* value = generator.emitNode(p->m_node->m_assign);
switch (p->m_node->m_type) {
case PropertyNode::Constant: {
// ------------------------------ 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());
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
+ RegisterID* property = generator.emitNode(m_subscript);
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());
+ RegisterID* base = generator.emitNode(m_base);
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);
+ return generator.emitNode(dst, m_expr);
}
// ------------------------------ 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());
+ RefPtr<RegisterID> func = generator.emitNode(m_expr);
+ return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, 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());
+ return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, 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> func = generator.emitNode(m_expr);
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());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, 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());
+ return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
int index = 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());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
- RefPtr<RegisterID> func = generator.tempDestination(dst);
+ RefPtr<RegisterID> func = generator.newTemporary();
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());
+ generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, 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());
+ RefPtr<RegisterID> base = generator.emitNode(m_base);
+ RegisterID* property = generator.emitNode(m_subscript);
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());
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallDotNode ----------------------------------
-FunctionCallDotNode::~FunctionCallDotNode()
+RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- NodeReleaser::releaseAllNodes(this);
+ RefPtr<RegisterID> function = generator.tempDestination(dst);
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ generator.emitNode(thisRegister.get(), m_base);
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ generator.emitMethodCheck();
+ generator.emitGetById(function.get(), thisRegister.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
-void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
+RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- releaser.release(m_base);
- releaser.release(m_args);
+ RefPtr<Label> realCall = generator.newLabel();
+ RefPtr<Label> end = generator.newLabel();
+ RefPtr<RegisterID> base = generator.emitNode(m_base);
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+ generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
+ {
+ RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ ArgumentListNode* oldList = m_args->m_listNode;
+ if (m_args->m_listNode && m_args->m_listNode->m_expr) {
+ generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+ m_args->m_listNode = m_args->m_listNode->m_next;
+ } else
+ generator.emitLoad(thisRegister.get(), jsNull());
+
+ generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ generator.emitJump(end.get());
+ m_args->m_listNode = oldList;
+ }
+ generator.emitLabel(realCall.get());
+ {
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ }
+ generator.emitLabel(end.get());
+ return finalDestination.get();
+}
+
+static bool areTrivialApplyArguments(ArgumentsNode* args)
+{
+ return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
+ || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
}
-RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ // A few simple cases can be trivially handled as ordinary function calls.
+ // function.apply(), function.apply(arg) -> identical to function.call
+ // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
+ bool mayBeCall = areTrivialApplyArguments(m_args);
+
+ RefPtr<Label> realCall = generator.newLabel();
+ RefPtr<Label> end = generator.newLabel();
+ RefPtr<RegisterID> base = generator.emitNode(m_base);
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());
+ RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+ generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
+ {
+ if (mayBeCall) {
+ RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ ArgumentListNode* oldList = m_args->m_listNode;
+ if (m_args->m_listNode && m_args->m_listNode->m_expr) {
+ generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+ m_args->m_listNode = m_args->m_listNode->m_next;
+ if (m_args->m_listNode) {
+ ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
+ ASSERT(!m_args->m_listNode->m_next);
+ m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
+ }
+ } else
+ generator.emitLoad(thisRegister.get(), jsNull());
+ generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ m_args->m_listNode = oldList;
+ } else {
+ ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
+ RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
+ RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ RefPtr<RegisterID> argsRegister = generator.newTemporary();
+ generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+ ArgumentListNode* args = m_args->m_listNode->m_next;
+ bool isArgumentsApply = false;
+ if (args->m_expr->isResolveNode()) {
+ ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
+ isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
+ if (isArgumentsApply)
+ generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
+ }
+ if (!isArgumentsApply)
+ generator.emitNode(argsRegister.get(), args->m_expr);
+ while ((args = args->m_next))
+ generator.emitNode(args->m_expr);
+
+ generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
+ generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
+ }
+ generator.emitJump(end.get());
+ }
+ generator.emitLabel(realCall.get());
+ {
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ }
+ generator.emitLabel(end.get());
+ return finalDestination.get();
}
// ------------------------------ PostfixResolveNode ----------------------------------
static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
{
+ if (srcDst == dst)
+ return generator.emitToJSNumber(dst, srcDst);
return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
}
// ------------------------------ 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());
+ RefPtr<RegisterID> base = generator.emitNode(m_base);
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript);
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
// ------------------------------ 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());
+ RefPtr<RegisterID> base = generator.emitNode(m_base);
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
// ------------------------------ 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.");
RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
if (generator.registerFor(m_ident))
- return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
+ return generator.emitLoad(generator.finalDestination(dst), false);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), 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());
+ RefPtr<RegisterID> r0 = generator.emitNode(m_base);
+ RegisterID* r1 = generator.emitNode(m_subscript);
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());
+ RegisterID* r0 = generator.emitNode(m_base);
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());
+ generator.emitNode(generator.ignoredResult(), m_expr);
// delete on a non-location expression ignores the value and returns true
- return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
+ return generator.emitLoad(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());
+ generator.emitNode(generator.ignoredResult(), m_expr);
return 0;
}
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
return generator.emitLoad(dst, jsUndefined());
}
// ------------------------------ 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());
+ generator.emitNode(generator.ignoredResult(), m_expr);
return 0;
}
- RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> src = generator.emitNode(m_expr);
return generator.emitTypeOf(generator.finalDestination(dst), src.get());
}
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);
+ RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
}
// ------------------------------ 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> base = generator.emitNode(m_base);
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript);
RefPtr<RegisterID> propDst = generator.tempDestination(dst);
generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
// ------------------------------ 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> base = generator.emitNode(m_base);
RefPtr<RegisterID> propDst = generator.tempDestination(dst);
generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
// ------------------------------ 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());
+ RegisterID* src = generator.emitNode(m_expr);
return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
}
// ------------------------------ Binary Operation Nodes -----------------------------------
-BinaryOpNode::~BinaryOpNode()
-{
- NodeReleaser::releaseAllNodes(this);
-}
+// BinaryOpNode::emitStrcat:
+//
+// This node generates an op_strcat operation. This opcode can handle concatenation of three or
+// more values, where we can determine a set of separate op_add operations would be operating on
+// string values.
+//
+// This function expects to be operating on a graph of AST nodes looking something like this:
+//
+// (a)... (b)
+// \ /
+// (+) (c)
+// \ /
+// [d] ((+))
+// \ /
+// [+=]
+//
+// The assignment operation is optional, if it exists the register holding the value on the
+// lefthand side of the assignment should be passing as the optional 'lhs' argument.
+//
+// The method should be called on the node at the root of the tree of regular binary add
+// operations (marked in the diagram with a double set of parentheses). This node must
+// be performing a string concatenation (determined by statically detecting that at least
+// one child must be a string).
+//
+// Since the minimum number of values being concatenated together is expected to be 3, if
+// a lhs to a concatenating assignment is not provided then the root add should have at
+// least one left child that is also an add that can be determined to be operating on strings.
+//
+RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
+{
+ ASSERT(isAdd());
+ ASSERT(resultDescriptor().definitelyIsString());
+
+ // Create a list of expressions for all the adds in the tree of nodes we can convert into
+ // a string concatenation. The rightmost node (c) is added first. The rightmost node is
+ // added first, and the leftmost child is never added, so the vector produced for the
+ // example above will be [ c, b ].
+ Vector<ExpressionNode*, 16> reverseExpressionList;
+ reverseExpressionList.append(m_expr2);
+
+ // Examine the left child of the add. So long as this is a string add, add its right-child
+ // to the list, and keep processing along the left fork.
+ ExpressionNode* leftMostAddChild = m_expr1;
+ while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
+ reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
+ leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
+ }
-void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
-{
- releaser.release(m_expr1);
- releaser.release(m_expr2);
+ Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
+
+ // If there is an assignment, allocate a temporary to hold the lhs after conversion.
+ // We could possibly avoid this (the lhs is converted last anyway, we could let the
+ // op_strcat node handle its conversion if required).
+ if (lhs)
+ temporaryRegisters.append(generator.newTemporary());
+
+ // Emit code for the leftmost node ((a) in the example).
+ temporaryRegisters.append(generator.newTemporary());
+ RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
+ generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
+
+ // Note on ordering of conversions:
+ //
+ // We maintain the same ordering of conversions as we would see if the concatenations
+ // was performed as a sequence of adds (otherwise this optimization could change
+ // behaviour should an object have been provided a valueOf or toString method).
+ //
+ // Considering the above example, the sequnce of execution is:
+ // * evaluate operand (a)
+ // * evaluate operand (b)
+ // * convert (a) to primitive <- (this would be triggered by the first add)
+ // * convert (b) to primitive <- (ditto)
+ // * evaluate operand (c)
+ // * convert (c) to primitive <- (this would be triggered by the second add)
+ // And optionally, if there is an assignment:
+ // * convert (d) to primitive <- (this would be triggered by the assigning addition)
+ //
+ // As such we do not plant an op to convert the leftmost child now. Instead, use
+ // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
+ // once the second node has been generated. However, if the leftmost child is an
+ // immediate we can trivially determine that no conversion will be required.
+ // If this is the case
+ if (leftMostAddChild->isString())
+ leftMostAddChildTempRegister = 0;
+
+ while (reverseExpressionList.size()) {
+ ExpressionNode* node = reverseExpressionList.last();
+ reverseExpressionList.removeLast();
+
+ // Emit the code for the current node.
+ temporaryRegisters.append(generator.newTemporary());
+ generator.emitNode(temporaryRegisters.last().get(), node);
+
+ // On the first iteration of this loop, when we first reach this point we have just
+ // generated the second node, which means it is time to convert the leftmost operand.
+ if (leftMostAddChildTempRegister) {
+ generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
+ leftMostAddChildTempRegister = 0; // Only do this once.
+ }
+ // Plant a conversion for this node, if necessary.
+ if (!node->isString())
+ generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
+ }
+ ASSERT(temporaryRegisters.size() >= 3);
+
+ // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
+ // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
+ if (emitExpressionInfoForMe)
+ generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
+
+ // If there is an assignment convert the lhs now. This will also copy lhs to
+ // the temporary register we allocated for it.
+ if (lhs)
+ generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
+
+ return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
}
RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
OpcodeID opcodeID = this->opcodeID();
+
+ if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
+ return emitStrcat(generator, dst);
+
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());
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2);
return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
}
{
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());
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2);
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());
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+ RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitGetByIdExceptionInfo(op_instanceof);
// ------------------------------ 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());
+ generator.emitNode(temp.get(), m_expr1);
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.emitNode(temp.get(), m_expr2);
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());
+ RegisterID* cond = generator.emitNode(m_logical);
generator.emitJumpIfFalse(cond, beforeElse.get());
- generator.emitNode(newDst.get(), m_expr1.get());
+ generator.emitNode(newDst.get(), m_expr1);
generator.emitJump(afterElse.get());
generator.emitLabel(beforeElse.get());
- generator.emitNode(newDst.get(), m_expr2.get());
+ generator.emitNode(newDst.get(), m_expr2);
generator.emitLabel(afterElse.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)
+static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
{
OpcodeID opcodeID;
switch (oper) {
opcodeID = op_div;
break;
case OpPlusEq:
+ if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
+ return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
opcodeID = op_add;
break;
case OpMinusEq:
ASSERT_NOT_REACHED();
return dst;
}
-
+
+ RegisterID* src2 = generator.emitNode(m_right);
+
+ // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
+ // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
+ if (emitExpressionInfoForMe)
+ generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
+
return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
}
{
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()));
+ return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, 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()));
+ emitReadModifyAssignment(generator, result.get(), result.get(), m_right, 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()));
+ RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
return generator.moveToDestinationIfNeeded(dst, result);
}
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()));
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, 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()));
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
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());
+ return generator.emitNode(dst, m_right);
- RegisterID* result = generator.emitNode(local, m_right.get());
+ RegisterID* result = generator.emitNode(local, m_right);
return generator.moveToDestinationIfNeeded(dst, result);
}
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());
+ RegisterID* value = generator.emitNode(dst, m_right);
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());
+ RegisterID* value = generator.emitNode(dst, m_right);
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> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
- RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ RegisterID* result = generator.emitNode(value.get(), m_right);
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);
-}
+// ------------------------------ ReadModifyDotNode -----------------------------------
RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, 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()));
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, 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> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
- RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ RegisterID* result = generator.emitNode(value.get(), m_right);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitPutByVal(base.get(), property.get(), 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));
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, 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()));
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitPutByVal(base.get(), property.get(), 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());
+ ASSERT(m_expressions.size() > 1);
+ for (size_t i = 0; i < m_expressions.size() - 1; i++)
+ generator.emitNode(generator.ignoredResult(), m_expressions[i]);
+ return generator.emitNode(dst, m_expressions.last());
}
// ------------------------------ 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());
+ return generator.emitNode(local, m_init);
}
// 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());
+ RegisterID* value = m_init ? generator.emitNode(m_init) : 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())
+ for (ConstDeclNode* n = this; n; n = n->m_next)
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());
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+ return generator.emitNode(m_next);
}
// ------------------------------ 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()
+static inline void statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst)
{
- NodeReleaser::releaseAllNodes(this);
-}
-
-void BlockNode::releaseNodes(NodeReleaser& releaser)
-{
- size_t size = m_children.size();
+ size_t size = statements.size();
for (size_t i = 0; i < size; ++i)
- releaser.release(m_children[i]);
+ generator.emitNode(dst, statements[i]);
}
-BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
- : StatementNode(globalData)
-{
- if (children)
- children->releaseContentsIntoVector(m_children);
-}
+// ------------------------------ BlockNode ------------------------------------
RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- return statementListEmitCode(m_children, generator, dst);
+ statementListEmitCode(m_children, generator, dst);
+ return 0;
}
// ------------------------------ EmptyStatementNode ---------------------------
-RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst)
+RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
return dst;
}
RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
ASSERT(m_expr);
- return generator.emitNode(dst, m_expr.get());
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+ return generator.emitNode(dst, m_expr);
}
// ------------------------------ 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());
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+ return generator.emitNode(m_expr);
}
// ------------------------------ 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)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
RefPtr<Label> afterThen = generator.newLabel();
- RegisterID* cond = generator.emitNode(m_condition.get());
+ RegisterID* cond = generator.emitNode(m_condition);
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.emitNode(dst, m_ifBlock);
generator.emitLabel(afterThen.get());
// FIXME: This should return the last statement executed so that it can be returned as a Completion.
// ------------------------------ 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)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
RefPtr<Label> beforeElse = generator.newLabel();
RefPtr<Label> afterElse = generator.newLabel();
- RegisterID* cond = generator.emitNode(m_condition.get());
+ RegisterID* cond = generator.emitNode(m_condition);
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.emitNode(dst, m_ifBlock);
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.emitNode(dst, m_elseBlock);
generator.emitLabel(afterElse.get());
// ------------------------------ 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);
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());
+
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
- RegisterID* cond = generator.emitNode(m_expr.get());
+ RegisterID* cond = generator.emitNode(m_expr);
generator.emitJumpIfTrue(cond, topOfLoop.get());
generator.emitLabel(scope->breakTarget());
// ------------------------------ 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);
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.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
- RegisterID* cond = generator.emitNode(m_expr.get());
+ RegisterID* cond = generator.emitNode(m_expr);
generator.emitJumpIfTrue(cond, topOfLoop.get());
generator.emitLabel(scope->breakTarget());
// ------------------------------ 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());
+ generator.emitNode(generator.ignoredResult(), m_expr1);
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());
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
if (m_expr3)
- generator.emitNode(generator.ignoredResult(), m_expr3.get());
+ generator.emitNode(generator.ignoredResult(), m_expr3);
generator.emitLabel(condition.get());
if (m_expr2) {
- RegisterID* cond = generator.emitNode(m_expr2.get());
+ RegisterID* cond = generator.emitNode(m_expr2);
generator.emitJumpIfTrue(cond, topOfLoop.get());
} else
generator.emitJump(topOfLoop.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);
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
if (m_init)
- generator.emitNode(generator.ignoredResult(), m_init.get());
- RegisterID* forInBase = generator.emitNode(m_expr.get());
+ generator.emitNode(generator.ignoredResult(), m_init);
+ RegisterID* forInBase = generator.emitNode(m_expr);
RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
generator.emitJump(scope->continueTarget());
RegisterID* propertyName;
if (m_lexpr->isResolveNode()) {
- const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
+ const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
propertyName = generator.registerFor(ident);
if (!propertyName) {
propertyName = generator.newTemporary();
generator.emitPutById(base, ident, propertyName);
}
} else if (m_lexpr->isDotAccessorNode()) {
- DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
+ DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
const Identifier& ident = assignNode->identifier();
propertyName = generator.newTemporary();
RefPtr<RegisterID> protect = propertyName;
generator.emitPutById(base, ident, propertyName);
} else {
ASSERT(m_lexpr->isBracketAccessorNode());
- BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
+ BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
propertyName = generator.newTemporary();
RefPtr<RegisterID> protect = propertyName;
RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
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.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
generator.emitLabel(scope->breakTarget());
return dst;
}
// ECMA 12.7
RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
LabelScope* scope = generator.continueTarget(m_ident);
if (!scope)
// ECMA 12.8
RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
LabelScope* scope = generator.breakTarget(m_ident);
if (!scope)
// ------------------------------ ReturnNode -----------------------------------
-ReturnNode::~ReturnNode()
-{
- NodeReleaser::releaseAllNodes(this);
-}
-
-void ReturnNode::releaseNodes(NodeReleaser& releaser)
-{
- releaser.release(m_value);
-}
-
RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
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());
+ RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
RefPtr<RegisterID> returnRegister;
if (generator.scopeDepth()) {
RefPtr<Label> l0 = generator.newLabel();
// ------------------------------ 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)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
RefPtr<RegisterID> scope = generator.newTemporary();
- generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped
+ generator.emitNode(scope.get(), m_expr); // 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());
+ RegisterID* result = generator.emitNode(dst, m_statement);
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,
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)) {
+ int32_t intVal = static_cast<int32_t>(value);
+ if ((typeForTable & ~SwitchNumber) || (intVal != 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)
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);
+ processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+ processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
return SwitchInfo::SwitchNone;
generator.beginSwitch(switchExpression, switchType);
} else {
// Setup jumps
- for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ for (ClauseListNode* list = m_list1; 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());
generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
}
- for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ for (ClauseListNode* list = m_list2; 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());
RegisterID* result = 0;
size_t i = 0;
- for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
generator.emitLabel(labelVector[i++].get());
- result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ statementListEmitCode(list->getClause()->children(), generator, dst);
}
if (m_defaultClause) {
generator.emitLabel(defaultLabel.get());
- result = statementListEmitCode(m_defaultClause->children(), generator, dst);
+ statementListEmitCode(m_defaultClause->children(), generator, dst);
}
- for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
generator.emitLabel(labelVector[i++].get());
- result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ statementListEmitCode(list->getClause()->children(), generator, dst);
}
if (!m_defaultClause)
generator.emitLabel(defaultLabel.get());
// ------------------------------ 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)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
- RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
generator.emitLabel(scope->breakTarget());
// ------------------------------ LabelNode ------------------------------------
-LabelNode::~LabelNode()
-{
- NodeReleaser::releaseAllNodes(this);
-}
-
-void LabelNode::releaseNodes(NodeReleaser& releaser)
-{
- releaser.release(m_statement);
-}
-
RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
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());
+ RegisterID* r0 = generator.emitNode(dst, m_statement);
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)
{
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
if (dst == generator.ignoredResult())
dst = 0;
- RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
+ RefPtr<RegisterID> expr = generator.emitNode(m_expr);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitThrow(expr.get());
- return dst;
+ return 0;
}
// ------------------------------ TryNode --------------------------------------
-TryNode::~TryNode()
+RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- NodeReleaser::releaseAllNodes(this);
-}
+ // NOTE: The catch and finally blocks must be labeled explicitly, so the
+ // optimizer knows they may be jumped to from anywhere.
-void TryNode::releaseNodes(NodeReleaser& releaser)
-{
- releaser.release(m_tryBlock);
- releaser.release(m_catchBlock);
- releaser.release(m_finallyBlock);
-}
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-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) {
finallyReturnAddr = generator.newTemporary();
generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
}
+
generator.emitLabel(tryStartLabel.get());
- generator.emitNode(dst, m_tryBlock.get());
- generator.emitLabel(tryEndLabel.get());
+ generator.emitNode(dst, m_tryBlock);
if (m_catchBlock) {
- RefPtr<Label> handlerEndLabel = generator.newLabel();
- generator.emitJump(handlerEndLabel.get());
- RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
+ RefPtr<Label> catchEndLabel = generator.newLabel();
+
+ // Normal path: jump over the catch block.
+ generator.emitJump(catchEndLabel.get());
+
+ // Uncaught exception path: the catch block.
+ RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
+ RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
if (m_catchHasEval) {
RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
generator.emitPushScope(exceptionRegister.get());
} else
generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
- generator.emitNode(dst, m_catchBlock.get());
+ generator.emitNode(dst, m_catchBlock);
generator.emitPopScope();
- generator.emitLabel(handlerEndLabel.get());
+ generator.emitLabel(catchEndLabel.get());
}
if (m_finallyBlock) {
// approach to not clobbering anything important
RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
RefPtr<Label> finallyEndLabel = generator.newLabel();
+
+ // Normal path: invoke the finally block, then jump over it.
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());
+ // Uncaught exception path: invoke the finally block, then re-throw the exception.
+ RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
+ RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.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
+ // The finally block.
generator.emitLabel(finallyStart.get());
- generator.emitNode(dst, m_finallyBlock.get());
+ generator.emitNode(dst, m_finallyBlock);
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)
+ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
: m_numConstants(numConstants)
{
+ m_arena.swap(arena);
if (varStack)
- m_varStack = *varStack;
+ m_varStack.swap(*varStack);
if (funcStack)
- m_functionStack = *funcStack;
+ m_functionStack.swap(*funcStack);
if (children)
children->releaseContentsIntoVector(m_children);
}
ScopeNode::ScopeNode(JSGlobalData* globalData)
: StatementNode(globalData)
+ , ParserArenaRefCounted(globalData)
, m_features(NoFeatures)
{
-#if ENABLE(OPCODE_SAMPLING)
- globalData->interpreter->sampler()->notifyOfScope(this);
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = globalData->interpreter->sampler())
+ 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))
+ , ParserArenaRefCounted(globalData)
+ , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
, m_features(features)
, m_source(source)
{
-#if ENABLE(OPCODE_SAMPLING)
- globalData->interpreter->sampler()->notifyOfScope(this);
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = globalData->interpreter->sampler())
+ 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)
+inline 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)
+PassRefPtr<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);
+ RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
+
+ ASSERT(node->data()->m_arena.last() == node);
+ node->data()->m_arena.removeLast();
+ ASSERT(!node->data()->m_arena.contains(node.get()));
+
+ return node.release();
}
RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
- BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get());
- generator.generate();
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get()));
+ generator->generate();
destroyData();
}
+#if ENABLE(JIT)
+void ProgramNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
// ------------------------------ EvalNode -----------------------------
-EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+inline 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)
+PassRefPtr<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);
+ RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
+
+ ASSERT(node->data()->m_arena.last() == node);
+ node->data()->m_arena.removeLast();
+ ASSERT(!node->data()->m_arena.contains(node.get()));
+
+ return node.release();
}
RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
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();
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(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.
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();
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator->generate();
return *m_code;
}
data()->mark();
}
+#if ENABLE(JIT)
+void EvalNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
// ------------------------------ FunctionBodyNode -----------------------------
-FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
+inline 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)
+inline 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);
m_code->mark();
}
+#if ENABLE(JIT)
+PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData)
+{
+ RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
+ globalData->parser->arena().reset();
+ body->m_code.set(new CodeBlock(body.get()));
+ body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk()));
+ return body.release();
+}
+#endif
+
+bool FunctionBodyNode::isHostFunction() const
+{
+ return m_code && m_code->codeType() == NativeCode;
+}
+
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)
+PassRefPtr<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);
+ RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
+
+ ASSERT(node->data()->m_arena.last() == node);
+ node->data()->m_arena.removeLast();
+ ASSERT(!node->data()->m_arena.contains(node.get()));
+
+ return node.release();
}
void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
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();
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->generate();
destroyData();
}
+#if ENABLE(JIT)
+void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode)
+{
+ bytecode(scopeChainNode);
+ ASSERT(m_code);
+ ASSERT(!m_jitCode);
+ JIT::compile(scopeChainNode->globalData, m_code.get());
+ ASSERT(m_jitCode);
+}
+#endif
+
CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
{
ASSERT(!m_code);
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();
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
+ generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
+ generator->generate();
return *m_code;
}
generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
statementListEmitCode(children(), generator, generator.ignoredResult());
if (children().size() && children().last()->isBlock()) {
- BlockNode* blockNode = static_cast<BlockNode*>(children().last().get());
+ BlockNode* blockNode = static_cast<BlockNode*>(children().last());
if (blockNode->children().size() && blockNode->children().last()->isReturnNode())
return 0;
}
// ------------------------------ 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);
// ------------------------------ 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);
*
*/
-#ifndef NODES_H_
-#define NODES_H_
+#ifndef Nodes_h
+#define Nodes_h
#include "Error.h"
+#include "JITCode.h"
#include "Opcode.h"
+#include "ParserArena.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 ArgumentListNode;
class CodeBlock;
class BytecodeGenerator;
class FuncDeclNode;
class EvalCodeBlock;
class JSFunction;
- class NodeReleaser;
class ProgramCodeBlock;
class PropertyListNode;
+ class ReadModifyResolveNode;
class RegisterID;
class ScopeChainNode;
namespace DeclarationStacks {
enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
typedef Vector<std::pair<Identifier, unsigned> > VarStack;
- typedef Vector<RefPtr<FuncDeclNode> > FunctionStack;
+ typedef Vector<FuncDeclNode*> FunctionStack;
}
struct SwitchInfo {
SwitchType switchType;
};
- class ParserRefCounted : Noncopyable {
+ class ParserArenaDeletable {
protected:
- ParserRefCounted(JSGlobalData*) JSC_FAST_CALL;
+ ParserArenaDeletable() { }
public:
- virtual ~ParserRefCounted();
+ virtual ~ParserArenaDeletable() { }
- // Nonrecursive destruction.
- virtual void releaseNodes(NodeReleaser&);
+ // Objects created with this version of new are deleted when the arena is deleted.
+ void* operator new(size_t, JSGlobalData*);
- void ref() JSC_FAST_CALL;
- void deref() JSC_FAST_CALL;
- bool hasOneRef() JSC_FAST_CALL;
+ // Objects created with this version of new are not deleted when the arena is deleted.
+ // Other arrangements must be made.
+ void* operator new(size_t);
+ };
- static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL;
+ class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
+ protected:
+ ParserArenaRefCounted(JSGlobalData*);
- private:
- JSGlobalData* m_globalData;
+ public:
+ virtual ~ParserArenaRefCounted()
+ {
+ ASSERT(deletionHasBegun());
+ }
};
- class Node : public ParserRefCounted {
- public:
- Node(JSGlobalData*) JSC_FAST_CALL;
+ class Node : public ParserArenaDeletable {
+ protected:
+ Node(JSGlobalData*);
+ public:
/*
Return value: The register holding the production's value.
dst: An optional parameter specifying the most efficient
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;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) = 0;
int lineNo() const { return 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; }
+ ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
+
+ virtual bool isNumber() const { return false; }
+ virtual bool isString() const { return false; }
+ virtual bool isNull() const { return false; }
+ virtual bool isPure(BytecodeGenerator&) const { return false; }
+ virtual bool isLocation() const { return false; }
+ virtual bool isResolveNode() const { return false; }
+ virtual bool isBracketAccessorNode() const { return false; }
+ virtual bool isDotAccessorNode() const { return false; }
+ virtual bool isFuncExprNode() const { return false; }
+ virtual bool isCommaNode() const { return false; }
+ virtual bool isSimpleArray() const { return false; }
+ virtual bool isAdd() const { return false; }
virtual ExpressionNode* stripUnaryPlus() { return this; }
- ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; }
+ ResultType resultDescriptor() const { return m_resultType; }
// This needs to be in public in order to compile using GCC 3.x
typedef enum { EvalOperator, FunctionCall } CallerType;
private:
- ResultType m_resultDesc;
+ ResultType m_resultType;
};
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; }
+ StatementNode(JSGlobalData*);
- 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; }
+ void setLoc(int line0, int line1);
+ int firstLine() const { return lineNo(); }
+ int lastLine() const { return m_lastLine; }
- virtual bool isBlock() const JSC_FAST_CALL { return false; }
- virtual bool isLoop() const JSC_FAST_CALL { return false; }
+ virtual bool isEmptyStatement() const { return false; }
+ virtual bool isReturnNode() const { return false; }
+ virtual bool isExprStatement() const { return false; }
+
+ virtual bool isBlock() const { return false; }
private:
int m_lastLine;
class NullNode : public ExpressionNode {
public:
- NullNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::nullType())
- {
- }
+ NullNode(JSGlobalData*);
- virtual bool isNull() const JSC_FAST_CALL { return true; }
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual bool isNull() const { return true; }
};
class BooleanNode : public ExpressionNode {
public:
- BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::booleanType())
- , m_value(value)
- {
- }
+ BooleanNode(JSGlobalData*, bool value);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+ virtual bool isPure(BytecodeGenerator&) const { 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)
- {
- }
+ NumberNode(JSGlobalData*, 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; }
+ double value() const { return m_double; }
+ void setValue(double d) { m_double = d; }
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isNumber() const { return true; }
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
+
double m_double;
};
class StringNode : public ExpressionNode {
public:
- StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::stringType())
- , m_value(v)
- {
- }
+ StringNode(JSGlobalData*, const Identifier& 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; }
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isString() const { return true; }
+
Identifier m_value;
};
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;
+ RegExpNode(JSGlobalData*, const UString& pattern, const UString& flags);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
UString m_pattern;
UString m_flags;
};
class ThisNode : public ExpressionNode {
public:
- ThisNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ExpressionNode(globalData)
- {
- }
+ ThisNode(JSGlobalData*);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
class ResolveNode : public ExpressionNode {
public:
- ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_ident(ident)
- , m_startOffset(startOffset)
- {
- }
+ ResolveNode(JSGlobalData*, const Identifier&, int 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; }
+ const Identifier& identifier() const { return m_ident; }
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isPure(BytecodeGenerator&) const ;
+ virtual bool isLocation() const { return true; }
+ virtual bool isResolveNode() const { return true; }
+
Identifier m_ident;
int32_t m_startOffset;
};
- class ElementNode : public ParserRefCounted {
+ class ElementNode : public ParserArenaDeletable {
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&);
+ ElementNode(JSGlobalData*, int elision, ExpressionNode*);
+ ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*);
int elision() const { return m_elision; }
- ExpressionNode* value() { return m_node.get(); }
-
- ElementNode* next() { return m_next.get(); }
+ ExpressionNode* value() { return m_node; }
+ ElementNode* next() { return m_next; }
private:
- RefPtr<ElementNode> m_next;
+ ElementNode* m_next;
int m_elision;
- RefPtr<ExpressionNode> m_node;
+ 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*, int elision);
+ ArrayNode(JSGlobalData*, ElementNode*);
+ ArrayNode(JSGlobalData*, int elision, ElementNode*);
- ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_element(element)
- , m_elision(elision)
- , m_optional(true)
- {
- }
+ ArgumentListNode* toArgumentList(JSGlobalData*) const;
- virtual ~ArrayNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual bool isSimpleArray() const ;
- private:
- RefPtr<ElementNode> m_element;
+ ElementNode* m_element;
int m_elision;
bool m_optional;
};
- class PropertyNode : public ParserRefCounted {
+ class PropertyNode : public ParserArenaDeletable {
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&);
+ PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
const Identifier& name() const { return m_name; }
private:
friend class PropertyListNode;
Identifier m_name;
- RefPtr<ExpressionNode> m_assign;
+ 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&);
+ PropertyListNode(JSGlobalData*, PropertyNode*);
+ PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
private:
- RefPtr<PropertyNode> m_node;
- RefPtr<PropertyListNode> m_next;
+ PropertyNode* m_node;
+ 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;
+ ObjectLiteralNode(JSGlobalData*);
+ ObjectLiteralNode(JSGlobalData*, PropertyListNode*);
private:
- RefPtr<PropertyListNode> m_list;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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)
- {
- }
+ BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments);
- virtual ~BracketAccessorNode();
- virtual void releaseNodes(NodeReleaser&);
+ ExpressionNode* base() const { return m_base; }
+ ExpressionNode* subscript() const { return m_subscript; }
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- 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(); }
+ virtual bool isLocation() const { return true; }
+ virtual bool isBracketAccessorNode() const { return true; }
- private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
+ ExpressionNode* m_base;
+ 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)
- {
- }
+ DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&);
- virtual ~DotAccessorNode();
- virtual void releaseNodes(NodeReleaser&);
+ ExpressionNode* base() const { return m_base; }
+ const Identifier& identifier() const { return m_ident; }
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- 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; }
+ virtual bool isLocation() const { return true; }
+ virtual bool isDotAccessorNode() const { return true; }
- private:
- RefPtr<ExpressionNode> m_base;
+ 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*, ExpressionNode*);
+ ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*);
- 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;
+ ArgumentListNode* m_next;
+ ExpressionNode* m_expr;
- RefPtr<ArgumentListNode> m_next;
- RefPtr<ExpressionNode> m_expr;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
- class ArgumentsNode : public ParserRefCounted {
+ class ArgumentsNode : public ParserArenaDeletable {
public:
- ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL
- : ParserRefCounted(globalData)
- {
- }
-
- ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL
- : ParserRefCounted(globalData)
- , m_listNode(listNode)
- {
- }
+ ArgumentsNode(JSGlobalData*);
+ ArgumentsNode(JSGlobalData*, ArgumentListNode*);
- virtual ~ArgumentsNode();
- virtual void releaseNodes(NodeReleaser&);
-
- RefPtr<ArgumentListNode> m_listNode;
+ 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;
+ NewExprNode(JSGlobalData*, ExpressionNode*);
+ NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*);
private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ 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;
+ EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ArgumentsNode> m_args;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<ArgumentsNode> m_args;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ 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;
+ FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
+ 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;
+ FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ArgumentsNode> m_args;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ 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)
- {
- }
+ FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual ~FunctionCallDotNode();
- virtual void releaseNodes(NodeReleaser&);
+ protected:
+ ExpressionNode* m_base;
+ const Identifier m_ident;
+ ArgumentsNode* m_args;
+ };
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ class CallFunctionCallDotNode : public FunctionCallDotNode {
+ public:
+ CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- Identifier m_ident;
- RefPtr<ArgumentsNode> m_args;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class ApplyFunctionCallDotNode : public FunctionCallDotNode {
+ public:
+ ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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)
- {
- }
+ PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
protected:
- Identifier m_ident;
+ const 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;
+ PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
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;
+ PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ 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;
+ PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
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;
+ DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ 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;
+ DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ DeleteValueNode(JSGlobalData*, ExpressionNode*);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ VoidNode(JSGlobalData*, ExpressionNode*);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
};
class TypeOfResolveNode : public ExpressionNode {
public:
- TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
- : ExpressionNode(globalData, ResultType::stringType())
- , m_ident(ident)
- {
- }
+ TypeOfResolveNode(JSGlobalData*, const Identifier&);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
- const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+ const Identifier& identifier() const { return m_ident; }
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
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;
+ TypeOfValueNode(JSGlobalData*, ExpressionNode*);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
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;
+ PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ 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;
+ PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
Operator m_operator;
};
class UnaryOpNode : public ExpressionNode {
public:
- UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr)
- : ExpressionNode(globalData)
- , m_expr(expr)
- {
- }
+ UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID);
- UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr)
- : ExpressionNode(globalData, type)
- , m_expr(expr)
- {
- }
+ protected:
+ ExpressionNode* expr() { return m_expr; }
- virtual ~UnaryOpNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+ OpcodeID opcodeID() const { return m_opcodeID; }
- protected:
- RefPtr<ExpressionNode> m_expr;
+ ExpressionNode* m_expr;
+ OpcodeID m_opcodeID;
};
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(); }
+ UnaryPlusNode(JSGlobalData*, ExpressionNode*);
- virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; }
+ private:
+ virtual ExpressionNode* stripUnaryPlus() { return expr(); }
};
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; }
+ NegateNode(JSGlobalData*, ExpressionNode*);
};
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; }
+ BitwiseNotNode(JSGlobalData*, ExpressionNode*);
};
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; }
+ LogicalNotNode(JSGlobalData*, ExpressionNode*);
};
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*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
- BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : ExpressionNode(globalData, type)
- , m_expr1(expr1)
- , m_expr2(expr2)
- , m_rightHasAssignments(rightHasAssignments)
- {
- }
+ RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
- virtual ~BinaryOpNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+ protected:
+ OpcodeID opcodeID() const { return m_opcodeID; }
protected:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ private:
+ OpcodeID m_opcodeID;
+ protected:
bool m_rightHasAssignments;
};
class ReverseBinaryOpNode : public BinaryOpNode {
public:
- ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
- : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
- {
- }
+ ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool 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;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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; }
+ MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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)
- {
- }
+ AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
- virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; }
+ virtual bool isAdd() const { return true; }
};
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; }
+ SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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;
+ ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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; }
+ InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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; }
+ InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
class EqualNode : public BinaryOpNode {
public:
- EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
- {
- }
+ EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; }
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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; }
+ NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
class StrictEqualNode : public BinaryOpNode {
public:
- StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
- : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments)
- {
- }
+ StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; }
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
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; }
+ NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
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; }
+ BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
};
- /**
- * m_expr1 && m_expr2, m_expr1 || m_expr2
- */
+ // 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;
+ LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator);
private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
LogicalOperator m_operator;
};
- /**
- * The ternary operator, "m_logical ? m_expr1 : m_expr2"
- */
+ // 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;
+ ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2);
private:
- RefPtr<ExpressionNode> m_logical;
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_logical;
+ ExpressionNode* m_expr1;
+ 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;
+ ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
+ ExpressionNode* m_right;
size_t m_index; // Used by ReadModifyLocalVarNode.
- Operator m_operator : 31;
- bool m_rightHasAssignments : 1;
+ Operator m_operator;
+ bool m_rightHasAssignments;
};
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;
+ AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
+ 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;
+ ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ExpressionNode> m_right;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ 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;
+ AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
- RefPtr<ExpressionNode> m_subscript;
- RefPtr<ExpressionNode> m_right;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ 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;
+ AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
+ 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;
+ ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_base;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
Identifier m_ident;
- RefPtr<ExpressionNode> m_right;
+ 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;
+ AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset);
private:
- RefPtr<ExpressionNode> m_left;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_left;
Operator m_operator;
- RefPtr<ExpressionNode> m_right;
+ ExpressionNode* m_right;
};
+
+ typedef Vector<ExpressionNode*, 8> ExpressionVector;
class CommaNode : public ExpressionNode {
public:
- CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
- : ExpressionNode(globalData)
- , m_expr1(expr1)
- , m_expr2(expr2)
- {
- }
+ CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2);
- virtual ~CommaNode();
- virtual void releaseNodes(NodeReleaser&);
-
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ void append(ExpressionNode* expr) { m_expressions.append(expr); }
private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
+ virtual bool isCommaNode() const { return true; }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionVector m_expressions;
};
- 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;
+ ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*);
+
+ bool hasInitializer() const { return m_init; }
+ const Identifier& ident() { return m_ident; }
- virtual ~ConstDeclNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
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)
- {
- }
+ ConstDeclNode* m_next;
- virtual ~ConstStatementNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ ExpressionNode* m_init;
+ };
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ class ConstStatementNode : public StatementNode {
+ public:
+ ConstStatementNode(JSGlobalData*, ConstDeclNode* next);
private:
- RefPtr<ConstDeclNode> m_next;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ConstDeclNode* m_next;
};
- typedef Vector<RefPtr<StatementNode> > StatementVector;
+ typedef Vector<StatementNode*> StatementVector;
- class SourceElements : public ParserRefCounted {
+ class SourceElements : public ParserArenaDeletable {
public:
- SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {}
+ SourceElements(JSGlobalData*);
- void append(PassRefPtr<StatementNode>);
+ void append(StatementNode*);
void releaseContentsIntoVector(StatementVector& destination)
{
ASSERT(destination.isEmpty());
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;
+ BlockNode(JSGlobalData*, SourceElements* children);
StatementVector& children() { return m_children; }
- virtual bool isBlock() const JSC_FAST_CALL { return true; }
-
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isBlock() const { return true; }
+
StatementVector m_children;
};
class EmptyStatementNode : public StatementNode {
public:
- EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug
- : StatementNode(globalData)
- {
- }
+ EmptyStatementNode(JSGlobalData*);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; }
+ virtual bool isEmptyStatement() const { return true; }
};
class DebuggerStatementNode : public StatementNode {
public:
- DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL
- : StatementNode(globalData)
- {
- }
+ DebuggerStatementNode(JSGlobalData*);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
class ExprStatementNode : public StatementNode {
public:
- ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_expr(expr)
- {
- }
+ ExprStatementNode(JSGlobalData*, ExpressionNode*);
- virtual bool isExprStatement() const JSC_FAST_CALL { return true; }
+ ExpressionNode* expr() const { return m_expr; }
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ private:
+ virtual bool isExprStatement() const { return true; }
- ExpressionNode* expr() const { return m_expr.get(); }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- private:
- RefPtr<ExpressionNode> m_expr;
+ 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;
+ VarStatementNode(JSGlobalData*, ExpressionNode*);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock);
protected:
- RefPtr<ExpressionNode> m_condition;
- RefPtr<StatementNode> m_ifBlock;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_condition;
+ 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;
+ IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
private:
- RefPtr<StatementNode> m_elseBlock;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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; }
+ DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*);
private:
- RefPtr<StatementNode> m_statement;
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ StatementNode* m_statement;
+ 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; }
+ WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement);
private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ 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; }
+ ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl);
private:
- RefPtr<ExpressionNode> m_expr1;
- RefPtr<ExpressionNode> m_expr2;
- RefPtr<ExpressionNode> m_expr3;
- RefPtr<StatementNode> m_statement;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ ExpressionNode* m_expr3;
+ 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; }
+ ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*);
+ ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_ident;
- RefPtr<ExpressionNode> m_init;
- RefPtr<ExpressionNode> m_lexpr;
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
+ ExpressionNode* m_init;
+ ExpressionNode* m_lexpr;
+ ExpressionNode* m_expr;
+ 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)
- {
- }
+ ContinueNode(JSGlobalData*);
+ ContinueNode(JSGlobalData*, const Identifier&);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
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)
- {
- }
+ BreakNode(JSGlobalData*);
+ BreakNode(JSGlobalData*, const Identifier&);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
-
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_ident;
};
class ReturnNode : public StatementNode, public ThrowableExpressionData {
public:
- ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL
- : StatementNode(globalData)
- , m_value(value)
- {
- }
+ ReturnNode(JSGlobalData*, ExpressionNode* value);
- virtual ~ReturnNode();
- virtual void releaseNodes(NodeReleaser&);
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
- virtual bool isReturnNode() const JSC_FAST_CALL { return true; }
+ virtual bool isReturnNode() const { return true; }
- private:
- RefPtr<ExpressionNode> m_value;
+ 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;
+ WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength);
private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<StatementNode> m_statement;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ 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;
+ LabelNode(JSGlobalData*, const Identifier& name, StatementNode*);
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
Identifier m_name;
- RefPtr<StatementNode> m_statement;
+ 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;
+ ThrowNode(JSGlobalData*, ExpressionNode*);
private:
- RefPtr<ExpressionNode> m_expr;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ 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;
+ TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
private:
- RefPtr<StatementNode> m_tryBlock;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0);
+
+ StatementNode* m_tryBlock;
Identifier m_exceptionIdent;
- RefPtr<StatementNode> m_catchBlock;
- RefPtr<StatementNode> m_finallyBlock;
+ StatementNode* m_catchBlock;
+ StatementNode* m_finallyBlock;
bool m_catchHasEval;
};
- class ParameterNode : public ParserRefCounted {
+ class ParameterNode : public ParserArenaDeletable {
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&);
+ ParameterNode(JSGlobalData*, const Identifier&);
+ ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&);
- const Identifier& ident() const JSC_FAST_CALL { return m_ident; }
- ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); }
+ const Identifier& ident() const { return m_ident; }
+ ParameterNode* nextParam() const { return m_next; }
private:
Identifier m_ident;
- RefPtr<ParameterNode> m_next;
+ ParameterNode* m_next;
};
struct ScopeNodeData {
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
- ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants);
+ ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants);
+ ParserArena m_arena;
VarStack m_varStack;
FunctionStack m_functionStack;
int m_numConstants;
void mark();
};
- class ScopeNode : public StatementNode {
+ class ScopeNode : public StatementNode, public ParserArenaRefCounted {
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&);
+ ScopeNode(JSGlobalData*);
+ ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
- void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); }
+ void adoptData(std::auto_ptr<ScopeNodeData> data)
+ {
+ ASSERT(!data->m_arena.contains(this));
+ ASSERT(!m_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(); }
+ const UString& sourceURL() const { return m_source.provider()->url(); }
intptr_t sourceID() const { return m_source.provider()->asID(); }
void setFeatures(CodeFeatures features) { m_features = features; }
virtual void mark() { }
+#if ENABLE(JIT)
+ JITCode& generatedJITCode()
+ {
+ ASSERT(m_jitCode);
+ return m_jitCode;
+ }
+
+ ExecutablePool* getExecutablePool()
+ {
+ return m_jitCode.getExecutablePool();
+ }
+
+ void setJITCode(const JITCode jitCode)
+ {
+ m_jitCode = jitCode;
+ }
+#endif
+
protected:
void setSource(const SourceCode& source) { m_source = source; }
+#if ENABLE(JIT)
+ JITCode m_jitCode;
+#endif
+
private:
OwnPtr<ScopeNodeData> m_data;
CodeFeatures m_features;
class ProgramNode : public ScopeNode {
public:
- static ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
- ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain)
{
if (!m_code)
generateBytecode(scopeChain);
return *m_code;
}
+#if ENABLE(JIT)
+ JITCode& jitCode(ScopeChainNode* scopeChain)
+ {
+ if (!m_jitCode)
+ generateJITCode(scopeChain);
+ return m_jitCode;
+ }
+#endif
+
private:
- ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+
+ void generateBytecode(ScopeChainNode*);
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+#if ENABLE(JIT)
+ void generateJITCode(ScopeChainNode*);
+#endif
OwnPtr<ProgramCodeBlock> m_code;
};
class EvalNode : public ScopeNode {
public:
- static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
- EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ EvalCodeBlock& bytecode(ScopeChainNode* scopeChain)
{
if (!m_code)
generateBytecode(scopeChain);
return *m_code;
}
- EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL;
+ EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*);
virtual void mark();
+#if ENABLE(JIT)
+ JITCode& jitCode(ScopeChainNode* scopeChain)
+ {
+ if (!m_jitCode)
+ generateJITCode(scopeChain);
+ return m_jitCode;
+ }
+#endif
+
private:
- EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
- void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ void generateBytecode(ScopeChainNode*);
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+#if ENABLE(JIT)
+ void generateJITCode(ScopeChainNode*);
+#endif
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;
+#if ENABLE(JIT)
+ static PassRefPtr<FunctionBodyNode> createNativeThunk(JSGlobalData*);
+#endif
+ static FunctionBodyNode* create(JSGlobalData*);
+ static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
virtual ~FunctionBodyNode();
- const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; }
+ const Identifier* parameters() const { return m_parameters; }
size_t parameterCount() const { return m_parameterCount; }
- UString paramString() const JSC_FAST_CALL;
+ UString paramString() const ;
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;
- }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
- bool isGenerated() JSC_FAST_CALL
+ bool isGenerated() const
{
return m_code;
}
+ bool isHostFunction() const;
+
virtual void mark();
void finishParsing(const SourceCode&, ParameterNode*);
void finishParsing(Identifier* parameters, size_t parameterCount);
- UString toSourceString() const JSC_FAST_CALL { return source().toString(); }
+ UString toSourceString() const { 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()
+ CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*);
+#if ENABLE(JIT)
+ JITCode& jitCode(ScopeChainNode* scopeChain)
{
- if (++m_refCount == 1)
- ScopeNode::ref();
+ if (!m_jitCode)
+ generateJITCode(scopeChain);
+ return m_jitCode;
}
- void deref()
+#endif
+
+ CodeBlock& bytecode(ScopeChainNode* scopeChain)
{
- ASSERT(m_refCount);
- if (!--m_refCount)
- ScopeNode::deref();
+ ASSERT(scopeChain);
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
}
-
- CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL;
-
+
+ CodeBlock& generatedBytecode()
+ {
+ ASSERT(m_code);
+ return *m_code;
+ }
+
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;
+ FunctionBodyNode(JSGlobalData*);
+ FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ void generateBytecode(ScopeChainNode*);
+#if ENABLE(JIT)
+ void generateJITCode(ScopeChainNode*);
+#endif
Identifier* m_parameters;
size_t m_parameterCount;
OwnPtr<CodeBlock> m_code;
- unsigned m_refCount;
};
- class FuncExprNode : public ExpressionNode {
+ class FuncExprNode : public ExpressionNode, public ParserArenaRefCounted {
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());
- }
+ FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0);
- 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;
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*);
FunctionBodyNode* body() { return m_body.get(); }
private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isFuncExprNode() const { return true; }
+
Identifier m_ident;
- RefPtr<ParameterNode> m_parameter;
RefPtr<FunctionBodyNode> m_body;
};
- class FuncDeclNode : public StatementNode {
+ class FuncDeclNode : public StatementNode, public ParserArenaRefCounted {
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;
+ FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
- JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*);
Identifier m_ident;
FunctionBodyNode* body() { return m_body.get(); }
private:
- RefPtr<ParameterNode> m_parameter;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
RefPtr<FunctionBodyNode> m_body;
};
- class CaseClauseNode : public ParserRefCounted {
+ class CaseClauseNode : public ParserArenaDeletable {
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&);
+ CaseClauseNode(JSGlobalData*, ExpressionNode*);
+ CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements*);
- ExpressionNode* expr() const { return m_expr.get(); }
+ ExpressionNode* expr() const { return m_expr; }
StatementVector& children() { return m_children; }
private:
- RefPtr<ExpressionNode> m_expr;
+ ExpressionNode* m_expr;
StatementVector m_children;
};
- class ClauseListNode : public ParserRefCounted {
+ class ClauseListNode : public ParserArenaDeletable {
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;
- }
+ ClauseListNode(JSGlobalData*, CaseClauseNode*);
+ ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*);
- 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(); }
+ CaseClauseNode* getClause() const { return m_clause; }
+ ClauseListNode* getNext() const { return m_next; }
private:
- RefPtr<CaseClauseNode> m_clause;
- RefPtr<ClauseListNode> m_next;
+ CaseClauseNode* m_clause;
+ ClauseListNode* m_next;
};
- class CaseBlockNode : public ParserRefCounted {
+ class CaseBlockNode : public ParserArenaDeletable {
public:
- CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL
- : ParserRefCounted(globalData)
- , m_list1(list1)
- , m_defaultClause(defaultClause)
- , m_list2(list2)
- {
- }
+ CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
- virtual ~CaseBlockNode();
- virtual void releaseNodes(NodeReleaser&);
-
- RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL;
+ RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0);
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;
+ ClauseListNode* m_list1;
+ CaseClauseNode* m_defaultClause;
+ 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;
+ SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*);
private:
- RefPtr<ExpressionNode> m_expr;
- RefPtr<CaseBlockNode> m_block;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ CaseBlockNode* m_block;
};
struct ElementList {
} // namespace JSC
-#endif // NODES_H_
+#endif // Nodes_h
void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
{
- ASSERT(!m_sourceElements);
+ m_sourceElements = 0;
int defaultErrLine;
UString defaultErrMsg;
int parseError = jscyyparse(globalData);
bool lexError = lexer.sawError();
+ int lineNumber = lexer.lineNumber();
lexer.clear();
- ParserRefCounted::deleteNewObjects(globalData);
-
if (parseError || lexError) {
- *errLine = lexer.lineNo();
+ *errLine = lineNumber;
*errMsg = "Parse error";
- m_sourceElements.clear();
+ m_sourceElements = 0;
}
}
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)));
+ functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(globalData->parser->arena(),
+ m_sourceElements,
+ 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();
+ ASSERT(globalData->parser->arena().isEmpty());
+
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)
+void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack,
+ ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
{
m_sourceElements = sourceElements;
m_varDeclarations = varStack;
#ifndef Parser_h
#define Parser_h
-#include "SourceProvider.h"
#include "Debugger.h"
#include "Nodes.h"
+#include "SourceProvider.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
class ProgramNode;
class UString;
- template <typename T>
- struct ParserRefCountedData : ParserRefCounted {
- ParserRefCountedData(JSGlobalData* globalData)
- : ParserRefCounted(globalData)
- {
- }
-
- T data;
- };
+ template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
class Parser : Noncopyable {
public:
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);
+ void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
+ ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
+
+ ParserArena& arena() { return m_arena; }
private:
void parse(JSGlobalData*, int* errLine, UString* errMsg);
+ ParserArena m_arena;
const SourceCode* m_source;
- RefPtr<SourceElements> m_sourceElements;
- RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
- RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
+ SourceElements* m_sourceElements;
+ ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
CodeFeatures m_features;
int m_lastLine;
int m_numConstants;
RefPtr<ParsedNode> result;
if (m_sourceElements) {
result = ParsedNode::create(&exec->globalData(),
- m_sourceElements.get(),
+ m_sourceElements,
m_varDeclarations ? &m_varDeclarations->data : 0,
m_funcDeclarations ? &m_funcDeclarations->data : 0,
*m_source,
result->setLoc(m_source->firstLine(), m_lastLine);
}
+ m_arena.reset();
+
m_source = 0;
- m_sourceElements = 0;
m_varDeclarations = 0;
m_funcDeclarations = 0;
RefPtr<ParsedNode> result;
if (m_sourceElements) {
result = ParsedNode::create(globalData,
- m_sourceElements.get(),
+ m_sourceElements,
m_varDeclarations ? &m_varDeclarations->data : 0,
m_funcDeclarations ? &m_funcDeclarations->data : 0,
*m_source,
result->setLoc(m_source->firstLine(), m_lastLine);
}
+ m_arena.reset();
+
m_source = 0;
- m_sourceElements = 0;
m_varDeclarations = 0;
m_funcDeclarations = 0;
--- /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 "ParserArena.h"
+
+#include "Nodes.h"
+
+namespace JSC {
+
+ParserArena::~ParserArena()
+{
+ deleteAllValues(m_deletableObjects);
+}
+
+bool ParserArena::contains(ParserArenaRefCounted* object) const
+{
+ return m_refCountedObjects.find(object) != notFound;
+}
+
+ParserArenaRefCounted* ParserArena::last() const
+{
+ return m_refCountedObjects.last().get();
+}
+
+void ParserArena::removeLast()
+{
+ m_refCountedObjects.removeLast();
+}
+
+void ParserArena::reset()
+{
+ deleteAllValues(m_deletableObjects);
+ m_deletableObjects.shrink(0);
+ m_refCountedObjects.shrink(0);
+}
+
+}
--- /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 ParserArena_h
+#define ParserArena_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class ParserArenaDeletable;
+ class ParserArenaRefCounted;
+
+ class ParserArena {
+ public:
+ void swap(ParserArena& otherArena)
+ {
+ m_deletableObjects.swap(otherArena.m_deletableObjects);
+ m_refCountedObjects.swap(otherArena.m_refCountedObjects);
+ }
+ ~ParserArena();
+
+ void deleteWithArena(ParserArenaDeletable* object) { m_deletableObjects.append(object); }
+ void derefWithArena(PassRefPtr<ParserArenaRefCounted> object) { m_refCountedObjects.append(object); }
+
+ bool contains(ParserArenaRefCounted*) const;
+ ParserArenaRefCounted* last() const;
+ void removeLast();
+
+ bool isEmpty() const { return m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); }
+ void reset();
+
+ private:
+ Vector<ParserArenaDeletable*> m_deletableObjects;
+ Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects;
+ };
+
+}
+
+#endif
return (m_type & TypeBits) == TypeMaybeNumber;
}
+ bool definitelyIsString()
+ {
+ return (m_type & TypeBits) == TypeMaybeString;
+ }
+
bool mightBeNumber()
{
return m_type & TypeMaybeNumber;
{
if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
return numberTypeCanReuse();
- if (op1.isNotNumber() || op2.isNotNumber())
+ if (op1.definitelyIsString() || op2.definitelyIsString())
return stringType();
return stringOrNumberTypeCanReuse();
}
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
namespace JSC {
+ enum SourceBOMPresence { SourceHasNoBOMs, SourceCouldHaveBOMs };
+
class SourceProvider : public RefCounted<SourceProvider> {
public:
- SourceProvider(const UString& url)
+ SourceProvider(const UString& url, SourceBOMPresence hasBOMs = SourceCouldHaveBOMs)
: m_url(url)
+ , m_hasBOMs(hasBOMs)
{
}
virtual ~SourceProvider() { }
const UString& url() { return m_url; }
intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
+ SourceBOMPresence hasBOMs() const { return m_hasBOMs; }
+
private:
UString m_url;
+ SourceBOMPresence m_hasBOMs;
};
class UStringSourceProvider : public SourceProvider {
my ($fh, $tempFile) = tempfile(
basename($0) . "-XXXXXXXX",
- DIR => ($ENV{'TMPDIR'} || "/tmp"),
+ DIR => File::Spec->tmpdir,
SUFFIX => ".in",
UNLINK => 0,
);
int d = -1;
if (safelyCheckNextChar(ptr, patternEnd, '-')) {
- UChar const *hyptr = ptr++;
+ const UChar* hyptr = ptr++;
if (safelyCheckNextChar(ptr, patternEnd, '\\')) {
ptr++;
d = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, true);
#include <wtf/Vector.h>
#if REGEXP_HISTOGRAM
-#include <parser/DateMath.h>
+#include <wtf/DateMath.h>
#include <runtime/UString.h>
#endif
using namespace WTF;
-#ifdef __GNUC__
+#if COMPILER(GCC)
#define USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
//#define USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
#endif
/* The below limit restricts the number of "recursive" match calls in order to
avoid spending exponential time on complex regular expressions. */
-static const unsigned matchLimit = 100000;
+static const unsigned matchLimit = 1000000;
#ifdef DEBUG
/*************************************************
int min;
bool minimize = false; /* Initialization not really needed, but some compilers think so. */
unsigned remainingMatchCount = matchLimit;
+ int othercase; /* Declare here to avoid errors during jumps */
MatchStack stack;
stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
if (stack.currentFrame->locals.fc <= 0xFFFF) {
- int othercase = md.ignoreCase ? jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
+ 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)
#define CallIdentifier_h
#include <runtime/UString.h>
+#include "FastAllocBase.h"
namespace JSC {
- struct CallIdentifier {
+ struct CallIdentifier : public FastAllocBase {
UString m_name;
UString m_url;
unsigned m_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); }
+ struct Hash {
+ 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;
+ };
+
+ unsigned hash() const { return Hash::hash(*this); }
+
#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 DefaultHash<JSC::CallIdentifier> { typedef JSC::CallIdentifier::Hash Hash; };
template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
static void constructDeletedValue(JSC::CallIdentifier& slot)
-/*
- * 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
-/*
- * 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
#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);
+ return adoptRef(new Profile(title, uid));
}
Profile::Profile(const UString& title, unsigned uid)
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;
int lineNumber;
intptr_t sourceID;
UString sourceURL;
- JSValuePtr function;
+ JSValue 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());
#ifndef ProfileGenerator_h
#define ProfileGenerator_h
+#include "Profile.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include "config.h"
#include "ProfileNode.h"
-#include "DateMath.h"
#include "Profiler.h"
#include <stdio.h>
+#include <wtf/DateMath.h>
#if PLATFORM(WIN_OS)
#include <windows.h>
QueryPerformanceCounter(&counter);
return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
#else
- return getCurrentUTCTimeWithMicroseconds();
+ return WTF::getCurrentUTCTimeWithMicroseconds();
#endif
}
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* 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&);
#include "CallFrame.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
+#include "Nodes.h"
#include "Profile.h"
#include "ProfileGenerator.h"
#include "ProfileNode.h"
void Profiler::startProfiling(ExecState* exec, const UString& title)
{
+ ASSERT_ARG(title, !title.isNull());
+
// 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;
}
}
-void Profiler::willExecute(ExecState* exec, JSValuePtr function)
+void Profiler::willExecute(ExecState* exec, JSValue function)
{
ASSERT(!m_currentProfiles.isEmpty());
{
ASSERT(!m_currentProfiles.isEmpty());
- CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), noValue(), sourceURL, startingLineNumber);
+ CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber);
dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
}
-void Profiler::didExecute(ExecState* exec, JSValuePtr function)
+void Profiler::didExecute(ExecState* exec, JSValue function)
{
ASSERT(!m_currentProfiles.isEmpty());
{
ASSERT(!m_currentProfiles.isEmpty());
- dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), noValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+ dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
}
-CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValuePtr function, const UString& defaultSourceURL, int defaultLineNumber)
+CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue 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(&JSFunction::info)) {
+ JSFunction* func = asFunction(function);
+ if (!func->isHostFunction())
+ return createCallIdentifierFromFunctionImp(globalData, func);
+ }
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);
+ const UString& name = function->calculatedDisplayName(globalData);
return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->body()->sourceURL(), function->body()->lineNo());
}
class ExecState;
class JSGlobalData;
class JSObject;
- class JSValuePtr;
+ class JSValue;
class ProfileGenerator;
class UString;
}
static Profiler* profiler();
- static CallIdentifier createCallIdentifier(JSGlobalData*, JSValuePtr, const UString& sourceURL, int lineNumber);
+ static CallIdentifier createCallIdentifier(JSGlobalData*, JSValue, 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*, JSValue function);
void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
- void didExecute(ExecState*, JSValuePtr function);
+ void didExecute(ExecState*, JSValue function);
void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
#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;
-/*
- * 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
-/*
- * 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
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();
+ if (startIndex <= 0 || static_cast<unsigned>(startIndex) >= m_argCount) {
+ result = ArgList(m_args, 0);
+ return;
+ }
+ result = ArgList(m_args + startIndex, m_argCount - startIndex);
}
-void ArgList::markLists(ListSet& markSet)
+void MarkedArgumentBuffer::markLists(ListSet& markSet)
{
ListSet::iterator end = markSet.end();
for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
- ArgList* list = *it;
+ MarkedArgumentBuffer* list = *it;
iterator end2 = list->end();
for (iterator it2 = list->begin(); it2 != end2; ++it2)
}
}
-void ArgList::slowAppend(JSValuePtr v)
+void MarkedArgumentBuffer::slowAppend(JSValue v)
{
// As long as our size stays within our Vector's inline
// capacity, all our values are allocated on the stack, and
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Computer, Inc.
+ * Copyright (C) 2003, 2007, 2008, 2009 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
#ifndef ArgList_h
#define ArgList_h
-#include "JSImmediate.h"
#include "Register.h"
#include <wtf/HashSet.h>
namespace JSC {
- class ArgList : Noncopyable {
+ class MarkedArgumentBuffer : Noncopyable {
private:
static const unsigned inlineCapacity = 8;
typedef Vector<Register, inlineCapacity> VectorType;
- typedef HashSet<ArgList*> ListSet;
+ typedef HashSet<MarkedArgumentBuffer*> ListSet;
public:
typedef VectorType::iterator 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)
+ MarkedArgumentBuffer()
+ : m_isUsingInlineBuffer(true)
+ , m_markSet(0)
#ifndef NDEBUG
, m_isReadOnly(false)
#endif
}
// Constructor for a read-only list whose data has already been allocated elsewhere.
- ArgList(Register* buffer, size_t size)
+ MarkedArgumentBuffer(Register* buffer, size_t size)
: m_buffer(buffer)
, m_size(size)
+ , m_isUsingInlineBuffer(true)
, m_markSet(0)
#ifndef NDEBUG
, m_isReadOnly(true)
#endif
}
- ~ArgList()
+ ~MarkedArgumentBuffer()
{
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
+ JSValue at(size_t i) const
{
if (i < m_size)
- return m_buffer[i].jsValue(exec);
+ return m_buffer[i].jsValue();
return jsUndefined();
}
m_size = 0;
}
- void append(JSValuePtr v)
+ void append(JSValue v)
{
ASSERT(!m_isReadOnly);
- if (m_size < inlineCapacity) {
+ if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
m_vector.uncheckedAppend(v);
++m_size;
} else {
// the performance of the fast "just append to inline buffer" case.
slowAppend(v);
++m_size;
+ m_isUsingInlineBuffer = false;
}
}
- void getSlice(int startIndex, ArgList& result) const;
+ void removeLast()
+ {
+ ASSERT(m_size);
+ m_size--;
+ m_vector.removeLast();
+ }
+ JSValue last()
+ {
+ ASSERT(m_size);
+ return m_buffer[m_size - 1].jsValue();
+ }
+
iterator begin() { return m_buffer; }
iterator end() { return m_buffer + m_size; }
static void markLists(ListSet&);
private:
- void slowAppend(JSValuePtr);
+ void slowAppend(JSValue);
Register* m_buffer;
size_t m_size;
+ bool m_isUsingInlineBuffer;
VectorType m_vector;
ListSet* m_markSet;
void operator delete(void*, size_t);
};
+ class ArgList {
+ friend class JIT;
+ public:
+ typedef JSValue* iterator;
+ typedef const JSValue* const_iterator;
+
+ ArgList()
+ : m_args(0)
+ , m_argCount(0)
+ {
+ }
+
+ ArgList(JSValue* args, unsigned argCount)
+ : m_args(args)
+ , m_argCount(argCount)
+ {
+ }
+
+ ArgList(Register* args, int argCount)
+ : m_args(reinterpret_cast<JSValue*>(args))
+ , m_argCount(argCount)
+ {
+ ASSERT(argCount >= 0);
+ }
+
+ ArgList(const MarkedArgumentBuffer& args)
+ : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
+ , m_argCount(args.size())
+ {
+ }
+
+ JSValue at(size_t idx) const
+ {
+ if (idx < m_argCount)
+ return m_args[idx];
+ return jsUndefined();
+ }
+
+ bool isEmpty() const { return !m_argCount; }
+
+ size_t size() const { return m_argCount; }
+
+ iterator begin() { return m_args; }
+ iterator end() { return m_args + m_argCount; }
+
+ const_iterator begin() const { return m_args; }
+ const_iterator end() const { return m_args + m_argCount; }
+
+ void getSlice(int startIndex, ArgList& result) const;
+ private:
+ JSValue* m_args;
+ size_t m_argCount;
+ };
+
} // namespace JSC
#endif // ArgList_h
d->activation->mark();
}
-void Arguments::fillArgList(ExecState* exec, ArgList& args)
+void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
{
+ if (UNLIKELY(d->overrodeLength)) {
+ unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
+ for (unsigned i = 0; i < length; i++)
+ buffer[i] = get(exec, i);
+ return;
+ }
+
+ if (LIKELY(!d->deletedArguments)) {
+ unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i)
+ buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+ for (; i < d->numArguments; ++i)
+ buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+ return;
+ }
+
+ unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i) {
+ if (!d->deletedArguments[i])
+ buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+ else
+ buffer[i] = get(exec, i);
+ }
+ for (; i < d->numArguments; ++i) {
+ if (!d->deletedArguments[i])
+ buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+ else
+ buffer[i] = get(exec, i);
+ }
+}
+
+void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
+{
+ if (UNLIKELY(d->overrodeLength)) {
+ unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec);
+ for (unsigned i = 0; i < length; i++)
+ args.append(get(exec, i));
+ return;
+ }
+
if (LIKELY(!d->deletedArguments)) {
if (LIKELY(!d->numParameters)) {
args.initialize(d->extraArguments, d->numArguments);
unsigned parametersLength = min(d->numParameters, d->numArguments);
unsigned i = 0;
for (; i < parametersLength; ++i)
- args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ args.append(d->registers[d->firstParameterIndex + i].jsValue());
for (; i < d->numArguments; ++i)
- args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ args.append(d->extraArguments[i - d->numParameters].jsValue());
return;
}
unsigned i = 0;
for (; i < parametersLength; ++i) {
if (!d->deletedArguments[i])
- args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ args.append(d->registers[d->firstParameterIndex + i].jsValue());
else
args.append(get(exec, i));
}
for (; i < d->numArguments; ++i) {
if (!d->deletedArguments[i])
- args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ args.append(d->extraArguments[i - d->numParameters].jsValue());
else
args.append(get(exec, i));
}
if (i < d->numParameters) {
slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
} else
- slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
return true;
}
if (i < d->numParameters) {
slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
} else
- slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
return true;
}
return JSObject::getOwnPropertySlot(exec, propertyName, slot);
}
-void Arguments::put(ExecState* exec, unsigned i, JSValuePtr value, PutPropertySlot& slot)
+void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
{
if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
if (i < d->numParameters)
- d->registers[d->firstParameterIndex + i] = JSValuePtr(value);
+ d->registers[d->firstParameterIndex + i] = JSValue(value);
else
- d->extraArguments[i - d->numParameters] = JSValuePtr(value);
+ d->extraArguments[i - d->numParameters] = JSValue(value);
return;
}
JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
}
-void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue 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);
+ d->registers[d->firstParameterIndex + i] = JSValue(value);
else
- d->extraArguments[i - d->numParameters] = JSValuePtr(value);
+ d->extraArguments[i - d->numParameters] = JSValue(value);
return;
}
virtual void mark();
- void fillArgList(ExecState*, ArgList&);
+ void fillArgList(ExecState*, MarkedArgumentBuffer&);
+ uint32_t numProvidedArguments(ExecState* exec) const
+ {
+ if (UNLIKELY(d->overrodeLength))
+ return get(exec, exec->propertyNames().length).toUInt32(exec);
+ return d->numArguments;
+ }
+
+ void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
void copyRegisters();
bool isTornOff() const { return d->registerArray; }
void setActivation(JSActivation* activation)
d->registers = &activation->registerAt(0);
}
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
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 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
OwnPtr<ArgumentsData> d;
};
- Arguments* asArguments(JSValuePtr);
+ Arguments* asArguments(JSValue);
- inline Arguments* asArguments(JSValuePtr value)
+ inline Arguments* asArguments(JSValue value)
{
ASSERT(asObject(value)->inherits(&Arguments::info));
return static_cast<Arguments*>(asObject(value));
{
function = callFrame->callee();
- CodeBlock* codeBlock = &function->body()->generatedBytecode();
- int numParameters = codeBlock->m_numParameters;
+ int numParameters = function->body()->parameterCount();
argc = callFrame->argumentCount();
if (argc <= numParameters)
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
else
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
argc -= 1; // - 1 to skip "this"
- firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
}
inline Arguments::Arguments(CallFrame* callFrame)
static_cast<Arguments*>(arguments)->setActivation(this);
}
+ ALWAYS_INLINE Arguments* Register::arguments() const
+ {
+ if (jsValue() == JSValue())
+ return 0;
+ return asArguments(jsValue());
+ }
+
+
} // namespace JSC
#endif // Arguments_h
#include "ArrayPrototype.h"
#include "JSArray.h"
+#include "JSFunction.h"
#include "Lookup.h"
namespace JSC {
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))
+ if (args.size() == 1 && args.at(0).isNumber()) {
+ uint32_t n = args.at(0).toUInt32(exec);
+ if (n != args.at(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);
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), args);
}
static JSObject* constructWithArrayConstructor(ExecState* exec, JSObject*, const ArgList& args)
return ConstructTypeHost;
}
-static JSValuePtr callArrayConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
return constructArrayWithSizeQuirk(exec, args);
}
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2003 Peter Kelly (pmk@post.com)
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
#include "ArrayPrototype.h"
#include "CodeBlock.h"
+#include "CachedCall.h"
#include "Interpreter.h"
+#include "JIT.h"
#include "ObjectPrototype.h"
#include "Lookup.h"
#include "Operations.h"
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&);
+static JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
}
{
if (callType != CallTypeJS)
return false;
-
- return callData.js.functionBody->bytecode(callData.js.scopeChain).isNumericCompareFunction();
+
+#if ENABLE(JIT)
+ // If the JIT is enabled then we need to preserve the invariant that every
+ // function with a CodeBlock also has JIT code.
+ callData.js.functionBody->jitCode(callData.js.scopeChain);
+ CodeBlock& codeBlock = callData.js.functionBody->generatedBytecode();
+#else
+ CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain);
+#endif
+
+ return codeBlock.isNumericCompareFunction();
}
// ------------------------------ ArrayPrototype ----------------------------
indexOf arrayProtoFuncIndexOf DontEnum|Function 1
lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
filter arrayProtoFuncFilter DontEnum|Function 1
+ reduce arrayProtoFuncReduce DontEnum|Function 1
+ reduceRight arrayProtoFuncReduceRight DontEnum|Function 1
map arrayProtoFuncMap DontEnum|Function 1
@end
*/
// ------------------------------ Array Functions ----------------------------
// Helper function
-static JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index)
+static JSValue getProperty(ExecState* exec, JSObject* obj, unsigned index)
{
PropertySlot slot(obj);
if (!obj->getPropertySlot(exec, index, slot))
- return noValue();
+ return JSValue();
return slot.getValue(exec, index);
}
-static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value)
+static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue value)
{
PutPropertySlot slot;
obj->put(exec, propertyName, value, slot);
}
-JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue 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.");
+ if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+ }
bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
if (alreadyVisited)
break;
}
- JSValuePtr element = thisObj->get(exec, k);
+ JSValue element = thisObj->get(exec, k);
if (element.isUndefinedOrNull())
continue;
return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
}
-JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue 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.");
+ if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+ }
bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
if (alreadyVisited)
break;
}
- JSValuePtr element = thisObj->get(exec, k);
+ JSValue element = thisObj->get(exec, k);
if (element.isUndefinedOrNull())
continue;
JSObject* o = element.toObject(exec);
- JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+ JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
UString str;
CallData callData;
CallType callType = conversionFunction.getCallData(callData);
return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
}
-JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue 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.");
+ if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+ }
bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
if (alreadyVisited)
Vector<UChar, 256> strBuffer;
UChar comma = ',';
- UString separator = args.at(exec, 0).isUndefined() ? UString(&comma, 1) : args.at(exec, 0).toString(exec);
+ UString separator = args.at(0).isUndefined() ? UString(&comma, 1) : args.at(0).toString(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned k = 0; k < length; k++) {
break;
}
- JSValuePtr element = thisObj->get(exec, k);
+ JSValue element = thisObj->get(exec, k);
if (element.isUndefinedOrNull())
continue;
return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
}
-JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSArray* arr = constructEmptyArray(exec);
int n = 0;
- JSValuePtr curArg = thisValue.toThisObject(exec);
+ JSValue 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();
+ unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
+ JSObject* curObject = curArg.toObject(exec);
for (unsigned k = 0; k < length; ++k) {
- if (JSValuePtr v = getProperty(exec, curArray, k))
+ if (JSValue v = getProperty(exec, curObject, k))
arr->put(exec, n, v);
n++;
}
}
if (it == end)
break;
- curArg = (*it).jsValue(exec);
+ curArg = (*it);
++it;
}
arr->setLength(n);
return arr;
}
-JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (exec->interpreter()->isJSArray(thisValue))
+ if (isJSArray(&exec->globalData(), thisValue))
return asArray(thisValue)->pop();
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr result;
+ JSValue result;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (length == 0) {
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
return result;
}
-JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (exec->interpreter()->isJSArray(thisValue) && args.size() == 1) {
+ if (isJSArray(&exec->globalData(), thisValue) && args.size() == 1) {
JSArray* array = asArray(thisValue);
- array->push(exec, args.begin()->jsValue(exec));
+ array->push(exec, *args.begin());
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));
+ thisObj->put(exec, length + n, args.at(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&)
+JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
JSObject* thisObj = thisValue.toThisObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned k = 0; k < middle; k++) {
unsigned lk1 = length - k - 1;
- JSValuePtr obj2 = getProperty(exec, thisObj, lk1);
- JSValuePtr obj = getProperty(exec, thisObj, k);
+ JSValue obj2 = getProperty(exec, thisObj, lk1);
+ JSValue obj = getProperty(exec, thisObj, k);
if (obj2)
thisObj->put(exec, k, obj2);
return thisObj;
}
-JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr result;
+ JSValue result;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (length == 0) {
} else {
result = thisObj->get(exec, 0);
for (unsigned k = 1; k < length; k++) {
- if (JSValuePtr obj = getProperty(exec, thisObj, k))
+ if (JSValue obj = getProperty(exec, thisObj, k))
thisObj->put(exec, k - 1, obj);
else
thisObj->deleteProperty(exec, k - 1);
return result;
}
-JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
// http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
// We return a new array
JSArray* resObj = constructEmptyArray(exec);
- JSValuePtr result = resObj;
- double begin = args.at(exec, 0).toInteger(exec);
+ JSValue result = resObj;
+ double begin = args.at(0).toInteger(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (begin >= 0) {
if (begin > length)
begin = 0;
}
double end;
- if (args.at(exec, 1).isUndefined())
+ if (args.at(1).isUndefined())
end = length;
else {
- end = args.at(exec, 1).toInteger(exec);
+ end = args.at(1).toInteger(exec);
if (end < 0) {
end += length;
if (end < 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))
+ if (JSValue 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)
+JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(0);
CallData callData;
CallType callType = function.getCallData(callData);
// "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);
+ JSValue iObj = thisObj->get(exec, i);
unsigned themin = i;
- JSValuePtr minObj = iObj;
+ JSValue minObj = iObj;
for (unsigned j = i + 1; j < length; ++j) {
- JSValuePtr jObj = thisObj->get(exec, 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 (callType != CallTypeNone) {
- ArgList l;
+ MarkedArgumentBuffer l;
l.append(jObj);
l.append(minObj);
compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec);
return thisObj;
}
-JSValuePtr arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
// 15.4.4.12
JSArray* resObj = constructEmptyArray(exec);
- JSValuePtr result = resObj;
+ JSValue 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);
+ int begin = args.at(0).toUInt32(exec);
if (begin < 0)
begin = std::max<int>(begin + length, 0);
else
unsigned deleteCount;
if (args.size() > 1)
- deleteCount = std::min<int>(std::max<int>(args.at(exec, 1).toUInt32(exec), 0), length - begin);
+ deleteCount = std::min<int>(std::max<int>(args.at(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))
+ if (JSValue v = getProperty(exec, thisObj, k + begin))
resObj->put(exec, k, v);
}
resObj->setLength(deleteCount);
if (additionalArgs != deleteCount) {
if (additionalArgs < deleteCount) {
for (unsigned k = begin; k < length - deleteCount; ++k) {
- if (JSValuePtr v = getProperty(exec, thisObj, k + deleteCount))
+ if (JSValue v = getProperty(exec, thisObj, k + deleteCount))
thisObj->put(exec, k + additionalArgs, v);
else
thisObj->deleteProperty(exec, k + additionalArgs);
thisObj->deleteProperty(exec, k - 1);
} else {
for (unsigned k = length - deleteCount; (int)k > begin; --k) {
- if (JSValuePtr obj = getProperty(exec, thisObj, k + deleteCount - 1))
+ 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.at(exec, k + 2));
+ thisObj->put(exec, k + begin, args.at(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)
+JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
unsigned nrArgs = args.size();
if (nrArgs) {
for (unsigned k = length; k > 0; --k) {
- if (JSValuePtr v = getProperty(exec, thisObj, k - 1))
+ 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.at(exec, k));
- JSValuePtr result = jsNumber(exec, length + nrArgs);
+ thisObj->put(exec, k, args.at(k));
+ JSValue result = jsNumber(exec, length + nrArgs);
putProperty(exec, thisObj, exec->propertyNames().length, result);
return result;
}
-JSValuePtr arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(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);
+ JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(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) {
+ unsigned k = 0;
+ if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ JSFunction* f = asFunction(function);
+ JSArray* array = asArray(thisObj);
+ CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ for (; k < length && !exec->hadException(); ++k) {
+ if (!array->canGetIndex(k))
+ break;
+ JSValue v = array->getIndex(k);
+ cachedCall.setThis(applyThis);
+ cachedCall.setArgument(0, v);
+ cachedCall.setArgument(1, jsNumber(exec, k));
+ cachedCall.setArgument(2, thisObj);
+
+ JSValue result = cachedCall.call();
+ if (result.toBoolean(exec))
+ resultArray->put(exec, filterIndex++, v);
+ }
+ if (k == length)
+ return resultArray;
+ }
+ for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
- JSValuePtr v = slot.getValue(exec, k);
+ JSValue v = slot.getValue(exec, k);
- ArgList eachArguments;
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(v);
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
- JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
+ JSValue 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)
+JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(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);
+ JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(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) {
+ unsigned k = 0;
+ if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ JSFunction* f = asFunction(function);
+ JSArray* array = asArray(thisObj);
+ CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ for (; k < length && !exec->hadException(); ++k) {
+ if (UNLIKELY(!array->canGetIndex(k)))
+ break;
+
+ cachedCall.setThis(applyThis);
+ cachedCall.setArgument(0, array->getIndex(k));
+ cachedCall.setArgument(1, jsNumber(exec, k));
+ cachedCall.setArgument(2, thisObj);
+
+ resultArray->JSArray::put(exec, k, cachedCall.call());
+ }
+ }
+ for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
- JSValuePtr v = slot.getValue(exec, k);
+ JSValue v = slot.getValue(exec, k);
- ArgList eachArguments;
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(v);
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
- JSValuePtr result = call(exec, function, callType, callData, applyThis, eachArguments);
+ JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
resultArray->put(exec, k, result);
}
// 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)
+JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(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);
+ JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
- JSValuePtr result = jsBoolean(true);
+ JSValue result = jsBoolean(true);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ unsigned k = 0;
+ if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ JSFunction* f = asFunction(function);
+ JSArray* array = asArray(thisObj);
+ CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ for (; k < length && !exec->hadException(); ++k) {
+ if (UNLIKELY(!array->canGetIndex(k)))
+ break;
+
+ cachedCall.setThis(applyThis);
+ cachedCall.setArgument(0, array->getIndex(k));
+ cachedCall.setArgument(1, jsNumber(exec, k));
+ cachedCall.setArgument(2, thisObj);
+
+ if (!cachedCall.call().toBoolean(exec))
+ return jsBoolean(false);
+ }
+ }
+ for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
- ArgList eachArguments;
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(slot.getValue(exec, k));
eachArguments.append(jsNumber(exec, k));
return result;
}
-JSValuePtr arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(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);
+ JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ unsigned k = 0;
+ if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ JSFunction* f = asFunction(function);
+ JSArray* array = asArray(thisObj);
+ CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ for (; k < length && !exec->hadException(); ++k) {
+ if (UNLIKELY(!array->canGetIndex(k)))
+ break;
+
+ cachedCall.setThis(applyThis);
+ cachedCall.setArgument(0, array->getIndex(k));
+ cachedCall.setArgument(1, jsNumber(exec, k));
+ cachedCall.setArgument(2, thisObj);
+
+ cachedCall.call();
+ }
+ }
+ for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
- ArgList eachArguments;
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(slot.getValue(exec, k));
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
return jsUndefined();
}
-JSValuePtr arrayProtoFuncSome(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- JSValuePtr function = args.at(exec, 0);
+ JSValue function = args.at(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);
+ JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
- JSValuePtr result = jsBoolean(false);
+ JSValue result = jsBoolean(false);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
- for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ unsigned k = 0;
+ if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ JSFunction* f = asFunction(function);
+ JSArray* array = asArray(thisObj);
+ CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ for (; k < length && !exec->hadException(); ++k) {
+ if (UNLIKELY(!array->canGetIndex(k)))
+ break;
+
+ cachedCall.setThis(applyThis);
+ cachedCall.setArgument(0, array->getIndex(k));
+ cachedCall.setArgument(1, jsNumber(exec, k));
+ cachedCall.setArgument(2, thisObj);
+
+ if (cachedCall.call().toBoolean(exec))
+ return jsBoolean(true);
+ }
+ }
+ for (; k < length && !exec->hadException(); ++k) {
PropertySlot slot(thisObj);
if (!thisObj->getPropertySlot(exec, k, slot))
continue;
- ArgList eachArguments;
+ MarkedArgumentBuffer eachArguments;
eachArguments.append(slot.getValue(exec, k));
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
return result;
}
-JSValuePtr arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValue function = args.at(0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ unsigned i = 0;
+ JSValue rv;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (!length && args.size() == 1)
+ return throwError(exec, TypeError);
+ JSArray* array = 0;
+ if (isJSArray(&exec->globalData(), thisObj))
+ array = asArray(thisObj);
+
+ if (args.size() >= 2)
+ rv = args.at(1);
+ else if (array && array->canGetIndex(0)){
+ rv = array->getIndex(0);
+ i = 1;
+ } else {
+ for (i = 0; i < length; i++) {
+ rv = getProperty(exec, thisObj, i);
+ if (rv)
+ break;
+ }
+ if (!rv)
+ return throwError(exec, TypeError);
+ i++;
+ }
+
+ if (callType == CallTypeJS && array) {
+ CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+ for (; i < length && !exec->hadException(); ++i) {
+ cachedCall.setThis(jsNull());
+ cachedCall.setArgument(0, rv);
+ JSValue v;
+ if (LIKELY(array->canGetIndex(i)))
+ v = array->getIndex(i);
+ else
+ break; // length has been made unsafe while we enumerate fallback to slow path
+ cachedCall.setArgument(1, v);
+ cachedCall.setArgument(2, jsNumber(exec, i));
+ cachedCall.setArgument(3, array);
+ rv = cachedCall.call();
+ }
+ if (i == length) // only return if we reached the end of the array
+ return rv;
+ }
+
+ for (; i < length && !exec->hadException(); ++i) {
+ JSValue prop = getProperty(exec, thisObj, i);
+ if (!prop)
+ continue;
+
+ MarkedArgumentBuffer eachArguments;
+ eachArguments.append(rv);
+ eachArguments.append(prop);
+ eachArguments.append(jsNumber(exec, i));
+ eachArguments.append(thisObj);
+
+ rv = call(exec, function, callType, callData, jsNull(), eachArguments);
+ }
+ return rv;
+}
+
+JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue.toThisObject(exec);
+
+ JSValue function = args.at(0);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ unsigned i = 0;
+ JSValue rv;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ if (!length && args.size() == 1)
+ return throwError(exec, TypeError);
+ JSArray* array = 0;
+ if (isJSArray(&exec->globalData(), thisObj))
+ array = asArray(thisObj);
+
+ if (args.size() >= 2)
+ rv = args.at(1);
+ else if (array && array->canGetIndex(length - 1)){
+ rv = array->getIndex(length - 1);
+ i = 1;
+ } else {
+ for (i = 0; i < length; i++) {
+ rv = getProperty(exec, thisObj, length - i - 1);
+ if (rv)
+ break;
+ }
+ if (!rv)
+ return throwError(exec, TypeError);
+ i++;
+ }
+
+ if (callType == CallTypeJS && array) {
+ CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+ for (; i < length && !exec->hadException(); ++i) {
+ unsigned idx = length - i - 1;
+ cachedCall.setThis(jsNull());
+ cachedCall.setArgument(0, rv);
+ if (UNLIKELY(!array->canGetIndex(idx)))
+ break; // length has been made unsafe while we enumerate fallback to slow path
+ cachedCall.setArgument(1, array->getIndex(idx));
+ cachedCall.setArgument(2, jsNumber(exec, idx));
+ cachedCall.setArgument(3, array);
+ rv = cachedCall.call();
+ }
+ if (i == length) // only return if we reached the end of the array
+ return rv;
+ }
+
+ for (; i < length && !exec->hadException(); ++i) {
+ unsigned idx = length - i - 1;
+ JSValue prop = getProperty(exec, thisObj, idx);
+ if (!prop)
+ continue;
+
+ MarkedArgumentBuffer eachArguments;
+ eachArguments.append(rv);
+ eachArguments.append(prop);
+ eachArguments.append(jsNumber(exec, idx));
+ eachArguments.append(thisObj);
+
+ rv = call(exec, function, callType, callData, jsNull(), eachArguments);
+ }
+ return rv;
+}
+
+JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue 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);
+ double d = args.at(1).toInteger(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
if (d < 0)
d += length;
index = static_cast<unsigned>(d);
}
- JSValuePtr searchElement = args.at(exec, 0);
+ JSValue searchElement = args.at(0);
for (; index < length; ++index) {
- JSValuePtr e = getProperty(exec, thisObj, index);
+ JSValue e = getProperty(exec, thisObj, index);
if (!e)
continue;
- if (JSValuePtr::strictEqual(searchElement, e))
+ if (JSValue::strictEqual(searchElement, e))
return jsNumber(exec, index);
}
return jsNumber(exec, -1);
}
-JSValuePtr arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue 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
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
int index = length - 1;
- double d = args.at(exec, 1).toIntegerPreserveNaN(exec);
+ double d = args.at(1).toIntegerPreserveNaN(exec);
if (d < 0) {
d += length;
if (d < length)
index = static_cast<int>(d);
- JSValuePtr searchElement = args.at(exec, 0);
+ JSValue searchElement = args.at(0);
for (; index >= 0; --index) {
- JSValuePtr e = getProperty(exec, thisObj, index);
+ JSValue e = getProperty(exec, thisObj, index);
if (!e)
continue;
- if (JSValuePtr::strictEqual(searchElement, e))
+ if (JSValue::strictEqual(searchElement, e))
return jsNumber(exec, index);
}
: m_object(object)
{
if (!m_object->structure()->isDictionary())
- m_object->setStructure(Structure::toDictionaryTransition(m_object->structure()));
+ m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
}
~BatchedTransitionOptimizer()
{
- m_object->setStructure(Structure::fromDictionaryTransition(m_object->structure()));
+ m_object->flattenDictionaryObject();
}
private:
JSObject* constructBoolean(ExecState* exec, const ArgList& args)
{
BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
- obj->setInternalValue(jsBoolean(args.at(exec, 0).toBoolean(exec)));
+ obj->setInternalValue(jsBoolean(args.at(0).toBoolean(exec)));
return obj;
}
}
// ECMA 15.6.1
-static JSValuePtr callBooleanConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsBoolean(args.at(exec, 0).toBoolean(exec));
+ return jsBoolean(args.at(0).toBoolean(exec));
}
CallType BooleanConstructor::getCallData(CallData& callData)
return CallTypeHost;
}
-JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValuePtr immediateBooleanValue)
+JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue)
{
BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
obj->setInternalValue(immediateBooleanValue);
virtual CallType getCallData(CallData&);
};
- JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValuePtr);
+ JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue);
JSObject* constructBoolean(ExecState*, const ArgList&);
} // namespace JSC
static const ClassInfo info;
};
- BooleanObject* asBooleanObject(JSValuePtr);
+ BooleanObject* asBooleanObject(JSValue);
- inline BooleanObject* asBooleanObject(JSValuePtr value)
+ inline BooleanObject* asBooleanObject(JSValue value)
{
ASSERT(asObject(value)->inherits(&BooleanObject::info));
return static_cast<BooleanObject*>(asObject(value));
#include "BooleanPrototype.h"
#include "Error.h"
+#include "JSFunction.h"
#include "JSString.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
// Functions
-static JSValuePtr booleanProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
-static JSValuePtr booleanProtoFuncValueOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
// ECMA 15.6.4
{
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
}
// ECMA 15.6.4.2 + 15.6.4.3
-JSValuePtr booleanProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (thisValue == jsBoolean(false))
return jsNontrivialString(exec, "false");
return jsNontrivialString(exec, "true");
}
-JSValuePtr booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (thisValue.isBoolean())
return thisValue;
namespace JSC {
-JSValuePtr call(ExecState* exec, JSValuePtr functionObject, CallType callType, const CallData& callData, JSValuePtr thisValue, const ArgList& args)
+JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
{
if (callType == CallTypeHost)
return callData.native.function(exec, asObject(functionObject), thisValue, args);
#ifndef CallData_h
#define CallData_h
+#include "NativeFunctionWrapper.h"
+
namespace JSC {
class ArgList;
class ExecState;
class FunctionBodyNode;
class JSObject;
- class JSValuePtr;
+ class JSValue;
class ScopeChainNode;
enum CallType {
CallTypeJS
};
- typedef JSValuePtr (*NativeFunction)(ExecState*, JSObject*, JSValuePtr thisValue, const ArgList&);
+ typedef JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&);
union CallData {
struct {
} js;
};
- JSValuePtr call(ExecState*, JSValuePtr functionObject, CallType, const CallData&, JSValuePtr thisValue, const ArgList&);
+ JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
} // namespace JSC
#include "Interpreter.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
+#include "JSONObject.h"
#include "JSString.h"
#include "JSValue.h"
#include "Nodes.h"
#include "Tracing.h"
#include <algorithm>
+#include <limits.h>
#include <setjmp.h>
#include <stdlib.h>
#include <wtf/FastMalloc.h>
#include <wtf/HashCountedSet.h>
#include <wtf/UnusedParam.h>
+#include <wtf/VMTags.h>
#if PLATFORM(DARWIN)
-#include <mach/mach_port.h>
#include <mach/mach_init.h>
+#include <mach/mach_port.h>
#include <mach/task.h>
#include <mach/thread_act.h>
#include <mach/vm_map.h>
#if PLATFORM(SOLARIS)
#include <thread.h>
-#endif
-
-#if PLATFORM(OPENBSD)
+#else
#include <pthread.h>
#endif
#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);
+ vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, 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);
return heapAllocate<NumberHeap>(s);
}
+#if PLATFORM(WINCE)
+void* g_stackBase = 0;
+
+inline bool isPageWritable(void* page)
+{
+ MEMORY_BASIC_INFORMATION memoryInformation;
+ DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
+
+ // return false on error, including ptr outside memory
+ if (result != sizeof(memoryInformation))
+ return false;
+
+ DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
+ return protect == PAGE_READWRITE
+ || protect == PAGE_WRITECOPY
+ || protect == PAGE_EXECUTE_READWRITE
+ || protect == PAGE_EXECUTE_WRITECOPY;
+}
+
+static void* getStackBase(void* previousFrame)
+{
+ // find the address of this stack frame by taking the address of a local variable
+ bool isGrowingDownward;
+ void* thisFrame = (void*)(&isGrowingDownward);
+
+ isGrowingDownward = previousFrame < &thisFrame;
+ static DWORD pageSize = 0;
+ if (!pageSize) {
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo(&systemInfo);
+ pageSize = systemInfo.dwPageSize;
+ }
+
+ // scan all of memory starting from this frame, and return the last writeable page found
+ register char* currentPage = (char*)((DWORD)thisFrame & ~(pageSize - 1));
+ if (isGrowingDownward) {
+ while (currentPage > 0) {
+ // check for underflow
+ if (currentPage >= (char*)pageSize)
+ currentPage -= pageSize;
+ else
+ currentPage = 0;
+ if (!isPageWritable(currentPage))
+ return currentPage + pageSize;
+ }
+ return 0;
+ } else {
+ while (true) {
+ // guaranteed to complete because isPageWritable returns false at end of memory
+ currentPage += pageSize;
+ if (!isPageWritable(currentPage))
+ return currentPage;
+ }
+ }
+}
+#endif
+
static inline void* currentThreadStackBase()
{
#if PLATFORM(DARWIN)
stack_t stack;
pthread_stackseg_np(thread, &stack);
return stack.ss_sp;
+#elif PLATFORM(SYMBIAN)
+ static void* stackBase = 0;
+ if (stackBase == 0) {
+ TThreadStackInfo info;
+ RThread thread;
+ thread.StackInfo(info);
+ stackBase = (void*)info.iBase;
+ }
+ return (void*)stackBase;
#elif PLATFORM(UNIX)
static void* stackBase = 0;
static size_t stackSize = 0;
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;
+#elif PLATFORM(WINCE)
+ if (g_stackBase)
+ return g_stackBase;
+ else {
+ int dummy;
+ return getStackBase(&dummy);
}
- return (void*)stackBase;
#else
#error Need a way to get the stack base on this platform
#endif
m_protectedValuesMutex.set(new Mutex);
}
-void Heap::protect(JSValuePtr k)
+void Heap::protect(JSValue k)
{
ASSERT(k);
ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
m_protectedValuesMutex->unlock();
}
-void Heap::unprotect(JSValuePtr k)
+void Heap::unprotect(JSValue k)
{
ASSERT(k);
ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
m_protectedValuesMutex->unlock();
}
-Heap* Heap::heap(JSValuePtr v)
+Heap* Heap::heap(JSValue v)
{
if (!v.isCell())
return 0;
markStackObjectsConservatively();
markProtectedObjects();
if (m_markListSet && m_markListSet->size())
- ArgList::markLists(*m_markListSet);
+ MarkedArgumentBuffer::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();
+ if (m_globalData->firstStringifierToMark)
+ JSONObject::markStringifiers(m_globalData->firstStringifierToMark);
JAVASCRIPTCORE_GC_MARKED();
{
if (cell->isString())
return "string";
+#if USE(JSVALUE32)
if (cell->isNumber())
return "number";
+#endif
if (cell->isGetterSetter())
return "gettersetter";
ASSERT(cell->isObject());
namespace JSC {
- class ArgList;
+ class MarkedArgumentBuffer;
class CollectorBlock;
class JSCell;
class JSGlobalData;
- class JSValuePtr;
+ class JSValue;
enum OperationInProgress { NoOperation, Allocation, Collection };
enum HeapType { PrimaryHeap, NumberHeap };
Statistics statistics() const;
void setGCProtectNeedsLocking();
- void protect(JSValuePtr);
- void unprotect(JSValuePtr);
+ void protect(JSValue);
+ void unprotect(JSValue);
- static Heap* heap(JSValuePtr); // 0 for immediate values
+ static Heap* heap(JSValue); // 0 for immediate values
size_t globalObjectCount();
size_t protectedObjectCount();
void markConservatively(void* start, void* end);
- HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
+ HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
JSGlobalData* globalData() const { return m_globalData; }
static bool isNumber(JSCell*);
OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
ProtectCountSet m_protectedValues;
- HashSet<ArgList*>* m_markListSet;
+ HashSet<MarkedArgumentBuffer*>* m_markListSet;
#if ENABLE(JSC_MULTIPLE_THREADS)
void makeUsableFromMultipleThreads();
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
+#if USE(JSVALUE32)
+ template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; };
+#else
+ template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 64; };
+#endif
+ template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
+
const size_t BLOCK_SIZE = 16 * 4096; // 64k
// derived constants
/*
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2007, 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
namespace JSC {
-const char* const nullCString = 0;
+static const char* const nullCString = 0;
#define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
: nullIdentifier(globalData, nullCString)
+ , emptyIdentifier(globalData, "")
, underscoreProto(globalData, "__proto__")
, thisIdentifier(globalData, "this")
JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
/*
- * Copyright (C) 2003,2007 Apple Computer, Inc
+ * Copyright (C) 2003, 2007, 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
#include "Identifier.h"
#include <wtf/Noncopyable.h>
-// ArgList of property names, passed to a macro so we can do set them up various
+// MarkedArgumentBuffer 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(test) \
macro(toExponential) \
macro(toFixed) \
+ macro(toISOString) \
+ macro(toJSON) \
macro(toLocaleString) \
macro(toPrecision) \
macro(toString) \
macro(UTC) \
- macro(valueOf)
+ macro(valueOf) \
+ macro(displayName)
namespace JSC {
public:
const Identifier nullIdentifier;
+ const Identifier emptyIdentifier;
const Identifier underscoreProto;
const Identifier thisIdentifier;
return Completion(Normal);
}
-Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValuePtr thisValue)
+Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
{
JSLock lock(exec);
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);
+ JSValue exception;
+ JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
if (exception) {
if (exception.isObject() && asObject(exception)->isWatchdogException())
*/
class Completion {
public:
- Completion(ComplType type = Normal, JSValuePtr value = noValue())
+ Completion(ComplType type = Normal, JSValue value = JSValue())
: 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; }
+ JSValue value() const { return m_value; }
+ void setValue(JSValue v) { m_value = v; }
bool isValueCompletion() const { return m_value; }
private:
ComplType m_type;
- JSValuePtr m_value;
+ JSValue m_value;
};
Completion checkSyntax(ExecState*, const SourceCode&);
- Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValuePtr thisValue = noValue());
+ Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue thisValue = JSValue());
} // namespace JSC
namespace JSC {
-JSObject* construct(ExecState* exec, JSValuePtr object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+JSObject* construct(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
{
if (constructType == ConstructTypeHost)
return constructData.native.function(exec, asObject(object), args);
class ExecState;
class FunctionBodyNode;
class JSObject;
- class JSValuePtr;
+ class JSValue;
class ScopeChainNode;
enum ConstructType {
} js;
};
- JSObject* construct(ExecState*, JSValuePtr constructor, ConstructType, const ConstructData&, const ArgList&);
+ JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&);
} // namespace JSC
#include "config.h"
#include "DateConstructor.h"
+#include "DateConversion.h"
#include "DateInstance.h"
-#include "DateMath.h"
#include "DatePrototype.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSString.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
#include <math.h>
#include <time.h>
+#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
+#if PLATFORM(WINCE) && !PLATFORM(QT)
+extern "C" time_t time(time_t* timer); //provided by libce
+#endif
+
#if HAVE(SYS_TIME_H)
#include <sys/time.h>
#endif
#include <sys/timeb.h>
#endif
+using namespace WTF;
+
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&);
+static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, 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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 7), ReadOnly | DontEnum | DontDelete);
}
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();
+ if (args.at(0).isObject(&DateInstance::info))
+ value = asDateInstance(args.at(0))->internalNumber();
else {
- JSValuePtr primitive = args.at(exec, 0).toPrimitive(exec);
+ JSValue primitive = args.at(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))))
+ if (isnan(args.at(0).toNumber(exec))
+ || isnan(args.at(1).toNumber(exec))
+ || (numArgs >= 3 && isnan(args.at(2).toNumber(exec)))
+ || (numArgs >= 4 && isnan(args.at(3).toNumber(exec)))
+ || (numArgs >= 5 && isnan(args.at(4).toNumber(exec)))
+ || (numArgs >= 6 && isnan(args.at(5).toNumber(exec)))
+ || (numArgs >= 7 && isnan(args.at(6).toNumber(exec))))
value = NaN;
else {
GregorianDateTime t;
- int year = args.at(exec, 0).toInt32(exec);
+ int year = args.at(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.month = args.at(1).toInt32(exec);
+ t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1;
+ t.hour = args.at(3).toInt32(exec);
+ t.minute = args.at(4).toInt32(exec);
+ t.second = args.at(5).toInt32(exec);
t.isDST = -1;
- double ms = (numArgs >= 7) ? args.at(exec, 6).toNumber(exec) : 0;
+ double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0;
value = gregorianDateTimeToMS(t, ms, false);
}
}
}
// ECMA 15.9.2
-static JSValuePtr callDate(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
time_t localTime = time(0);
tm localTM;
return CallTypeHost;
}
-static JSValuePtr dateParse(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, parseDate(args.at(exec, 0).toString(exec)));
+ return jsNumber(exec, parseDate(args.at(0).toString(exec)));
}
-static JSValuePtr dateNow(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
return jsNumber(exec, getCurrentUTCTime());
}
-static JSValuePtr dateUTC(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, 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))))
+ if (isnan(args.at(0).toNumber(exec))
+ || isnan(args.at(1).toNumber(exec))
+ || (n >= 3 && isnan(args.at(2).toNumber(exec)))
+ || (n >= 4 && isnan(args.at(3).toNumber(exec)))
+ || (n >= 5 && isnan(args.at(4).toNumber(exec)))
+ || (n >= 6 && isnan(args.at(5).toNumber(exec)))
+ || (n >= 7 && isnan(args.at(6).toNumber(exec))))
return jsNaN(exec);
GregorianDateTime t;
- int year = args.at(exec, 0).toInt32(exec);
+ int year = args.at(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;
+ t.month = args.at(1).toInt32(exec);
+ t.monthDay = (n >= 3) ? args.at(2).toInt32(exec) : 1;
+ t.hour = args.at(3).toInt32(exec);
+ t.minute = args.at(4).toInt32(exec);
+ t.second = args.at(5).toInt32(exec);
+ double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0;
return jsNumber(exec, gregorianDateTimeToMS(t, ms, true));
}
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 "DateConversion.h"
+
+#include "UString.h"
+#include <wtf/DateMath.h>
+#include <wtf/StringExtras.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+double parseDate(const UString &date)
+{
+ return parseDateFromNullTerminatedCharacters(date.UTF8String().c_str());
+}
+
+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 timeZoneName[70];
+ struct tm gtm = t;
+ strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m);
+
+ if (timeZoneName[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, timeZoneName);
+ } 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.
+ * Copyright (C) 2009 Google 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 DateConversion_h
+#define DateConversion_h
+
+namespace WTF {
+ struct GregorianDateTime;
+}
+
+namespace JSC {
+
+class UString;
+
+double parseDate(const UString&);
+UString formatDate(const WTF::GregorianDateTime&);
+UString formatDateUTCVariant(const WTF::GregorianDateTime&);
+UString formatTime(const WTF::GregorianDateTime&, bool inputIsUTC);
+
+} // namespace JSC
+
+#endif // DateConversion_h
#include "config.h"
#include "DateInstance.h"
-#include "DateMath.h"
#include <math.h>
+#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
+using namespace WTF;
+
namespace JSC {
struct DateInstance::Cache {
if (outputIsUTC) {
if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
- JSC::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
+ WTF::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);
+ WTF::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
m_cache->m_gregorianDateTimeCachedForMS = milli;
}
t.copyFrom(m_cache->m_cachedGregorianDateTime);
#include "JSWrapperObject.h"
-namespace JSC {
-
+namespace WTF {
struct GregorianDateTime;
+}
+
+namespace JSC {
class DateInstance : public JSWrapperObject {
public:
double internalNumber() const { return internalValue().uncheckedGetNumber(); }
- bool getTime(GregorianDateTime&, int& offset) const;
- bool getUTCTime(GregorianDateTime&) const;
+ bool getTime(WTF::GregorianDateTime&, int& offset) const;
+ bool getUTCTime(WTF::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;
+ void msToGregorianDateTime(double, bool outputIsUTC, WTF::GregorianDateTime&) const;
private:
virtual const ClassInfo* classInfo() const { return &info; }
mutable Cache* m_cache;
};
- DateInstance* asDateInstance(JSValuePtr);
+ DateInstance* asDateInstance(JSValue);
- inline DateInstance* asDateInstance(JSValuePtr value)
+ inline DateInstance* asDateInstance(JSValue value)
{
ASSERT(asObject(value)->inherits(&DateInstance::info));
return static_cast<DateInstance*>(asObject(value));
+++ /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
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile, 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
#include "config.h"
#include "DatePrototype.h"
-#include "DateMath.h"
+#include "DateConversion.h"
+#include "Error.h"
#include "JSString.h"
#include "ObjectPrototype.h"
#include "DateInstance.h"
#include <float.h>
+
+#if !PLATFORM(MAC) && HAVE(LANGINFO_H)
+#include <langinfo.h>
+#endif
+
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <time.h>
#include <wtf/Assertions.h>
+#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
#include <wtf/StringExtras.h>
#include <wtf/UnusedParam.h>
#include <CoreFoundation/CoreFoundation.h>
+#if PLATFORM(WINCE) && !PLATFORM(QT)
+extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce
+#endif
+
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&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*, JSObject*, JSValue, const ArgList&);
+
+static JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*, JSObject*, JSValue, const ArgList&);
}
bool useCustomFormat = false;
UString customFormatString;
- UString arg0String = args.at(exec, 0).toString(exec);
- if (arg0String == "custom" && !args.at(exec, 1).isUndefined()) {
+ UString arg0String = args.at(0).toString(exec);
+ if (arg0String == "custom" && !args.at(1).isUndefined()) {
useCustomFormat = true;
- customFormatString = args.at(exec, 1).toString(exec);
- } else if (format == LocaleDateAndTime && !args.at(exec, 1).isUndefined()) {
+ customFormatString = args.at(1).toString(exec);
+ } else if (format == LocaleDateAndTime && !args.at(1).isUndefined()) {
dateStyle = styleFromArgString(arg0String, dateStyle);
- timeStyle = styleFromArgString(args.at(exec, 1).toString(exec), timeStyle);
- } else if (format != LocaleTime && !args.at(exec, 0).isUndefined())
+ timeStyle = styleFromArgString(args.at(1).toString(exec), timeStyle);
+ } else if (format != LocaleTime && !args.at(0).isUndefined())
dateStyle = styleFromArgString(arg0String, dateStyle);
- else if (format != LocaleDate && !args.at(exec, 0).isUndefined())
+ else if (format != LocaleDate && !args.at(0).isUndefined())
timeStyle = styleFromArgString(arg0String, timeStyle);
CFLocaleRef locale = CFLocaleCopyCurrent();
// hours
if (maxArgs >= 4 && idx < numArgs) {
t->hour = 0;
- milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerHour;
+ milliseconds += args.at(idx++).toInt32(exec, ok) * msPerHour;
}
// minutes
if (maxArgs >= 3 && idx < numArgs && ok) {
t->minute = 0;
- milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerMinute;
+ milliseconds += args.at(idx++).toInt32(exec, ok) * msPerMinute;
}
// seconds
if (maxArgs >= 2 && idx < numArgs && ok) {
t->second = 0;
- milliseconds += args.at(exec, idx++).toInt32(exec, ok) * msPerSecond;
+ milliseconds += args.at(idx++).toInt32(exec, ok) * msPerSecond;
}
if (!ok)
// milliseconds
if (idx < numArgs) {
- double millis = args.at(exec, idx).toNumber(exec);
+ double millis = args.at(idx).toNumber(exec);
ok = isfinite(millis);
milliseconds += millis;
} else
// years
if (maxArgs >= 3 && idx < numArgs)
- t->year = args.at(exec, idx++).toInt32(exec, ok) - 1900;
+ t->year = args.at(idx++).toInt32(exec, ok) - 1900;
// months
if (maxArgs >= 2 && idx < numArgs && ok)
- t->month = args.at(exec, idx++).toInt32(exec, ok);
+ t->month = args.at(idx++).toInt32(exec, ok);
// days
if (idx < numArgs && ok) {
t->monthDay = 0;
- *ms += args.at(exec, idx).toInt32(exec, ok) * msPerDay;
+ *ms += args.at(idx).toInt32(exec, ok) * msPerDay;
}
return ok;
/* Source for DatePrototype.lut.h
@begin dateTable
toString dateProtoFuncToString DontEnum|Function 0
+ toISOString dateProtoFuncToISOString DontEnum|Function 0
toUTCString dateProtoFuncToUTCString DontEnum|Function 0
toDateString dateProtoFuncToDateString DontEnum|Function 0
toTimeString dateProtoFuncToTimeString DontEnum|Function 0
setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
setYear dateProtoFuncSetYear DontEnum|Function 1
getYear dateProtoFuncGetYear DontEnum|Function 0
+ toJSON dateProtoFuncToJSON DontEnum|Function 0
@end
*/
// Functions
-JSValuePtr dateProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
}
-JSValuePtr dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
}
-JSValuePtr dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue 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 (!isfinite(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second)
+ // 6 for formatting and one for null termination = 23. We add one extra character to allow us to force null termination.
+ char buffer[24];
+ snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second);
+ buffer[sizeof(buffer) - 1] = 0;
+ return jsNontrivialString(exec, buffer);
+}
+
+JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNontrivialString(exec, formatDate(t));
}
-JSValuePtr dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNontrivialString(exec, formatTime(t, utc));
}
-JSValuePtr dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
}
-JSValuePtr dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
}
-JSValuePtr dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
}
-JSValuePtr dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, milli);
}
-JSValuePtr dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, 1900 + t.year);
}
-JSValuePtr dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, 1900 + t.year);
}
-JSValuePtr dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
}
-JSValuePtr dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.month);
}
-JSValuePtr dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.month);
}
-JSValuePtr dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.monthDay);
}
-JSValuePtr dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.monthDay);
}
-JSValuePtr dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.weekDay);
}
-JSValuePtr dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.weekDay);
}
-JSValuePtr dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.hour);
}
-JSValuePtr dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.hour);
}
-JSValuePtr dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.minute);
}
-JSValuePtr dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.minute);
}
-JSValuePtr dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.second);
}
-JSValuePtr dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.second);
}
-JSValuePtr dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, ms);
}
-JSValuePtr dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, ms);
}
-JSValuePtr dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
}
-JSValuePtr dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue 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);
+ double milli = timeClip(args.at(0).toNumber(exec));
+ JSValue result = jsNumber(exec, milli);
thisDateObj->setInternalValue(result);
return result;
}
-static JSValuePtr setNewValueFromTimeArgs(ExecState* exec, JSValuePtr thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
double milli = thisDateObj->internalNumber();
if (args.isEmpty() || isnan(milli)) {
- JSValuePtr result = jsNaN(exec);
+ JSValue result = jsNaN(exec);
thisDateObj->setInternalValue(result);
return result;
}
thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
- JSValuePtr result = jsNaN(exec);
+ JSValue result = jsNaN(exec);
thisDateObj->setInternalValue(result);
return result;
}
- JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ JSValue 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)
+static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue 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);
+ JSValue result = jsNaN(exec);
thisDateObj->setInternalValue(result);
return result;
}
}
if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
- JSValuePtr result = jsNaN(exec);
+ JSValue result = jsNaN(exec);
thisDateObj->setInternalValue(result);
return result;
}
- JSValuePtr result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
thisDateObj->setInternalValue(result);
return result;
}
-JSValuePtr dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
if (args.isEmpty()) {
- JSValuePtr result = jsNaN(exec);
+ JSValue result = jsNaN(exec);
thisDateObj->setInternalValue(result);
return result;
}
}
bool ok = true;
- int32_t year = args.at(exec, 0).toInt32(exec, ok);
+ int32_t year = args.at(0).toInt32(exec, ok);
if (!ok) {
- JSValuePtr result = jsNaN(exec);
+ JSValue 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));
+ JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
thisDateObj->setInternalValue(result);
return result;
}
-JSValuePtr dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&DateInstance::info))
return throwError(exec, TypeError);
return jsNumber(exec, t.year);
}
+JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+ JSObject* object = thisValue.toThisObject(exec);
+ if (exec->hadException())
+ return jsNull();
+
+ JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
+ if (exec->hadException())
+ return jsNull();
+
+ CallData callData;
+ CallType callType = toISOValue.getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError, "toISOString is not a function");
+
+ JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
+ if (exec->hadException())
+ return jsNull();
+ if (result.isObject())
+ return throwError(exec, TypeError, "toISOString did not return a primitive value");
+ return result;
+}
+
} // namespace JSC
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
#include "ConstructData.h"
#include "ErrorConstructor.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSObject.h"
#include "JSString.h"
break;
}
- ArgList args;
+ MarkedArgumentBuffer args;
if (message.isEmpty())
args.append(jsString(exec, name));
else
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)));
+ if (!args.at(0).isUndefined())
+ obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec)));
return obj;
}
}
// ECMA 15.9.2
-static JSValuePtr callErrorConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
// "Error()" gives the sames result as "new Error()"
return constructError(exec, args);
#include "config.h"
#include "ErrorPrototype.h"
+#include "JSFunction.h"
#include "JSString.h"
#include "ObjectPrototype.h"
#include "PrototypeFunction.h"
ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
-static JSValuePtr errorProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
// ECMA 15.9.4
ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
}
-JSValuePtr errorProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
JSObject* thisObj = thisValue.toThisObject(exec);
UString s = "Error";
- JSValuePtr v = thisObj->get(exec, exec->propertyNames().name);
+ JSValue v = thisObj->get(exec, exec->propertyNames().name);
if (!v.isUndefined())
s = v.toString(exec);
virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
};
-JSValuePtr createInterruptedExecutionException(JSGlobalData* globalData)
+JSValue createInterruptedExecutionException(JSGlobalData* globalData)
{
return new (globalData) InterruptedExecutionError(globalData);
}
-static JSValuePtr createError(ExecState* exec, ErrorType e, const char* msg)
+static JSValue createError(ExecState* exec, ErrorType e, const char* msg)
{
return Error::create(exec, e, msg, -1, -1, 0);
}
-JSValuePtr createStackOverflowError(ExecState* exec)
+JSValue createStackOverflowError(ExecState* exec)
{
return createError(exec, RangeError, "Maximum call stack size exceeded.");
}
-JSValuePtr createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
int startOffset = 0;
int endOffset = 0;
return exception;
}
-static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValuePtr value, UString error)
+static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error)
{
if (!expressionStop || expressionStart > codeBlock->source()->length()) {
UString errorText = value.toString(exec);
return errorText;
}
-JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
UString message = "not a valid argument for '";
message.append(op);
return exception;
}
-JSObject* createNotAConstructorError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
int startOffset = 0;
int endOffset = 0;
return exception;
}
-JSValuePtr createNotAFunctionError(ExecState* exec, JSValuePtr value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
int startOffset = 0;
int endOffset = 0;
#ifndef ExceptionHelpers_h
#define ExceptionHelpers_h
-#include "JSImmediate.h"
namespace JSC {
class JSGlobalData;
class JSNotAnObjectErrorStub;
class JSObject;
- class JSValuePtr;
+ class JSValue;
class Node;
- JSValuePtr createInterruptedExecutionException(JSGlobalData*);
- JSValuePtr createStackOverflowError(ExecState*);
- JSValuePtr createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
+ JSValue createInterruptedExecutionException(JSGlobalData*);
+ JSValue createStackOverflowError(ExecState*);
+ JSValue 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* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
+ JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
+ JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
} // namespace JSC
return ConstructTypeHost;
}
-static JSValuePtr callFunctionConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
return constructFunction(exec, args);
}
if (children.size() != 1)
return 0;
- ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(children[0].get());
+ StatementNode* exprStatement = children[0];
+ ASSERT(exprStatement);
ASSERT(exprStatement->isExprStatement());
if (!exprStatement || !exprStatement->isExprStatement())
return 0;
- FuncExprNode* funcExpr = static_cast<FuncExprNode*>(exprStatement->expr());
+ ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+ ASSERT(funcExpr);
ASSERT(funcExpr->isFuncExprNode());
if (!funcExpr || !funcExpr->isFuncExprNode())
return 0;
- FunctionBodyNode* body = funcExpr->body();
+ FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
ASSERT(body);
return body;
}
if (args.isEmpty())
program = "(function() { \n})";
else if (args.size() == 1)
- program = "(function() { " + args.at(exec, 0).toString(exec) + "\n})";
+ program = "(function() { " + args.at(0).toString(exec) + "\n})";
else {
- program = "(function(" + args.at(exec, 0).toString(exec);
+ program = "(function(" + args.at(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})";
+ program += "," + args.at(i).toString(exec);
+ program += ") { " + args.at(args.size() - 1).toString(exec) + "\n})";
}
int errLine;
#include "JSFunction.h"
#include "JSString.h"
#include "Interpreter.h"
+#include "Lexer.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&);
+static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, 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)
+void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction)
{
- 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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+ *applyFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
+ putDirectFunctionWithoutTransition(exec, *applyFunction, DontEnum);
+ *callFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
+ putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum);
}
-static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&)
+static JSValue JSC_HOST_CALL callFunctionPrototype(ExecState*, JSObject*, JSValue, const ArgList&)
{
return jsUndefined();
}
// Functions
-JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+// Compatibility hack for the Optimost JavaScript library. (See <rdar://problem/6595040>.)
+static inline void insertSemicolonIfNeeded(UString& functionBody)
+{
+ ASSERT(functionBody[0] == '{');
+ ASSERT(functionBody[functionBody.size() - 1] == '}');
+
+ for (size_t i = functionBody.size() - 2; i > 0; --i) {
+ UChar ch = functionBody[i];
+ if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) {
+ if (ch != ';' && ch != '}')
+ functionBody = functionBody.substr(0, i + 1) + ";" + functionBody.substr(i + 1, functionBody.size() - (i + 1));
+ return;
+ }
+ }
+}
+
+JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue 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 (!function->isHostFunction()) {
+ UString functionBody = function->body()->toSourceString();
+ insertSemicolonIfNeeded(functionBody);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + functionBody);
+ }
}
if (thisValue.isObject(&InternalFunction::info)) {
return throwError(exec, TypeError);
}
-JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue 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);
+ JSValue array = args.at(1);
- JSValuePtr applyThis;
- if (thisArg.isUndefinedOrNull())
- applyThis = exec->globalThisValue();
- else
- applyThis = thisArg.toObject(exec);
-
- ArgList applyArgs;
- if (!argArray.isUndefinedOrNull()) {
- if (!argArray.isObject())
+ MarkedArgumentBuffer applyArgs;
+ if (!array.isUndefinedOrNull()) {
+ if (!array.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);
+ if (asObject(array)->classInfo() == &Arguments::info)
+ asArguments(array)->fillArgList(exec, applyArgs);
+ else if (isJSArray(&exec->globalData(), array))
+ asArray(array)->fillArgList(exec, applyArgs);
+ else if (asObject(array)->inherits(&JSArray::info)) {
+ unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
for (unsigned i = 0; i < length; ++i)
- applyArgs.append(asArray(argArray)->get(exec, i));
+ applyArgs.append(asArray(array)->get(exec, i));
} else
return throwError(exec, TypeError);
}
- return call(exec, thisValue, callType, callData, applyThis, applyArgs);
+ return call(exec, thisValue, callType, callData, args.at(0), applyArgs);
}
-JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec, JSObject*, JSValue 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);
+ ArgList callArgs;
+ args.getSlice(1, callArgs);
+ return call(exec, thisValue, callType, callData, args.at(0), callArgs);
}
} // namespace JSC
namespace JSC {
+ class PrototypeFunction;
+
class FunctionPrototype : public InternalFunction {
public:
FunctionPrototype(ExecState*, PassRefPtr<Structure>);
- void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure);
+ void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
}
m_setter->mark();
}
-JSValuePtr GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
+JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return jsNull();
}
-bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
{
ASSERT_NOT_REACHED();
number = 0;
- value = noValue();
+ value = JSValue();
return true;
}
private:
virtual bool isGetterSetter() const;
- virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
JSObject* m_setter;
};
- GetterSetter* asGetterSetter(JSValuePtr);
+ GetterSetter* asGetterSetter(JSValue);
- inline GetterSetter* asGetterSetter(JSValuePtr value)
+ inline GetterSetter* asGetterSetter(JSValue value)
{
ASSERT(asCell(value)->isGetterSetter());
return static_cast<GetterSetter*>(asCell(value));
#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/DateMath.h>
#include <wtf/Threading.h>
using namespace WTF;
initializeUString();
#if ENABLE(JSC_MULTIPLE_THREADS)
s_dtoaP5Mutex = new Mutex;
- initDateMath();
+ WTF::initializeDates();
#endif
}
return asString(getDirect(globalData->propertyNames->name))->value();
}
+const UString InternalFunction::displayName(JSGlobalData* globalData)
+{
+ JSValue displayName = getDirect(globalData->propertyNames->displayName);
+
+ if (displayName && isJSString(globalData, displayName))
+ return asString(displayName)->value();
+
+ return UString::null();
+}
+
+const UString InternalFunction::calculatedDisplayName(JSGlobalData* globalData)
+{
+ const UString explicitName = displayName(globalData);
+
+ if (!explicitName.isEmpty())
+ return explicitName;
+
+ return name(globalData);
+}
+
} // namespace JSC
class InternalFunction : public JSObject {
public:
virtual const ClassInfo* classInfo() const;
- static const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo info;
const UString& name(JSGlobalData*);
+ const UString displayName(JSGlobalData*);
+ const UString calculatedDisplayName(JSGlobalData*);
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
}
virtual CallType getCallData(CallData&) = 0;
};
- InternalFunction* asInternalFunction(JSValuePtr);
+ InternalFunction* asInternalFunction(JSValue);
- inline InternalFunction* asInternalFunction(JSValuePtr value)
+ inline InternalFunction* asInternalFunction(JSValue value)
{
ASSERT(asObject(value)->inherits(&InternalFunction::info));
return static_cast<InternalFunction*>(asObject(value));
--- /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 "JSAPIValueWrapper.h"
+
+#include "NumberObject.h"
+#include "UString.h"
+
+namespace JSC {
+
+JSValue JSAPIValueWrapper::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return JSValue();
+}
+
+bool JSAPIValueWrapper::getPrimitiveNumber(ExecState*, double&, JSValue&)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+bool JSAPIValueWrapper::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double JSAPIValueWrapper::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+UString JSAPIValueWrapper::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return UString();
+}
+
+JSObject* JSAPIValueWrapper::toObject(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+} // 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 JSAPIValueWrapper_h
+#define JSAPIValueWrapper_h
+
+#include <wtf/Platform.h>
+
+#include "JSCell.h"
+
+namespace JSC {
+
+ class JSAPIValueWrapper : public JSCell {
+ friend JSValue jsAPIValueWrapper(ExecState*, JSValue);
+ public:
+ JSValue value() const { return m_value; }
+
+ virtual bool isAPIValueWrapper() const { return true; }
+
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ private:
+ JSAPIValueWrapper(JSValue value)
+ : JSCell(0)
+ , m_value(value)
+ {
+ }
+
+ JSValue m_value;
+ };
+
+ inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
+ {
+ return new (exec) JSAPIValueWrapper(value);
+ }
+
+} // namespace JSC
+
+#endif // JSAPIValueWrapper_h
const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
- : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame))
+ : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame->registers()))
{
}
if (!registerArray)
return;
- size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
+ size_t numParametersMinusThis = d()->functionBody->parameterCount();
size_t i = 0;
size_t count = numParametersMinusThis;
r.mark();
}
- size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+ size_t numVars = d()->numVars;
// Skip the call frame, which sits between the parameters and vars.
i += RegisterFile::CallFrameHeaderSize;
for ( ; i < count; ++i) {
Register& r = registerArray[i];
- if (!r.marked())
+ if (r.jsValue() && !r.marked())
r.mark();
}
}
if (symbolTableGet(propertyName, slot))
return true;
- if (JSValuePtr* location = getDirectLocation(propertyName)) {
+ if (JSValue* location = getDirectLocation(propertyName)) {
slot.setValueSlot(location);
return true;
}
return false;
}
-void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
}
// FIXME: Make this function honor ReadOnly (const) and DontEnum
-void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
// expose in the activation object.
ASSERT(!hasGetterSetterProperties());
PutPropertySlot slot;
- putDirect(propertyName, value, attributes, true, slot);
+ JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
}
bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
return d()->functionBody->usesEval();
}
-JSValuePtr JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSActivation* activation = asActivation(slot.slotBase());
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
- virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes);
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual JSObject* toThisObject(ExecState*) const;
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue 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)
+ JSActivationData(PassRefPtr<FunctionBodyNode> _functionBody, Register* registers)
+ : JSVariableObjectData(&_functionBody->generatedBytecode().symbolTable(), registers)
+ , functionBody(_functionBody)
+ , numVars(functionBody->generatedBytecode().m_numVars)
{
}
RefPtr<FunctionBodyNode> functionBody;
+ size_t numVars;
};
- static JSValuePtr argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
};
- JSActivation* asActivation(JSValuePtr);
+ JSActivation* asActivation(JSValue);
- inline JSActivation* asActivation(JSValuePtr value)
+ inline JSActivation* asActivation(JSValue value)
{
ASSERT(asObject(value)->inherits(&JSActivation::info));
return static_cast<JSActivation*>(asObject(value));
#include "JSArray.h"
#include "ArrayPrototype.h"
+#include "CachedCall.h"
#include "PropertyNameArray.h"
#include <wtf/AVLTree.h>
#include <wtf/Assertions.h>
+#include <wtf/OwnPtr.h>
#include <Operations.h>
#define CHECK_ARRAY_CONSISTENCY 0
// 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))
+// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValue)) +
+// (vectorLength * sizeof(JSValue)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue))
// 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>.
// 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));
+ size_t size = (sizeof(ArrayStorage) - sizeof(JSValue)) + (vectorLength * sizeof(JSValue));
// 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))));
+ ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValue))));
return size;
}
unsigned initialCapacity = 0;
m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
- m_fastAccessCutoff = 0;
m_storage->m_vectorLength = initialCapacity;
- m_storage->m_length = 0;
+
+ m_fastAccessCutoff = 0;
checkConsistency();
}
{
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 = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
m_storage->m_length = initialLength;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_numValuesInVector = 0;
+ m_storage->m_sparseValueMap = 0;
+ m_storage->lazyCreationData = 0;
- Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValuePtr));
+ JSValue* vector = m_storage->m_vector;
+ for (size_t i = 0; i < initialCapacity; ++i)
+ vector[i] = JSValue();
+
+ m_fastAccessCutoff = 0;
checkConsistency();
+
+ Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue));
}
-JSArray::JSArray(ExecState* exec, PassRefPtr<Structure> structure, const ArgList& list)
+JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list)
: JSObject(structure)
{
- unsigned length = list.size();
+ unsigned initialCapacity = 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;
+ m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
+ m_storage->m_length = initialCapacity;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_numValuesInVector = initialCapacity;
+ m_storage->m_sparseValueMap = 0;
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->m_vector[i] = *it;
- m_storage = storage;
-
- Heap::heap(this)->reportExtraMemoryCost(storageSize(length));
+ m_fastAccessCutoff = initialCapacity;
checkConsistency();
+
+ Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
}
JSArray::~JSArray()
}
if (i < storage->m_vectorLength) {
- JSValuePtr& valueSlot = storage->m_vector[i];
+ JSValue& valueSlot = storage->m_vector[i];
if (valueSlot) {
slot.setValueSlot(&valueSlot);
return true;
}
// ECMA 15.4.5.1
-void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
bool isArrayIndex;
unsigned i = propertyName.toArrayIndex(&isArrayIndex);
JSObject::put(exec, propertyName, value, slot);
}
-void JSArray::put(ExecState* exec, unsigned i, JSValuePtr value)
+void JSArray::put(ExecState* exec, unsigned i, JSValue value)
{
checkConsistency();
}
if (i < m_storage->m_vectorLength) {
- JSValuePtr& valueSlot = m_storage->m_vector[i];
+ JSValue& valueSlot = m_storage->m_vector[i];
if (valueSlot) {
valueSlot = value;
checkConsistency();
putSlowCase(exec, i, value);
}
-NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValuePtr value)
+NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue value)
{
ArrayStorage* storage = m_storage;
SparseArrayValueMap* map = storage->m_sparseValueMap;
if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
for (unsigned j = vectorLength; j < newVectorLength; ++j)
- storage->m_vector[j] = noValue();
+ storage->m_vector[j] = JSValue();
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();
+ storage->m_vector[j] = JSValue();
for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
storage->m_vector[j] = map->take(j);
}
ArrayStorage* storage = m_storage;
if (i < storage->m_vectorLength) {
- JSValuePtr& valueSlot = storage->m_vector[i];
+ JSValue& valueSlot = storage->m_vector[i];
if (!valueSlot) {
checkConsistency();
return false;
}
- valueSlot = noValue();
+ valueSlot = JSValue();
--storage->m_numValuesInVector;
if (m_fastAccessCutoff > i)
m_fastAccessCutoff = i;
storage->m_vectorLength = newVectorLength;
for (unsigned i = vectorLength; i < newVectorLength; ++i)
- storage->m_vector[i] = noValue();
+ storage->m_vector[i] = JSValue();
m_storage = storage;
return true;
unsigned usedVectorLength = min(length, storage->m_vectorLength);
for (unsigned i = newLength; i < usedVectorLength; ++i) {
- JSValuePtr& valueSlot = storage->m_vector[i];
+ JSValue& valueSlot = storage->m_vector[i];
bool hadValue = valueSlot;
- valueSlot = noValue();
+ valueSlot = JSValue();
storage->m_numValuesInVector -= hadValue;
}
checkConsistency();
}
-JSValuePtr JSArray::pop()
+JSValue JSArray::pop()
{
checkConsistency();
--length;
- JSValuePtr result;
+ JSValue result;
if (m_fastAccessCutoff > length) {
- JSValuePtr& valueSlot = m_storage->m_vector[length];
+ JSValue& valueSlot = m_storage->m_vector[length];
result = valueSlot;
ASSERT(result);
- valueSlot = noValue();
+ valueSlot = JSValue();
--m_storage->m_numValuesInVector;
m_fastAccessCutoff = length;
} else if (length < m_storage->m_vectorLength) {
- JSValuePtr& valueSlot = m_storage->m_vector[length];
+ JSValue& valueSlot = m_storage->m_vector[length];
result = valueSlot;
- valueSlot = noValue();
+ valueSlot = JSValue();
if (result)
--m_storage->m_numValuesInVector;
else
return result;
}
-void JSArray::push(ExecState* exec, JSValuePtr value)
+void JSArray::push(ExecState* exec, JSValue value)
{
checkConsistency();
unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
for (unsigned i = 0; i < usedVectorLength; ++i) {
- JSValuePtr value = storage->m_vector[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) {
- JSValuePtr value = it->second;
+ JSValue 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();
+ double da = static_cast<const JSValue*>(a)->uncheckedGetNumber();
+ double db = static_cast<const JSValue*>(b)->uncheckedGetNumber();
return (da > db) - (da < db);
}
-typedef std::pair<JSValuePtr, UString> ValueStringPair;
+typedef std::pair<JSValue, UString> ValueStringPair;
static int compareByStringPairForQSort(const void* a, const void* b)
{
return compare(va->second, vb->second);
}
-void JSArray::sortNumeric(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData)
+void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
{
unsigned lengthNotIncludingUndefined = compactForSorting();
if (m_storage->m_sparseValueMap) {
// 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);
+ qsort(m_storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort);
checkConsistency(SortConsistencyCheck);
}
}
for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
- JSValuePtr value = m_storage->m_vector[i];
+ JSValue value = m_storage->m_vector[i];
ASSERT(!value.isUndefined());
values[i].first = value;
}
}
struct AVLTreeNodeForArrayCompare {
- JSValuePtr value;
+ JSValue 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
struct AVLTreeAbstractorForArrayCompare {
typedef int32_t handle; // Handle is an index into m_nodes vector.
- typedef JSValuePtr key;
+ typedef JSValue key;
typedef int32_t size;
Vector<AVLTreeNodeForArrayCompare> m_nodes;
ExecState* m_exec;
- JSValuePtr m_compareFunction;
+ JSValue m_compareFunction;
CallType m_compareCallType;
const CallData* m_compareCallData;
- JSValuePtr m_globalThisValue;
+ JSValue m_globalThisValue;
+ OwnPtr<CachedCall> m_cachedCall;
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; }
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);
+ double compareResult;
+ if (m_cachedCall) {
+ m_cachedCall->setThis(m_globalThisValue);
+ m_cachedCall->setArgument(0, va);
+ m_cachedCall->setArgument(1, vb);
+ compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame());
+ } else {
+ MarkedArgumentBuffer arguments;
+ arguments.append(va);
+ arguments.append(vb);
+ 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.
}
static handle null() { return 0x7FFFFFFF; }
};
-void JSArray::sort(ExecState* exec, JSValuePtr compareFunction, CallType callType, const CallData& callData)
+void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
{
checkConsistency();
tree.abstractor().m_globalThisValue = exec->globalThisValue();
tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));
+ if (callType == CallTypeJS)
+ tree.abstractor().m_cachedCall.set(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot()));
+
if (!tree.abstractor().m_nodes.begin()) {
throwOutOfMemoryError(exec);
return;
// 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];
+ JSValue 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];
+ JSValue v = m_storage->m_vector[i];
if (v) {
if (v.isUndefined())
++numUndefined;
// Ensure that unused values in the vector are zeroed out.
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
- m_storage->m_vector[i] = noValue();
+ m_storage->m_vector[i] = JSValue();
m_fastAccessCutoff = newUsedVectorLength;
m_storage->m_numValuesInVector = newUsedVectorLength;
checkConsistency(SortConsistencyCheck);
}
-void JSArray::fillArgList(ExecState* exec, ArgList& args)
+void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
{
unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
unsigned i = 0;
args.append(get(exec, i));
}
+void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
+{
+ ASSERT(m_storage->m_length == maxSize);
+ UNUSED_PARAM(maxSize);
+ unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+ unsigned i = 0;
+ for (; i < fastAccessLength; ++i)
+ buffer[i] = getIndex(i);
+ uint32_t size = m_storage->m_length;
+ for (; i < size; ++i)
+ buffer[i] = get(exec, i);
+}
+
unsigned JSArray::compactForSorting()
{
checkConsistency();
unsigned numUndefined = 0;
for (; numDefined < usedVectorLength; ++numDefined) {
- JSValuePtr v = storage->m_vector[numDefined];
+ JSValue v = storage->m_vector[numDefined];
if (!v || v.isUndefined())
break;
}
for (unsigned i = numDefined; i < usedVectorLength; ++i) {
- JSValuePtr v = storage->m_vector[i];
+ JSValue v = storage->m_vector[i];
if (v) {
if (v.isUndefined())
++numUndefined;
for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
storage->m_vector[i] = jsUndefined();
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
- storage->m_vector[i] = noValue();
+ storage->m_vector[i] = JSValue();
m_fastAccessCutoff = newUsedVectorLength;
storage->m_numValuesInVector = newUsedVectorLength;
unsigned numValuesInVector = 0;
for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
- if (JSValuePtr value = m_storage->m_vector[i]) {
+ if (JSValue 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.
return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
}
-JSArray* constructArray(ExecState* exec, JSValuePtr singleItemValue)
+JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
{
- ArgList values;
+ MarkedArgumentBuffer values;
values.append(singleItemValue);
- return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
}
JSArray* constructArray(ExecState* exec, const ArgList& values)
{
- return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
}
} // namespace JSC
namespace JSC {
- typedef HashMap<unsigned, JSValuePtr> SparseArrayValueMap;
+ typedef HashMap<unsigned, JSValue> SparseArrayValueMap;
struct ArrayStorage {
unsigned m_length;
unsigned m_numValuesInVector;
SparseArrayValueMap* m_sparseValueMap;
void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
- JSValuePtr m_vector[1];
+ JSValue m_vector[1];
};
class JSArray : public JSObject {
public:
explicit JSArray(PassRefPtr<Structure>);
JSArray(PassRefPtr<Structure>, unsigned initialLength);
- JSArray(ExecState*, PassRefPtr<Structure>, const ArgList& initialValues);
+ JSArray(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.
+ virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
- static const ClassInfo info;
+ static JS_EXPORTDATA 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 sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
+ void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
- void push(ExecState*, JSValuePtr);
- JSValuePtr pop();
+ void push(ExecState*, JSValue);
+ JSValue pop();
bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
- JSValuePtr getIndex(unsigned i)
+ JSValue 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)
+ JSValue setIndex(unsigned i, JSValue v)
{
ASSERT(canSetIndex(i));
return m_storage->m_vector[i] = v;
}
- void fillArgList(ExecState*, ArgList&);
+ void fillArgList(ExecState*, MarkedArgumentBuffer&);
+ void copyToRegisters(ExecState*, Register*, uint32_t);
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
protected:
- virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual const ClassInfo* classInfo() const { return &info; }
bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
- void putSlowCase(ExecState*, unsigned propertyName, JSValuePtr);
+ void putSlowCase(ExecState*, unsigned propertyName, JSValue);
bool increaseVectorLength(unsigned newLength);
ArrayStorage* m_storage;
};
- JSArray* asArray(JSValuePtr);
+ JSArray* asArray(JSValue);
JSArray* constructEmptyArray(ExecState*);
JSArray* constructEmptyArray(ExecState*, unsigned initialLength);
- JSArray* constructArray(ExecState*, JSValuePtr singleItemValue);
+ JSArray* constructArray(ExecState*, JSValue singleItemValue);
JSArray* constructArray(ExecState*, const ArgList& values);
- inline JSArray* asArray(JSValuePtr value)
+ inline JSArray* asArray(JSValue value)
{
ASSERT(asObject(value)->inherits(&JSArray::info));
return static_cast<JSArray*>(asObject(value));
}
+ inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; }
+
} // namespace JSC
#endif // JSArray_h
putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
}
-PassRefPtr<Structure> JSByteArray::createStructure(JSValuePtr prototype)
+PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
{
PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType));
return result;
return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
-void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
bool ok;
unsigned index = propertyName.toUInt32(&ok, false);
JSObject::put(exec, propertyName, value, slot);
}
-void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value)
{
setIndex(exec, propertyName, value);
}
namespace JSC {
class JSByteArray : public JSObject {
- friend class Interpreter;
+ friend class VPtrSet;
public:
bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
- JSValuePtr getIndex(ExecState* exec, unsigned i)
+ JSValue getIndex(ExecState* exec, unsigned i)
{
ASSERT(canAccessIndex(i));
return jsNumber(exec, m_storage->data()[i]);
m_storage->data()[i] = static_cast<unsigned char>(value + 0.5);
}
- void setIndex(ExecState* exec, unsigned i, JSValuePtr value)
+ void setIndex(ExecState* exec, unsigned i, JSValue value)
{
double byteValue = value.toNumber(exec);
if (exec->hadException())
}
JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype);
+ static PassRefPtr<Structure> createStructure(JSValue 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 put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
+ virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
size_t length() const { return m_storage->length(); }
+ WTF::ByteArray* storage() const { return m_storage.get(); }
+
private:
enum VPtrStealingHackType { VPtrStealingHack };
JSByteArray(VPtrStealingHackType)
const ClassInfo* m_classInfo;
};
- JSByteArray* asByteArray(JSValuePtr value);
- inline JSByteArray* asByteArray(JSValuePtr value)
+ JSByteArray* asByteArray(JSValue value);
+ inline JSByteArray* asByteArray(JSValue value)
{
return static_cast<JSByteArray*>(asCell(value));
}
-}
-#endif
+ inline bool isJSByteArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsByteArrayVPtr; }
+
+} // namespace JSC
+
+#endif // JSByteArray_h
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 true;
}
-void JSCell::put(ExecState* exec, const Identifier& identifier, JSValuePtr value, PutPropertySlot& slot)
+void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
{
toObject(exec)->put(exec, identifier, value, slot);
}
-void JSCell::put(ExecState* exec, unsigned identifier, JSValuePtr value)
+void JSCell::put(ExecState* exec, unsigned identifier, JSValue value)
{
toObject(exec)->put(exec, identifier, value);
}
return 0;
}
-JSValuePtr JSCell::getJSNumber()
+JSValue JSCell::getJSNumber()
{
- return noValue();
+ return JSValue();
}
bool JSCell::isGetterSetter() const
namespace JSC {
class JSCell : Noncopyable {
- friend class JIT;
friend class GetterSetter;
friend class Heap;
+ friend class JIT;
friend class JSNumberCell;
friend class JSObject;
friend class JSPropertyNameIterator;
friend class JSString;
- friend class JSValuePtr;
- friend class Interpreter;
+ friend class JSValue;
+ friend class JSAPIValueWrapper;
+ friend struct VPtrSet;
private:
explicit JSCell(Structure*);
public:
// Querying the type.
+#if USE(JSVALUE32)
bool isNumber() const;
+#endif
bool isString() const;
bool isObject() const;
virtual bool isGetterSetter() const;
virtual bool isObject(const ClassInfo*) const;
+ virtual bool isAPIValueWrapper() const { return false; }
Structure* structure() const;
virtual ConstructType getConstructData(ConstructData&);
// Extracting integer values.
- // FIXME: remove these methods, can check isNumberCell in JSValuePtr && then call asNumberCell::*.
+ // FIXME: remove these methods, can check isNumberCell in JSValue && 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 JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0;
virtual bool toBoolean(ExecState*) const = 0;
virtual double toNumber(ExecState*) const = 0;
virtual UString toString(ExecState*) const = 0;
// 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 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue);
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();
+ virtual JSValue getJSNumber();
void* vptr() { return *reinterpret_cast<void**>(this); }
private:
Structure* m_structure;
};
- JSCell* asCell(JSValuePtr);
+ JSCell* asCell(JSValue);
- inline JSCell* asCell(JSValuePtr value)
+ inline JSCell* asCell(JSValue value)
{
return value.asCell();
}
{
}
+#if USE(JSVALUE32)
inline bool JSCell::isNumber() const
{
return Heap::isNumber(const_cast<JSCell*>(this));
}
+#endif
inline bool JSCell::isObject() const
{
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
// --- JSValue inlines ----------------------------
- inline bool JSValuePtr::isString() const
+ inline bool JSValue::isString() const
{
- return !JSImmediate::isImmediate(asValue()) && asCell()->isString();
+ return isCell() && asCell()->isString();
}
- inline bool JSValuePtr::isGetterSetter() const
+ inline bool JSValue::isGetterSetter() const
{
- return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter();
+ return isCell() && asCell()->isGetterSetter();
}
- inline bool JSValuePtr::isObject() const
+ inline bool JSValue::isObject() const
{
- return !JSImmediate::isImmediate(asValue()) && asCell()->isObject();
+ return isCell() && asCell()->isObject();
}
- inline bool JSValuePtr::getString(UString& s) const
+ inline bool JSValue::getString(UString& s) const
{
- return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s);
+ return isCell() && asCell()->getString(s);
}
- inline UString JSValuePtr::getString() const
+ inline UString JSValue::getString() const
{
- return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString();
+ return isCell() ? asCell()->getString() : UString();
}
- inline JSObject* JSValuePtr::getObject() const
+ inline JSObject* JSValue::getObject() const
{
- return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject();
+ return isCell() ? asCell()->getObject() : 0;
}
- inline CallType JSValuePtr::getCallData(CallData& callData)
+ inline CallType JSValue::getCallData(CallData& callData)
{
- return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData);
+ return isCell() ? asCell()->getCallData(callData) : CallTypeNone;
}
- inline ConstructType JSValuePtr::getConstructData(ConstructData& constructData)
+ inline ConstructType JSValue::getConstructData(ConstructData& constructData)
{
- return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData);
+ return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone;
}
- ALWAYS_INLINE bool JSValuePtr::getUInt32(uint32_t& v) const
+ ALWAYS_INLINE bool JSValue::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);
+ if (isInt32()) {
+ int32_t i = asInt32();
+ v = static_cast<uint32_t>(i);
+ return i >= 0;
+ }
+ if (isDouble()) {
+ double d = asDouble();
+ v = static_cast<uint32_t>(d);
+ return v == d;
+ }
+ return false;
}
- inline bool JSValuePtr::getTruncatedUInt32(uint32_t& v) const
+ inline void JSValue::mark()
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v);
+ asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
}
- inline void JSValuePtr::mark()
+ inline bool JSValue::marked() const
{
- asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
+ return !isCell() || asCell()->marked();
}
- inline bool JSValuePtr::marked() const
+#if !USE(JSVALUE32_64)
+ ALWAYS_INLINE JSCell* JSValue::asCell() const
{
- return JSImmediate::isImmediate(asValue()) || asCell()->marked();
+ ASSERT(isCell());
+ return m_ptr;
}
+#endif // !USE(JSVALUE32_64)
- inline JSValuePtr JSValuePtr::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+ inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
- return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType);
+ return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
}
- inline bool JSValuePtr::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& value)
+ inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
{
- if (JSImmediate::isImmediate(asValue())) {
- number = JSImmediate::toDouble(asValue());
- value = asValue();
+ if (isInt32()) {
+ number = asInt32();
+ value = *this;
+ return true;
+ }
+ if (isDouble()) {
+ number = asDouble();
+ value = *this;
+ return true;
+ }
+ if (isCell())
+ return asCell()->getPrimitiveNumber(exec, number, value);
+ if (isTrue()) {
+ number = 1.0;
+ value = *this;
+ return true;
+ }
+ if (isFalse() || isNull()) {
+ number = 0.0;
+ value = *this;
return true;
}
- return asCell()->getPrimitiveNumber(exec, number, value);
+ ASSERT(isUndefined());
+ number = nonInlineNaN();
+ value = *this;
+ return true;
}
- inline bool JSValuePtr::toBoolean(ExecState* exec) const
+ inline bool JSValue::toBoolean(ExecState* exec) const
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec);
+ if (isInt32())
+ return asInt32() != 0;
+ if (isDouble())
+ return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
+ if (isCell())
+ return asCell()->toBoolean(exec);
+ return isTrue(); // false, null, and undefined all convert to false.
}
- ALWAYS_INLINE double JSValuePtr::toNumber(ExecState* exec) const
+ ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec);
+ if (isInt32())
+ return asInt32();
+ if (isDouble())
+ return asDouble();
+ if (isCell())
+ return asCell()->toNumber(exec);
+ if (isTrue())
+ return 1.0;
+ return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
}
- inline UString JSValuePtr::toString(ExecState* exec) const
+ inline UString JSValue::toString(ExecState* exec) const
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec);
+ if (isCell())
+ return asCell()->toString(exec);
+ if (isInt32())
+ return UString::from(asInt32());
+ if (isDouble())
+ return asDouble() == 0.0 ? "0" : UString::from(asDouble());
+ if (isTrue())
+ return "true";
+ if (isFalse())
+ return "false";
+ if (isNull())
+ return "null";
+ ASSERT(isUndefined());
+ return "undefined";
}
- inline JSObject* JSValuePtr::toObject(ExecState* exec) const
+ inline bool JSValue::needsThisConversion() const
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec);
+ if (UNLIKELY(!isCell()))
+ return true;
+ return asCell()->structure()->typeInfo().needsThisConversion();
}
- inline JSObject* JSValuePtr::toThisObject(ExecState* exec) const
+ inline UString JSValue::toThisString(ExecState* exec) const
{
- if (UNLIKELY(JSImmediate::isImmediate(asValue())))
- return JSImmediate::toThisObject(asValue(), exec);
- return asCell()->toThisObject(exec);
+ return isCell() ? asCell()->toThisString(exec) : toString(exec);
}
- inline bool JSValuePtr::needsThisConversion() const
+ inline JSValue JSValue::getJSNumber()
{
- if (UNLIKELY(JSImmediate::isImmediate(asValue())))
- return true;
- return asCell()->structure()->typeInfo().needsThisConversion();
+ if (isInt32() || isDouble())
+ return *this;
+ if (isCell())
+ return asCell()->getJSNumber();
+ return JSValue();
}
- inline UString JSValuePtr::toThisString(ExecState* exec) const
+ inline JSObject* JSValue::toObject(ExecState* exec) const
{
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec);
+ return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
}
- inline JSValuePtr JSValuePtr::getJSNumber()
+ inline JSObject* JSValue::toThisObject(ExecState* exec) const
{
- return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber();
+ return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
}
} // namespace JSC
const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
+JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
+ : Base(&exec->globalData(), structure, name)
+#if ENABLE(JIT)
+ , m_body(FunctionBodyNode::createNativeThunk(&exec->globalData()))
+#else
+ , m_body(0)
+#endif
+{
+#if ENABLE(JIT)
+ setNativeFunction(func);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+#else
+ UNUSED_PARAM(length);
+ UNUSED_PARAM(func);
+ ASSERT_NOT_REACHED();
+#endif
+}
+
JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode)
: Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name)
, m_body(body)
- , m_scopeChain(scopeChainNode)
{
+ setScopeChain(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 ENABLE(JIT_OPTIMIZE_CALL)
if (m_body && m_body->isGenerated())
m_body->generatedBytecode().unlinkCallers();
#endif
+ if (!isHostFunction())
+ scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
}
void JSFunction::mark()
{
Base::mark();
m_body->mark();
- m_scopeChain.mark();
+ if (!isHostFunction())
+ scopeChain().mark();
}
CallType JSFunction::getCallData(CallData& callData)
{
+ if (isHostFunction()) {
+ callData.native.function = nativeFunction();
+ return CallTypeHost;
+ }
callData.js.functionBody = m_body.get();
- callData.js.scopeChain = m_scopeChain.node();
+ callData.js.scopeChain = scopeChain().node();
return CallTypeJS;
}
-JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args)
+JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
{
- return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot());
+ ASSERT(!isHostFunction());
+ return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
}
-JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSFunction* thisObj = asFunction(slot.slotBase());
+ ASSERT(!thisObj->isHostFunction());
return exec->interpreter()->retrieveArguments(exec, thisObj);
}
-JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSFunction* thisObj = asFunction(slot.slotBase());
+ ASSERT(!thisObj->isHostFunction());
return exec->interpreter()->retrieveCaller(exec, thisObj);
}
-JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSFunction* thisObj = asFunction(slot.slotBase());
+ ASSERT(!thisObj->isHostFunction());
return jsNumber(exec, thisObj->m_body->parameterCount());
}
bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
+ if (isHostFunction())
+ return Base::getOwnPropertySlot(exec, propertyName, slot);
+
if (propertyName == exec->propertyNames().prototype) {
- JSValuePtr* location = getDirectLocation(propertyName);
+ JSValue* location = getDirectLocation(propertyName);
if (!location) {
- JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure());
+ JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
putDirect(exec->propertyNames().prototype, prototype, DontDelete);
location = getDirectLocation(propertyName);
return Base::getOwnPropertySlot(exec, propertyName, slot);
}
-void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
+ if (isHostFunction()) {
+ Base::put(exec, propertyName, value, slot);
+ return;
+ }
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 (isHostFunction())
+ return Base::deleteProperty(exec, 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)
{
+ if (isHostFunction())
+ return ConstructTypeNone;
constructData.js.functionBody = m_body.get();
- constructData.js.scopeChain = m_scopeChain.node();
+ constructData.js.scopeChain = scopeChain().node();
return ConstructTypeJS;
}
JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
{
+ ASSERT(!isHostFunction());
Structure* structure;
- JSValuePtr prototype = get(exec, exec->propertyNames().prototype);
+ JSValue 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());
+ JSValue result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
if (exec->hadException() || !result.isObject())
return thisObj;
return asObject(result);
class JSFunction : public InternalFunction {
friend class JIT;
- friend class Interpreter;
+ friend class VPtrSet;
typedef InternalFunction Base;
JSFunction(PassRefPtr<Structure> structure)
: InternalFunction(structure)
- , m_scopeChain(NoScopeChain())
{
+ clearScopeChain();
}
public:
+ JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
~JSFunction();
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
JSObject* construct(ExecState*, const ArgList&);
- JSValuePtr call(ExecState*, JSValuePtr thisValue, const ArgList&);
+ JSValue call(ExecState*, JSValue thisValue, const ArgList&);
- void setScope(const ScopeChain& scopeChain) { m_scopeChain = scopeChain; }
- ScopeChain& scope() { return m_scopeChain; }
+ void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); }
+ ScopeChain& scope() { return scopeChain(); }
void setBody(FunctionBodyNode* body) { m_body = body; }
void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; }
virtual void mark();
- static const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
}
- private:
- virtual const ClassInfo* classInfo() const { return &info; }
+#if ENABLE(JIT)
+ bool isHostFunction() const { return m_body && m_body->isHostFunction(); }
+#else
+ bool isHostFunction() const { return false; }
+#endif
+ NativeFunction nativeFunction()
+ {
+ return *reinterpret_cast<NativeFunction*>(m_data);
+ }
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&);
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
RefPtr<FunctionBodyNode> m_body;
- ScopeChain m_scopeChain;
+ ScopeChain& scopeChain()
+ {
+ ASSERT(!isHostFunction());
+ return *reinterpret_cast<ScopeChain*>(m_data);
+ }
+ void clearScopeChain()
+ {
+ ASSERT(!isHostFunction());
+ new (m_data) ScopeChain(NoScopeChain());
+ }
+ void setScopeChain(ScopeChainNode* sc)
+ {
+ ASSERT(!isHostFunction());
+ new (m_data) ScopeChain(sc);
+ }
+ void setScopeChain(const ScopeChain& sc)
+ {
+ ASSERT(!isHostFunction());
+ *reinterpret_cast<ScopeChain*>(m_data) = sc;
+ }
+ void setNativeFunction(NativeFunction func)
+ {
+ *reinterpret_cast<NativeFunction*>(m_data) = func;
+ }
+ unsigned char m_data[sizeof(void*)];
};
- JSFunction* asFunction(JSValuePtr);
+ JSFunction* asFunction(JSValue);
- inline JSFunction* asFunction(JSValuePtr value)
+ inline JSFunction* asFunction(JSValue value)
{
ASSERT(asObject(value)->inherits(&JSFunction::info));
return static_cast<JSFunction*>(asObject(value));
#include "FunctionConstructor.h"
#include "Interpreter.h"
#include "JSActivation.h"
+#include "JSArray.h"
+#include "JSByteArray.h"
#include "JSClassRef.h"
+#include "JSFunction.h"
#include "JSLock.h"
#include "JSNotAnObject.h"
#include "JSStaticScopeObject.h"
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;
+extern JSC_CONST_HASHTABLE HashTable arrayTable;
+extern JSC_CONST_HASHTABLE HashTable jsonTable;
+extern JSC_CONST_HASHTABLE HashTable dateTable;
+extern JSC_CONST_HASHTABLE HashTable mathTable;
+extern JSC_CONST_HASHTABLE HashTable numberTable;
+extern JSC_CONST_HASHTABLE HashTable regExpTable;
+extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable stringTable;
+
+struct VPtrSet {
+ VPtrSet();
+
+ void* jsArrayVPtr;
+ void* jsByteArrayVPtr;
+ void* jsStringVPtr;
+ void* jsFunctionVPtr;
+};
+
+VPtrSet::VPtrSet()
+{
+ // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
+ void* storage = fastMalloc(sizeof(CollectorBlock));
-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))
+ JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
+ jsArrayVPtr = jsArray->vptr();
+ jsArray->~JSCell();
+
+ JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+ jsByteArrayVPtr = jsByteArray->vptr();
+ jsByteArray->~JSCell();
+
+ JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
+ jsStringVPtr = jsString->vptr();
+ jsString->~JSCell();
+
+ JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
+ jsFunctionVPtr = jsFunction->vptr();
+ jsFunction->~JSCell();
+
+ fastFree(storage);
+}
+
+JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
+ : isSharedInstance(isShared)
+ , clientData(0)
+ , arrayTable(fastNew<HashTable>(JSC::arrayTable))
+ , dateTable(fastNew<HashTable>(JSC::dateTable))
+ , jsonTable(fastNew<HashTable>(JSC::jsonTable))
+ , mathTable(fastNew<HashTable>(JSC::mathTable))
+ , numberTable(fastNew<HashTable>(JSC::numberTable))
+ , regExpTable(fastNew<HashTable>(JSC::regExpTable))
+ , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
+ , stringTable(fastNew<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)
+#if USE(JSVALUE32)
, numberStructure(JSNumberCell::createStructure(jsNull()))
#endif
+ , jsArrayVPtr(vptrSet.jsArrayVPtr)
+ , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr)
+ , jsStringVPtr(vptrSet.jsStringVPtr)
+ , jsFunctionVPtr(vptrSet.jsFunctionVPtr)
, identifierTable(createIdentifierTable())
, propertyNames(new CommonIdentifiers(this))
- , emptyList(new ArgList)
- , newParserObjects(0)
- , parserObjectExtraRefCounts(0)
+ , emptyList(new MarkedArgumentBuffer)
, lexer(new Lexer(this))
, parser(new Parser)
+ , interpreter(new Interpreter)
+#if ENABLE(JIT)
+ , jitStubs(this)
+#endif
+ , heap(this)
+ , initializingLazyNumericCompareFunction(false)
, head(0)
, dynamicGlobalObject(0)
- , isSharedInstance(isShared)
- , clientData(0)
, scopeNodeBeingReparsed(0)
- , heap(this)
+ , firstStringifierToMark(0)
{
#if PLATFORM(MAC)
startProfilerServerIfNeeded();
#endif
- interpreter->initialize(this);
}
JSGlobalData::~JSGlobalData()
arrayTable->deleteTable();
dateTable->deleteTable();
+ jsonTable->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;
+
+ fastDelete(const_cast<HashTable*>(arrayTable));
+ fastDelete(const_cast<HashTable*>(dateTable));
+ fastDelete(const_cast<HashTable*>(jsonTable));
+ fastDelete(const_cast<HashTable*>(mathTable));
+ fastDelete(const_cast<HashTable*>(numberTable));
+ fastDelete(const_cast<HashTable*>(regExpTable));
+ fastDelete(const_cast<HashTable*>(regExpConstructorTable));
+ fastDelete(const_cast<HashTable*>(stringTable));
delete parser;
delete lexer;
delete propertyNames;
deleteIdentifierTable(identifierTable);
- delete newParserObjects;
- delete parserObjectExtraRefCounts;
-
delete clientData;
}
-PassRefPtr<JSGlobalData> JSGlobalData::create()
+PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared)
{
- return adoptRef(new JSGlobalData);
+ return adoptRef(new JSGlobalData(isShared, VPtrSet()));
}
PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
{
-#ifndef NDEBUG
Structure::startIgnoringLeaks();
RefPtr<JSGlobalData> data = create();
Structure::stopIgnoringLeaks();
return data.release();
-#else
- return create();
-#endif
}
bool JSGlobalData::sharedInstanceExists()
{
JSGlobalData*& instance = sharedInstanceInternal();
if (!instance) {
- instance = new JSGlobalData(true);
+ instance = create(true).releaseRef();
#if ENABLE(JSC_MULTIPLE_THREADS)
instance->makeUsableFromMultipleThreads();
#endif
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
#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 "JITStubs.h"
#include "JSValue.h"
+#include "SmallStrings.h"
+#include "TimeoutChecker.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
struct OpaqueJSClass;
struct OpaqueJSClassContextData;
namespace JSC {
- class ArgList;
class CommonIdentifiers;
- class Heap;
+ class FunctionBodyNode;
class IdentifierTable;
class Instruction;
class Interpreter;
class JSObject;
class Lexer;
class Parser;
- class ParserRefCounted;
class ScopeNode;
+ class Stringifier;
class Structure;
class UString;
+
struct HashTable;
+ struct VPtrSet;
class JSGlobalData : public RefCounted<JSGlobalData> {
public:
+ struct ClientData {
+ virtual ~ClientData() = 0;
+ };
+
static bool sharedInstanceExists();
static JSGlobalData& sharedInstance();
- static PassRefPtr<JSGlobalData> create();
+ static PassRefPtr<JSGlobalData> create(bool isShared = false);
static PassRefPtr<JSGlobalData> createLeaked();
~JSGlobalData();
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
+ bool isSharedInstance;
+ ClientData* clientData;
const HashTable* arrayTable;
const HashTable* dateTable;
+ const HashTable* jsonTable;
const HashTable* mathTable;
const HashTable* numberTable;
const HashTable* regExpTable;
RefPtr<Structure> stringStructure;
RefPtr<Structure> notAnObjectErrorStubStructure;
RefPtr<Structure> notAnObjectStructure;
-#if !USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE32)
RefPtr<Structure> numberStructure;
#endif
+ void* jsArrayVPtr;
+ void* jsByteArrayVPtr;
+ void* jsStringVPtr;
+ void* jsFunctionVPtr;
+
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.
-
+ const MarkedArgumentBuffer* 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;
+#if ENABLE(ASSEMBLER)
+ ExecutableAllocator executableAllocator;
+#endif
Lexer* lexer;
Parser* parser;
+ Interpreter* interpreter;
+#if ENABLE(JIT)
+ JITThunks jitStubs;
+#endif
+ TimeoutChecker timeoutChecker;
+ Heap heap;
- JSGlobalObject* head;
- JSGlobalObject* dynamicGlobalObject;
+ JSValue exception;
+#if ENABLE(JIT)
+ ReturnAddressPtr exceptionLocation;
+#endif
- bool isSharedInstance;
+ const Vector<Instruction>& numericCompareFunction(ExecState*);
+ Vector<Instruction> lazyNumericCompareFunction;
+ bool initializingLazyNumericCompareFunction;
- struct ClientData {
- virtual ~ClientData() = 0;
- };
+ HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
- ClientData* clientData;
+ JSGlobalObject* head;
+ JSGlobalObject* dynamicGlobalObject;
HashSet<JSObject*> arrayVisitedElements;
ScopeNode* scopeNodeBeingReparsed;
+ Stringifier* firstStringifierToMark;
- 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
-
+ JSGlobalData(bool isShared, const VPtrSet&);
static JSGlobalData*& sharedInstanceInternal();
+ void createNativeThunk();
};
-}
+} // namespace JSC
-#endif
+#endif // JSGlobalData_h
#include "FunctionConstructor.h"
#include "FunctionPrototype.h"
#include "GlobalEvalFunction.h"
+#include "JSFunction.h"
#include "JSGlobalObjectFunctions.h"
#include "JSLock.h"
+#include "JSONObject.h"
#include "Interpreter.h"
#include "MathObject.h"
#include "NativeErrorConstructor.h"
// Preferred number of milliseconds between each timeout check
static const int preferredScriptCheckTimeInterval = 1000;
-static inline void markIfNeeded(JSValuePtr v)
+static inline void markIfNeeded(JSValue v)
{
if (v && !v.marked())
v.mark();
reset(prototype());
}
-void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
JSVariableObject::put(exec, propertyName, value, slot);
}
-void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
if (symbolTablePutWithAttributes(propertyName, value, attributes))
return;
- JSValuePtr valueBefore = getDirect(propertyName);
+ JSValue valueBefore = getDirect(propertyName);
PutPropertySlot slot;
JSVariableObject::put(exec, propertyName, value, slot);
if (!valueBefore) {
- JSValuePtr valueAfter = getDirect(propertyName);
+ JSValue valueAfter = getDirect(propertyName);
if (valueAfter)
- putDirect(propertyName, valueAfter, attributes);
+ JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
}
}
return o;
}
-void JSGlobalObject::reset(JSValuePtr prototype)
+void JSGlobalObject::reset(JSValue prototype)
{
ExecState* exec = JSGlobalObject::globalExec();
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());
+ NativeFunctionWrapper* callFunction = 0;
+ NativeFunctionWrapper* applyFunction = 0;
+ d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction);
+ d()->callFunction = callFunction;
+ d()->applyFunction = applyFunction;
d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get());
d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype);
d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype);
+ d()->methodCallDummy = constructEmptyObject(exec);
+
ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
// 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);
+ JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
+ JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
+ JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
+ JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
+ JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
+ JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
+ JSCell* 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()->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);
+ d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
+ d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
+ d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
+ d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
+ d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
+ d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
+ d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
+ d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
+ errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum);
rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum);
// 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);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
+ putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
+ putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
+ putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
+ putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
+ putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
+ putDirectFunctionWithoutTransition(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)
+ GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(JSONObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete)
};
addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(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)
+void JSGlobalObject::resetPrototype(JSValue 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();
+ JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this);
+ JSObject* objectPrototype = d()->objectPrototype;
+ if (oldLastInPrototypeChain != objectPrototype)
+ oldLastInPrototypeChain->setPrototype(objectPrototype);
}
void JSGlobalObject::mark()
markIfNeeded(d()->URIErrorConstructor);
markIfNeeded(d()->evalFunction);
+ markIfNeeded(d()->callFunction);
+ markIfNeeded(d()->applyFunction);
markIfNeeded(d()->objectPrototype);
markIfNeeded(d()->functionPrototype);
markIfNeeded(d()->datePrototype);
markIfNeeded(d()->regExpPrototype);
+ markIfNeeded(d()->methodCallDummy);
+
markIfNeeded(d()->errorStructure);
// No need to mark the other structures, because their prototypes are all
#include "JSGlobalData.h"
#include "JSVariableObject.h"
+#include "NativeFunctionWrapper.h"
#include "NumberPrototype.h"
#include "StringPrototype.h"
#include <wtf/HashSet.h>
class GlobalEvalFunction;
class NativeErrorConstructor;
class ProgramCodeBlock;
+ class PrototypeFunction;
class RegExpConstructor;
class RegExpPrototype;
class RegisterFile;
, typeErrorConstructor(0)
, URIErrorConstructor(0)
, evalFunction(0)
+ , callFunction(0)
+ , applyFunction(0)
, objectPrototype(0)
, functionPrototype(0)
, arrayPrototype(0)
, numberPrototype(0)
, datePrototype(0)
, regExpPrototype(0)
+ , methodCallDummy(0)
{
}
NativeErrorConstructor* URIErrorConstructor;
GlobalEvalFunction* evalFunction;
+ NativeFunctionWrapper* callFunction;
+ NativeFunctionWrapper* applyFunction;
ObjectPrototype* objectPrototype;
FunctionPrototype* functionPrototype;
DatePrototype* datePrototype;
RegExpPrototype* regExpPrototype;
+ JSObject* methodCallDummy;
+
RefPtr<Structure> argumentsStructure;
RefPtr<Structure> arrayStructure;
RefPtr<Structure> booleanObjectStructure;
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 bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
+ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
DatePrototype* datePrototype() const { return d()->datePrototype; }
RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
+ JSObject* methodCallDummy() const { return d()->methodCallDummy; }
+
Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
Structure* arrayStructure() const { return d()->arrayStructure.get(); }
Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.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; }
void copyGlobalsFrom(RegisterFile&);
void copyGlobalsTo(RegisterFile&);
- void resetPrototype(JSValuePtr prototype);
+ void resetPrototype(JSValue prototype);
JSGlobalData* globalData() { return d()->globalData.get(); }
JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
protected:
struct GlobalPropertyInfo {
- GlobalPropertyInfo(const Identifier& i, JSValuePtr v, unsigned a)
+ GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
: identifier(i)
, value(v)
, attributes(a)
}
const Identifier identifier;
- JSValuePtr value;
+ JSValue value;
unsigned attributes;
};
void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
// FIXME: Fold reset into init.
void init(JSObject* thisValue);
- void reset(JSValuePtr prototype);
+ void reset(JSValue prototype);
void setRegisters(Register* registers, Register* registerArray, size_t count);
void* operator new(size_t); // can only be allocated with JSGlobalData
};
- JSGlobalObject* asGlobalObject(JSValuePtr);
+ JSGlobalObject* asGlobalObject(JSValue);
- inline JSGlobalObject* asGlobalObject(JSValuePtr value)
+ inline JSGlobalObject* asGlobalObject(JSValue value)
{
ASSERT(asObject(value)->isGlobalObject());
return static_cast<JSGlobalObject*>(asObject(value));
return symbolTableGet(propertyName, slot);
}
- inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
{
- if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
+ PropertySlot slot;
+ if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
return true;
+ bool slotIsWriteable;
return symbolTableGet(propertyName, slot, slotIsWriteable);
}
return asGlobalObject(n->object);
}
- inline JSValuePtr Structure::prototypeForLookup(ExecState* exec) const
+ inline JSValue Structure::prototypeForLookup(ExecState* exec) const
{
if (typeInfo().type() == ObjectType)
return m_prototype;
+#if USE(JSVALUE32)
if (typeInfo().type() == StringType)
return exec->lexicalGlobalObject()->stringPrototype();
ASSERT(typeInfo().type() == NumberType);
return exec->lexicalGlobalObject()->numberPrototype();
+#else
+ ASSERT(typeInfo().type() == StringType);
+ return exec->lexicalGlobalObject()->stringPrototype();
+#endif
}
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);
+ JSValue prototype = prototypeForLookup(exec);
m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
}
return m_cachedPrototypeChain.get();
if (!cachedPrototypeChain)
return false;
- JSValuePtr prototype = prototypeForLookup(exec);
+ JSValue prototype = prototypeForLookup(exec);
RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
while(*cachedStructure && !prototype.isNull()) {
if (asObject(prototype)->structure() != *cachedStructure)
#include "CallFrame.h"
#include "GlobalEvalFunction.h"
#include "JSGlobalObject.h"
+#include "LiteralParser.h"
#include "JSString.h"
#include "Interpreter.h"
#include "Parser.h"
namespace JSC {
-static JSValuePtr encode(ExecState* exec, const ArgList& args, const char* doNotEscape)
+static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEscape)
{
- UString str = args.at(exec, 0).toString(exec);
+ UString str = args.at(0).toString(exec);
CString cstr = str.UTF8String(true);
if (!cstr.c_str())
return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
return jsString(exec, result);
}
-static JSValuePtr decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
+static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
{
UString result = "";
- UString str = args.at(exec, 0).toString(exec);
+ UString str = args.at(0).toString(exec);
int k = 0;
int len = str.size();
const UChar* d = str.data();
return s.toDouble(true /*tolerant*/, false /* NaN for empty string */);
}
-JSValuePtr globalFuncEval(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValue 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);
+ JSValue x = args.at(0);
if (!x.isString())
return x;
UString s = x.toString(exec);
+ LiteralParser preparser(exec, s, LiteralParser::NonStrictJSON);
+ if (JSValue parsedObject = preparser.tryLiteralParse())
+ return parsedObject;
+
int errLine;
UString errMsg;
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)
+JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- JSValuePtr value = args.at(exec, 0);
- int32_t radix = args.at(exec, 1).toInt32(exec);
+ JSValue value = args.at(0);
+ int32_t radix = args.at(1).toInt32(exec);
+
+ if (radix != 0 && radix != 10)
+ return jsNumber(exec, parseInt(value.toString(exec), radix));
+
+ if (value.isInt32())
+ return value;
- if (value.isNumber() && (radix == 0 || radix == 10)) {
- if (value.isInt32Fast())
- return value;
- double d = value.uncheckedGetNumber();
+ if (value.isDouble()) {
+ double d = value.asDouble();
if (isfinite(d))
return jsNumber(exec, (d > 0) ? floor(d) : ceil(d));
if (isnan(d) || isinf(d))
- return jsNaN(&exec->globalData());
- return js0();
+ return jsNaN(exec);
+ return jsNumber(exec, 0);
}
return jsNumber(exec, parseInt(value.toString(exec), radix));
}
-JSValuePtr globalFuncParseFloat(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, parseFloat(args.at(exec, 0).toString(exec)));
+ return jsNumber(exec, parseFloat(args.at(0).toString(exec)));
}
-JSValuePtr globalFuncIsNaN(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsBoolean(isnan(args.at(exec, 0).toNumber(exec)));
+ return jsBoolean(isnan(args.at(0).toNumber(exec)));
}
-JSValuePtr globalFuncIsFinite(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- double n = args.at(exec, 0).toNumber(exec);
+ double n = args.at(0).toNumber(exec);
return jsBoolean(!isnan(n) && !isinf(n));
}
-JSValuePtr globalFuncDecodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue, 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)
+JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
return decode(exec, args, "", true);
}
-JSValuePtr globalFuncEncodeURI(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
static const char do_not_escape_when_encoding_URI[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return encode(exec, args, do_not_escape_when_encoding_URI);
}
-JSValuePtr globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
static const char do_not_escape_when_encoding_URI_component[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return encode(exec, args, do_not_escape_when_encoding_URI_component);
}
-JSValuePtr globalFuncEscape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
static const char do_not_escape[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
UString result = "";
UString s;
- UString str = args.at(exec, 0).toString(exec);
+ UString str = args.at(0).toString(exec);
const UChar* c = str.data();
for (int k = 0; k < str.size(); k++, c++) {
int u = c[0];
return jsString(exec, result);
}
-JSValuePtr globalFuncUnescape(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
UString result = "";
- UString str = args.at(exec, 0).toString(exec);
+ UString str = args.at(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])) {
+ if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(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])) {
+ } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
u = UChar(Lexer::convertHex(c[1], c[2]));
c = &u;
k += 2;
}
#ifndef NDEBUG
-JSValuePtr globalFuncJSCPrint(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
CStringBuffer string;
- args.at(exec, 0).toString(exec).getCString(string);
+ args.at(0).toString(exec).getCString(string);
puts(string.data());
return jsUndefined();
}
class ArgList;
class ExecState;
class JSObject;
- class JSValuePtr;
+ class JSValue;
// 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&);
+ JSValue JSC_HOST_CALL globalFuncEval(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncParseInt(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncEscape(ExecState*, JSObject*, JSValue, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState*, JSObject*, JSValue, const ArgList&);
#ifndef NDEBUG
- JSValuePtr globalFuncJSCPrint(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState*, JSObject*, JSValue, const ArgList&);
#endif
static const double mantissaOverflowLowerBound = 9007199254740992.0;
#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
#ifndef JSImmediate_h
#define JSImmediate_h
+#include <wtf/Platform.h>
+
+#if !USE(JSVALUE32_64)
+
#include <wtf/Assertions.h>
#include <wtf/AlwaysInline.h>
#include <wtf/MathExtras.h>
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)
+#if USE(JSVALUE64)
inline intptr_t reinterpretDoubleToIntptr(double value)
{
return WTF::bitwise_cast<intptr_t>(value);
/*
* 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
+ * USE(JSVALUE64) 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
class JSImmediate {
private:
friend class JIT;
- friend class JSValuePtr;
+ friend class JSValue;
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)
+ friend JSValue jsNumber(ExecState* exec, double d);
+ friend JSValue jsNumber(ExecState*, char i);
+ friend JSValue jsNumber(ExecState*, unsigned char i);
+ friend JSValue jsNumber(ExecState*, short i);
+ friend JSValue jsNumber(ExecState*, unsigned short i);
+ friend JSValue jsNumber(ExecState* exec, int i);
+ friend JSValue jsNumber(ExecState* exec, unsigned i);
+ friend JSValue jsNumber(ExecState* exec, long i);
+ friend JSValue jsNumber(ExecState* exec, unsigned long i);
+ friend JSValue jsNumber(ExecState* exec, long long i);
+ friend JSValue jsNumber(ExecState* exec, unsigned long long i);
+ friend JSValue jsNumber(JSGlobalData* globalData, double d);
+ friend JSValue jsNumber(JSGlobalData* globalData, short i);
+ friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i);
+ friend JSValue jsNumber(JSGlobalData* globalData, int i);
+ friend JSValue jsNumber(JSGlobalData* globalData, unsigned i);
+ friend JSValue jsNumber(JSGlobalData* globalData, long i);
+ friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i);
+ friend JSValue jsNumber(JSGlobalData* globalData, long long i);
+ friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i);
+
+#if USE(JSVALUE64)
// 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;
static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
static const intptr_t FullTagTypeNull = TagBitTypeOther;
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
static const int32_t IntegerPayloadShift = 0;
#else
static const int32_t IntegerPayloadShift = 1;
static const int32_t signBit = 0x80000000;
- static ALWAYS_INLINE bool isImmediate(JSValuePtr v)
+ static ALWAYS_INLINE bool isImmediate(JSValue v)
{
return rawValue(v) & TagMask;
}
- static ALWAYS_INLINE bool isNumber(JSValuePtr v)
+ static ALWAYS_INLINE bool isNumber(JSValue v)
{
return rawValue(v) & TagTypeNumber;
}
- static ALWAYS_INLINE bool isIntegerNumber(JSValuePtr v)
+ static ALWAYS_INLINE bool isIntegerNumber(JSValue v)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
#else
return isNumber(v);
#endif
}
-#if USE(ALTERNATE_JSIMMEDIATE)
- static ALWAYS_INLINE bool isDoubleNumber(JSValuePtr v)
+#if USE(JSVALUE64)
+ static ALWAYS_INLINE bool isDouble(JSValue v)
{
return isNumber(v) && !isIntegerNumber(v);
}
#endif
- static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValuePtr v)
+ static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue 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)
+ static ALWAYS_INLINE bool isBoolean(JSValue v)
{
return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
}
- static ALWAYS_INLINE bool isUndefinedOrNull(JSValuePtr v)
+ static ALWAYS_INLINE bool isUndefinedOrNull(JSValue 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 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 isEitherImmediate(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2)
{
return (rawValue(v1) | rawValue(v2)) & TagMask;
}
- static ALWAYS_INLINE bool areBothImmediate(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2)
{
return isImmediate(v1) & isImmediate(v2);
}
- static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2)
{
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
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 double toDouble(JSValue);
+ static bool toBoolean(JSValue);
- static int32_t getTruncatedInt32(JSValuePtr);
- static uint32_t getTruncatedUInt32(JSValuePtr);
+ static bool getUInt32(JSValue, uint32_t&);
+ static bool getTruncatedInt32(JSValue, int32_t&);
+ static bool getTruncatedUInt32(JSValue, uint32_t&);
- static JSValuePtr trueImmediate();
- static JSValuePtr falseImmediate();
- static JSValuePtr undefinedImmediate();
- static JSValuePtr nullImmediate();
- static JSValuePtr zeroImmediate();
- static JSValuePtr oneImmediate();
+ static int32_t getTruncatedInt32(JSValue);
+ static uint32_t getTruncatedUInt32(JSValue);
- static JSValuePtr impossibleValue();
-
- static JSObject* prototype(JSValuePtr, ExecState*);
+ static JSValue trueImmediate();
+ static JSValue falseImmediate();
+ static JSValue undefinedImmediate();
+ static JSValue nullImmediate();
+ static JSValue zeroImmediate();
+ static JSValue oneImmediate();
private:
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
static const int minImmediateInt = ((-INT_MAX) - 1);
static const int maxImmediateInt = INT_MAX;
#else
#endif
static const unsigned maxImmediateUInt = maxImmediateInt;
- static ALWAYS_INLINE JSValuePtr makeValue(intptr_t integer)
+ static ALWAYS_INLINE JSValue makeValue(intptr_t integer)
{
- return JSValuePtr::makeImmediate(integer);
+ return JSValue::makeImmediate(integer);
}
- // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the
+ // With USE(JSVALUE64) 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)
+#if USE(JSVALUE64)
+ static ALWAYS_INLINE JSValue makeInt(uint32_t value)
#else
- static ALWAYS_INLINE JSValuePtr makeInt(int32_t value)
+ static ALWAYS_INLINE JSValue 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)
+#if USE(JSVALUE64)
+ static ALWAYS_INLINE JSValue makeDouble(double value)
{
return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
}
#endif
- static ALWAYS_INLINE JSValuePtr makeBool(bool b)
+ static ALWAYS_INLINE JSValue makeBool(bool b)
{
return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
}
- static ALWAYS_INLINE JSValuePtr makeUndefined()
+ static ALWAYS_INLINE JSValue makeUndefined()
{
return makeValue(FullTagTypeUndefined);
}
- static ALWAYS_INLINE JSValuePtr makeNull()
+ static ALWAYS_INLINE JSValue makeNull()
{
return makeValue(FullTagTypeNull);
}
template<typename T>
- static JSValuePtr fromNumberOutsideIntegerRange(T);
+ static JSValue fromNumberOutsideIntegerRange(T);
-#if USE(ALTERNATE_JSIMMEDIATE)
- static ALWAYS_INLINE double doubleValue(JSValuePtr v)
+#if USE(JSVALUE64)
+ static ALWAYS_INLINE double doubleValue(JSValue v)
{
return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
}
#endif
- static ALWAYS_INLINE int32_t intValue(JSValuePtr v)
+ static ALWAYS_INLINE int32_t intValue(JSValue v)
{
return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
}
- static ALWAYS_INLINE uint32_t uintValue(JSValuePtr v)
+ static ALWAYS_INLINE uint32_t uintValue(JSValue v)
{
return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
}
- static ALWAYS_INLINE bool boolValue(JSValuePtr v)
+ static ALWAYS_INLINE bool boolValue(JSValue v)
{
return rawValue(v) & ExtendedPayloadBitBoolValue;
}
- static ALWAYS_INLINE intptr_t rawValue(JSValuePtr v)
+ static ALWAYS_INLINE intptr_t rawValue(JSValue 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); }
+ ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); }
+ ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); }
+ ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); }
+ ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); }
+ ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); }
+ ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); }
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
inline bool doubleToBoolean(double value)
{
return value < 0.0 || value > 0.0;
}
- ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
+ ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
{
ASSERT(isImmediate(v));
return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
: doubleToBoolean(doubleValue(v)) : v == trueImmediate();
}
#else
- ALWAYS_INLINE bool JSImmediate::toBoolean(JSValuePtr v)
+ ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
{
ASSERT(isImmediate(v));
return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
}
#endif
- ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValuePtr v)
+ ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v)
{
// FIXME: should probably be asserting isPositiveIntegerNumber here.
ASSERT(isIntegerNumber(v));
return intValue(v);
}
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
template<typename T>
- inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T value)
+ inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value)
{
return makeDouble(static_cast<double>(value));
}
#else
template<typename T>
- inline JSValuePtr JSImmediate::fromNumberOutsideIntegerRange(T)
+ inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T)
{
- return noValue();
+ return JSValue();
}
#endif
- ALWAYS_INLINE JSValuePtr JSImmediate::from(char i)
+ ALWAYS_INLINE JSValue JSImmediate::from(char i)
{
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(signed char i)
+ ALWAYS_INLINE JSValue JSImmediate::from(signed char i)
{
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned char i)
+ ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i)
{
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(short i)
+ ALWAYS_INLINE JSValue JSImmediate::from(short i)
{
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned short i)
+ ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i)
{
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(int i)
+ ALWAYS_INLINE JSValue JSImmediate::from(int i)
{
-#if !USE(ALTERNATE_JSIMMEDIATE)
+#if !USE(JSVALUE64)
if ((i < minImmediateInt) | (i > maxImmediateInt))
return fromNumberOutsideIntegerRange(i);
#endif
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned i)
+ ALWAYS_INLINE JSValue JSImmediate::from(unsigned i)
{
if (i > maxImmediateUInt)
return fromNumberOutsideIntegerRange(i);
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(long i)
+ ALWAYS_INLINE JSValue JSImmediate::from(long i)
{
if ((i < minImmediateInt) | (i > maxImmediateInt))
return fromNumberOutsideIntegerRange(i);
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long i)
+ ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i)
{
if (i > maxImmediateUInt)
return fromNumberOutsideIntegerRange(i);
return makeInt(i);
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(long long i)
+ ALWAYS_INLINE JSValue JSImmediate::from(long long i)
{
if ((i < minImmediateInt) | (i > maxImmediateInt))
- return noValue();
+ return JSValue();
return makeInt(static_cast<intptr_t>(i));
}
- ALWAYS_INLINE JSValuePtr JSImmediate::from(unsigned long long i)
+ ALWAYS_INLINE JSValue 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)
+ ALWAYS_INLINE JSValue JSImmediate::from(double d)
{
const int intVal = static_cast<int>(d);
return from(intVal);
}
- ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValuePtr v)
+ ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v)
{
ASSERT(isIntegerNumber(v));
return intValue(v);
}
- ALWAYS_INLINE double JSImmediate::toDouble(JSValuePtr v)
+ ALWAYS_INLINE double JSImmediate::toDouble(JSValue v)
{
ASSERT(isImmediate(v));
if (isIntegerNumber(v))
return intValue(v);
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
if (isNumber(v)) {
- ASSERT(isDoubleNumber(v));
+ ASSERT(isDouble(v));
return doubleValue(v);
}
#else
return rawValue(v) >> ExtendedPayloadShift;
}
- ALWAYS_INLINE bool JSImmediate::getUInt32(JSValuePtr v, uint32_t& i)
+ ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i)
{
i = uintValue(v);
return isPositiveIntegerNumber(v);
}
- ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValuePtr v, int32_t& i)
+ ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i)
{
i = intValue(v);
return isIntegerNumber(v);
}
- ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValuePtr v, uint32_t& i)
+ ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i)
{
return getUInt32(v, i);
}
- inline JSValuePtr js0()
+ inline JSValue::JSValue(JSNullTag)
{
- return JSImmediate::zeroImmediate();
+ *this = JSImmediate::nullImmediate();
}
-
- inline JSValuePtr jsNull()
+
+ inline JSValue::JSValue(JSUndefinedTag)
{
- return JSImmediate::nullImmediate();
+ *this = JSImmediate::undefinedImmediate();
}
- inline JSValuePtr jsBoolean(bool b)
+ inline JSValue::JSValue(JSTrueTag)
{
- return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
+ *this = JSImmediate::trueImmediate();
}
- inline JSValuePtr jsUndefined()
+ inline JSValue::JSValue(JSFalseTag)
{
- return JSImmediate::undefinedImmediate();
+ *this = JSImmediate::falseImmediate();
}
- 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
+ inline bool JSValue::isUndefinedOrNull() const
{
- return asValue() == jsUndefined();
+ return JSImmediate::isUndefinedOrNull(asValue());
}
- inline bool JSValuePtr::isNull() const
+ inline bool JSValue::isBoolean() const
{
- return asValue() == jsNull();
+ return JSImmediate::isBoolean(asValue());
}
- inline bool JSValuePtr::isUndefinedOrNull() const
+ inline bool JSValue::isTrue() const
{
- return JSImmediate::isUndefinedOrNull(asValue());
+ return asValue() == JSImmediate::trueImmediate();
}
- inline bool JSValuePtr::isBoolean() const
+ inline bool JSValue::isFalse() const
{
- return JSImmediate::isBoolean(asValue());
+ return asValue() == JSImmediate::falseImmediate();
}
- inline bool JSValuePtr::getBoolean(bool& v) const
+ inline bool JSValue::getBoolean(bool& v) const
{
if (JSImmediate::isBoolean(asValue())) {
v = JSImmediate::toBoolean(asValue());
return false;
}
- inline bool JSValuePtr::getBoolean() const
+ inline bool JSValue::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
+ inline bool JSValue::isCell() const
{
return !JSImmediate::isImmediate(asValue());
}
- inline bool JSValuePtr::isInt32Fast() const
+ inline bool JSValue::isInt32() const
{
return JSImmediate::isIntegerNumber(asValue());
}
- inline int32_t JSValuePtr::getInt32Fast() const
+ inline int32_t JSValue::asInt32() const
{
- ASSERT(isInt32Fast());
+ ASSERT(isInt32());
return JSImmediate::getTruncatedInt32(asValue());
}
- inline bool JSValuePtr::isUInt32Fast() const
+ inline bool JSValue::isUInt32() const
{
return JSImmediate::isPositiveIntegerNumber(asValue());
}
- inline uint32_t JSValuePtr::getUInt32Fast() const
+ inline uint32_t JSValue::asUInt32() const
{
- ASSERT(isUInt32Fast());
+ ASSERT(isUInt32());
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)
+ static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2)
{
return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
}
- static ALWAYS_INLINE JSValuePtr equal(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE JSValue equal(JSValue v1, JSValue v2)
{
ASSERT(canDoFastBitwiseOperations(v1, v2));
return jsBoolean(v1 == v2);
}
- static ALWAYS_INLINE JSValuePtr notEqual(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE JSValue notEqual(JSValue v1, JSValue v2)
{
ASSERT(canDoFastBitwiseOperations(v1, v2));
return jsBoolean(v1 != v2);
}
- static ALWAYS_INLINE JSValuePtr andImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE JSValue andImmediateNumbers(JSValue v1, JSValue v2)
{
ASSERT(canDoFastBitwiseOperations(v1, v2));
return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
}
- static ALWAYS_INLINE JSValuePtr xorImmediateNumbers(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE JSValue xorImmediateNumbers(JSValue v1, JSValue 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)
+ static ALWAYS_INLINE JSValue orImmediateNumbers(JSValue v1, JSValue v2)
{
ASSERT(canDoFastBitwiseOperations(v1, v2));
return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
}
- static ALWAYS_INLINE bool canDoFastRshift(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE bool canDoFastRshift(JSValue v1, JSValue v2)
{
return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
}
- static ALWAYS_INLINE bool canDoFastUrshift(JSValuePtr v1, JSValuePtr v2)
+ static ALWAYS_INLINE bool canDoFastUrshift(JSValue v1, JSValue v2)
{
return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
}
- static ALWAYS_INLINE JSValuePtr rightShiftImmediateNumbers(JSValuePtr val, JSValuePtr shift)
+ static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift)
{
ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
-#if USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE64)
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)
+ static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue 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)
+ static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v1, JSValue 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)
+ static ALWAYS_INLINE JSValue addImmediateNumbers(JSValue v1, JSValue 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)
+ static ALWAYS_INLINE JSValue subImmediateNumbers(JSValue v1, JSValue v2)
{
ASSERT(canDoFastAdditiveOperations(v1, v2));
return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
}
- static ALWAYS_INLINE JSValuePtr incImmediateNumber(JSValuePtr v)
+ static ALWAYS_INLINE JSValue incImmediateNumber(JSValue v)
{
ASSERT(canDoFastAdditiveOperations(v));
return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
}
- static ALWAYS_INLINE JSValuePtr decImmediateNumber(JSValuePtr v)
+ static ALWAYS_INLINE JSValue decImmediateNumber(JSValue v)
{
ASSERT(canDoFastAdditiveOperations(v));
return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
} // namespace JSC
+#endif // !USE(JSVALUE32_64)
+
#endif // JSImmediate_h
ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
// JSValue methods
-JSValuePtr JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
+JSValue 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&)
+bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue&)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
return false;
return false;
}
-void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValuePtr, PutPropertySlot&)
+void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
}
-void JSNotAnObject::put(ExecState* exec, unsigned, JSValuePtr)
+void JSNotAnObject::put(ExecState* exec, unsigned, JSValue)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
}
{
}
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
private:
// JSValue methods
- virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr&);
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
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 void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
#include "config.h"
#include "JSNumberCell.h"
+#if USE(JSVALUE32)
+
#include "NumberObject.h"
#include "UString.h"
namespace JSC {
-#if !USE(ALTERNATE_JSIMMEDIATE)
-
-JSValuePtr JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
return const_cast<JSNumberCell*>(this);
}
-bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
{
number = m_value;
value = this;
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()
+JSValue JSNumberCell::getJSNumber()
{
return this;
}
-JSValuePtr jsNumberCell(ExecState* exec, double d)
+JSValue jsNumberCell(ExecState* exec, double d)
{
return new (exec) JSNumberCell(exec, d);
}
-JSValuePtr jsNumberCell(JSGlobalData* globalData, double d)
+JSValue jsNumberCell(JSGlobalData* globalData, double d)
{
return new (globalData) JSNumberCell(globalData, d);
}
-#else
+} // namespace JSC
-JSValuePtr jsNumberCell(ExecState*, double)
+#else // USE(JSVALUE32)
+
+// Keep our exported symbols lists happy.
+namespace JSC {
+
+JSValue jsNumberCell(ExecState*, double);
+
+JSValue jsNumberCell(ExecState*, double)
{
ASSERT_NOT_REACHED();
- return noValue();
+ return JSValue();
}
-#endif
-
} // namespace JSC
+
+#endif // USE(JSVALUE32)
extern const double NaN;
extern const double Inf;
- JSValuePtr jsNumberCell(ExecState*, double);
-
-#if !USE(ALTERNATE_JSIMMEDIATE)
+#if USE(JSVALUE32)
+ JSValue jsNumberCell(ExecState*, double);
class Identifier;
class JSCell;
class JSNumberCell : public JSCell {
friend class JIT;
- friend JSValuePtr jsNumberCell(JSGlobalData*, double);
- friend JSValuePtr jsNumberCell(ExecState*, double);
+ friend JSValue jsNumberCell(JSGlobalData*, double);
+ friend JSValue 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 JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual UString toThisString(ExecState*) const;
virtual JSObject* toThisObject(ExecState*) const;
- virtual JSValuePtr getJSNumber();
+ virtual JSValue getJSNumber();
void* operator new(size_t size, ExecState* exec)
{
#endif
}
- static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
private:
JSNumberCell(JSGlobalData* globalData, double 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);
+ JSValue jsNumberCell(JSGlobalData*, double);
- inline bool isNumberCell(JSValuePtr v)
+ inline bool isNumberCell(JSValue v)
{
return v.isCell() && v.asCell()->isNumber();
}
- inline JSNumberCell* asNumberCell(JSValuePtr v)
+ inline JSNumberCell* asNumberCell(JSValue 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)
+ inline JSValue::JSValue(ExecState* exec, double d)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(exec, i);
+ JSValue v = JSImmediate::from(d);
+ *this = v ? v : jsNumberCell(exec, d);
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, long long i)
+ inline JSValue::JSValue(ExecState* exec, int i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState* exec, unsigned long long i)
+ inline JSValue::JSValue(ExecState* exec, unsigned i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, double d)
+ inline JSValue::JSValue(ExecState* exec, long i)
{
- JSValuePtr v = JSImmediate::from(d);
- return v ? v : jsNumberCell(globalData, d);
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, int i)
+ inline JSValue::JSValue(ExecState* exec, unsigned long i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, i);
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned i)
+ inline JSValue::JSValue(ExecState* exec, long long i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, i);
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long i)
+ inline JSValue::JSValue(ExecState* exec, unsigned long long i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, i);
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long i)
+ inline JSValue::JSValue(JSGlobalData* globalData, double d)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, i);
+ JSValue v = JSImmediate::from(d);
+ *this = v ? v : jsNumberCell(globalData, d);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, long long i)
+ inline JSValue::JSValue(JSGlobalData* globalData, int i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(globalData, i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData* globalData, unsigned long long i)
+ inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
{
- JSValuePtr v = JSImmediate::from(i);
- return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ JSValue v = JSImmediate::from(i);
+ *this = v ? v : jsNumberCell(globalData, i);
}
- inline bool JSValuePtr::isDoubleNumber() const
+ inline bool JSValue::isDouble() const
{
return isNumberCell(asValue());
}
- inline double JSValuePtr::getDoubleNumber() const
+ inline double JSValue::asDouble() const
{
return asNumberCell(asValue())->value();
}
- inline bool JSValuePtr::isNumber() const
+ inline bool JSValue::isNumber() const
{
- return JSImmediate::isNumber(asValue()) || isDoubleNumber();
+ return JSImmediate::isNumber(asValue()) || isDouble();
}
- inline double JSValuePtr::uncheckedGetNumber() const
+ inline double JSValue::uncheckedGetNumber() const
{
ASSERT(isNumber());
- return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber();
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble();
}
-#else
+#endif // USE(JSVALUE32)
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, double d)
+#if USE(JSVALUE64)
+ inline JSValue::JSValue(ExecState*, double d)
{
- JSValuePtr v = JSImmediate::from(d);
+ JSValue v = JSImmediate::from(d);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, int i)
+ inline JSValue::JSValue(ExecState*, int i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned i)
+ inline JSValue::JSValue(ExecState*, unsigned i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long i)
+ inline JSValue::JSValue(ExecState*, long i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long i)
+ inline JSValue::JSValue(ExecState*, unsigned long i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, long long i)
+ inline JSValue::JSValue(ExecState*, long long i)
{
- JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ JSValue v = JSImmediate::from(static_cast<double>(i));
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned long long i)
+ inline JSValue::JSValue(ExecState*, unsigned long long i)
{
- JSValuePtr v = JSImmediate::from(static_cast<double>(i));
+ JSValue v = JSImmediate::from(static_cast<double>(i));
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, double d)
+ inline JSValue::JSValue(JSGlobalData*, double d)
{
- JSValuePtr v = JSImmediate::from(d);
+ JSValue v = JSImmediate::from(d);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, int i)
+ inline JSValue::JSValue(JSGlobalData*, int i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned i)
+ inline JSValue::JSValue(JSGlobalData*, unsigned i)
{
- JSValuePtr v = JSImmediate::from(i);
+ JSValue v = JSImmediate::from(i);
ASSERT(v);
- return v;
+ *this = v;
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, long i)
+ inline bool JSValue::isDouble() const
{
- JSValuePtr v = JSImmediate::from(i);
- ASSERT(v);
- return v;
+ return JSImmediate::isDouble(asValue());
}
- 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
+ inline double JSValue::asDouble() const
{
return JSImmediate::doubleValue(asValue());
}
- inline bool JSValuePtr::isNumber() const
+ inline bool JSValue::isNumber() const
{
return JSImmediate::isNumber(asValue());
}
- inline double JSValuePtr::uncheckedGetNumber() const
+ inline double JSValue::uncheckedGetNumber() const
{
ASSERT(isNumber());
return JSImmediate::toDouble(asValue());
}
-#endif
+#endif // USE(JSVALUE64)
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, char i)
- {
- ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
- }
+#if USE(JSVALUE32) || USE(JSVALUE64)
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned char i)
+ inline JSValue::JSValue(ExecState*, char i)
{
ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
+ *this = JSImmediate::from(i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, short i)
+ inline JSValue::JSValue(ExecState*, unsigned char i)
{
ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
+ *this = JSImmediate::from(i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(ExecState*, unsigned short i)
+ inline JSValue::JSValue(ExecState*, short i)
{
ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
+ *this = JSImmediate::from(i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, short i)
+ inline JSValue::JSValue(ExecState*, unsigned short i)
{
ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
+ *this = JSImmediate::from(i);
}
- ALWAYS_INLINE JSValuePtr jsNumber(JSGlobalData*, unsigned short i)
- {
- ASSERT(JSImmediate::from(i));
- return JSImmediate::from(i);
- }
-
- inline JSValuePtr jsNaN(ExecState* exec)
+ inline JSValue jsNaN(ExecState* exec)
{
return jsNumber(exec, NaN);
}
- inline JSValuePtr jsNaN(JSGlobalData* globalData)
+ inline JSValue jsNaN(JSGlobalData* globalData)
{
return jsNumber(globalData, NaN);
}
// --- JSValue inlines ----------------------------
- ALWAYS_INLINE JSValuePtr JSValuePtr::toJSNumber(ExecState* exec) const
+ ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
{
return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
}
- inline bool JSValuePtr::getNumber(double &result) const
+ inline bool JSValue::getNumber(double &result) const
{
- if (isInt32Fast())
- result = getInt32Fast();
- else if (LIKELY(isDoubleNumber()))
- result = getDoubleNumber();
+ if (isInt32())
+ result = asInt32();
+ else if (LIKELY(isDouble()))
+ result = asDouble();
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;
- }
+#endif // USE(JSVALUE32) || USE(JSVALUE64)
} // namespace JSC
--- /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 "JSONObject.h"
+
+#include "BooleanObject.h"
+#include "Error.h"
+#include "ExceptionHelpers.h"
+#include "JSArray.h"
+#include "LiteralParser.h"
+#include "PropertyNameArray.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSONObject);
+
+static JSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*, JSObject*, JSValue, const ArgList&);
+
+}
+
+#include "JSONObject.lut.h"
+
+namespace JSC {
+
+// PropertyNameForFunctionCall objects must be on the stack, since the JSValue that they create is not marked.
+class PropertyNameForFunctionCall {
+public:
+ PropertyNameForFunctionCall(const Identifier&);
+ PropertyNameForFunctionCall(unsigned);
+
+ JSValue value(ExecState*) const;
+
+private:
+ const Identifier* m_identifier;
+ unsigned m_number;
+ mutable JSValue m_value;
+};
+
+class Stringifier : Noncopyable {
+public:
+ Stringifier(ExecState*, JSValue replacer, JSValue space);
+ ~Stringifier();
+ JSValue stringify(JSValue);
+
+ void mark();
+
+private:
+ typedef UString StringBuilder;
+
+ class Holder {
+ public:
+ Holder(JSObject*);
+
+ JSObject* object() const { return m_object; }
+
+ bool appendNextProperty(Stringifier&, StringBuilder&);
+
+ private:
+ JSObject* const m_object;
+ const bool m_isArray;
+ bool m_isJSArray;
+ unsigned m_index;
+ unsigned m_size;
+ RefPtr<PropertyNameArrayData> m_propertyNames;
+ };
+
+ friend class Holder;
+
+ static void appendQuotedString(StringBuilder&, const UString&);
+
+ JSValue toJSON(JSValue, const PropertyNameForFunctionCall&);
+
+ enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedValue };
+ StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&);
+
+ bool willIndent() const;
+ void indent();
+ void unindent();
+ void startNewLine(StringBuilder&) const;
+
+ Stringifier* const m_nextStringifierToMark;
+ ExecState* const m_exec;
+ const JSValue m_replacer;
+ bool m_usingArrayReplacer;
+ PropertyNameArray m_arrayReplacerPropertyNames;
+ CallType m_replacerCallType;
+ CallData m_replacerCallData;
+ const UString m_gap;
+
+ HashSet<JSObject*> m_holderCycleDetector;
+ Vector<Holder, 16> m_holderStack;
+ UString m_repeatedGap;
+ UString m_indent;
+};
+
+// ------------------------------ helper functions --------------------------------
+
+static inline JSValue unwrapBoxedPrimitive(JSValue value)
+{
+ if (!value.isObject())
+ return value;
+ if (!asObject(value)->inherits(&NumberObject::info) && !asObject(value)->inherits(&StringObject::info) && !asObject(value)->inherits(&BooleanObject::info))
+ return value;
+ return static_cast<JSWrapperObject*>(asObject(value))->internalValue();
+}
+
+static inline UString gap(JSValue space)
+{
+ space = unwrapBoxedPrimitive(space);
+
+ // If the space value is a number, create a gap string with that number of spaces.
+ double spaceCount;
+ if (space.getNumber(spaceCount)) {
+ const int maxSpaceCount = 100;
+ int count;
+ if (spaceCount > maxSpaceCount)
+ count = maxSpaceCount;
+ else if (!(spaceCount > 0))
+ count = 0;
+ else
+ count = static_cast<int>(spaceCount);
+ UChar spaces[maxSpaceCount];
+ for (int i = 0; i < count; ++i)
+ spaces[i] = ' ';
+ return UString(spaces, count);
+ }
+
+ // If the space value is a string, use it as the gap string, otherwise use no gap string.
+ return space.getString();
+}
+
+// ------------------------------ PropertyNameForFunctionCall --------------------------------
+
+inline PropertyNameForFunctionCall::PropertyNameForFunctionCall(const Identifier& identifier)
+ : m_identifier(&identifier)
+{
+}
+
+inline PropertyNameForFunctionCall::PropertyNameForFunctionCall(unsigned number)
+ : m_identifier(0)
+ , m_number(number)
+{
+}
+
+JSValue PropertyNameForFunctionCall::value(ExecState* exec) const
+{
+ if (!m_value) {
+ if (m_identifier)
+ m_value = jsString(exec, m_identifier->ustring());
+ else
+ m_value = jsNumber(exec, m_number);
+ }
+ return m_value;
+}
+
+// ------------------------------ Stringifier --------------------------------
+
+Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
+ : m_nextStringifierToMark(exec->globalData().firstStringifierToMark)
+ , m_exec(exec)
+ , m_replacer(replacer)
+ , m_usingArrayReplacer(false)
+ , m_arrayReplacerPropertyNames(exec)
+ , m_replacerCallType(CallTypeNone)
+ , m_gap(gap(space))
+{
+ exec->globalData().firstStringifierToMark = this;
+
+ if (!m_replacer.isObject())
+ return;
+
+ if (asObject(m_replacer)->inherits(&JSArray::info)) {
+ m_usingArrayReplacer = true;
+ JSObject* array = asObject(m_replacer);
+ unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
+ for (unsigned i = 0; i < length; ++i) {
+ JSValue name = array->get(exec, i);
+ if (exec->hadException())
+ break;
+ UString propertyName;
+ if (!name.getString(propertyName))
+ continue;
+ if (exec->hadException())
+ return;
+ m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
+ }
+ return;
+ }
+
+ m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData);
+}
+
+Stringifier::~Stringifier()
+{
+ ASSERT(m_exec->globalData().firstStringifierToMark == this);
+ m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
+}
+
+void Stringifier::mark()
+{
+ for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
+ size_t size = m_holderStack.size();
+ for (size_t i = 0; i < size; ++i) {
+ JSObject* object = m_holderStack[i].object();
+ if (!object->marked())
+ object->mark();
+ }
+ }
+}
+
+JSValue Stringifier::stringify(JSValue value)
+{
+ JSObject* object = constructEmptyObject(m_exec);
+ if (m_exec->hadException())
+ return jsNull();
+
+ PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier);
+ object->putDirect(m_exec->globalData().propertyNames->emptyIdentifier, value);
+
+ StringBuilder result;
+ if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded)
+ return jsUndefined();
+ if (m_exec->hadException())
+ return jsNull();
+
+ return jsString(m_exec, result);
+}
+
+void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value)
+{
+ int length = value.size();
+
+ // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters.
+ builder.reserveCapacity(builder.size() + length + 2 + 8);
+
+ builder.append('"');
+
+ const UChar* data = value.data();
+ for (int i = 0; i < length; ++i) {
+ int start = i;
+ while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\'))
+ ++i;
+ builder.append(data + start, i - start);
+ if (i >= length)
+ break;
+ switch (data[i]) {
+ case '\t':
+ builder.append('\\');
+ builder.append('t');
+ break;
+ case '\r':
+ builder.append('\\');
+ builder.append('r');
+ break;
+ case '\n':
+ builder.append('\\');
+ builder.append('n');
+ break;
+ case '\f':
+ builder.append('\\');
+ builder.append('f');
+ break;
+ case '\b':
+ builder.append('\\');
+ builder.append('b');
+ break;
+ case '"':
+ builder.append('\\');
+ builder.append('"');
+ break;
+ case '\\':
+ builder.append('\\');
+ builder.append('\\');
+ break;
+ default:
+ static const char hexDigits[] = "0123456789abcdef";
+ UChar ch = data[i];
+ UChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
+ builder.append(hex, sizeof(hex) / sizeof(UChar));
+ break;
+ }
+ }
+
+ builder.append('"');
+}
+
+inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionCall& propertyName)
+{
+ ASSERT(!m_exec->hadException());
+ if (!value.isObject() || !asObject(value)->hasProperty(m_exec, m_exec->globalData().propertyNames->toJSON))
+ return value;
+
+ JSValue toJSONFunction = asObject(value)->get(m_exec, m_exec->globalData().propertyNames->toJSON);
+ if (m_exec->hadException())
+ return jsNull();
+
+ if (!toJSONFunction.isObject())
+ return value;
+
+ JSObject* object = asObject(toJSONFunction);
+ CallData callData;
+ CallType callType = object->getCallData(callData);
+ if (callType == CallTypeNone)
+ return value;
+
+ JSValue list[] = { propertyName.value(m_exec) };
+ ArgList args(list, sizeof(list) / sizeof(JSValue));
+ return call(m_exec, object, callType, callData, value, args);
+}
+
+Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName)
+{
+ // Call the toJSON function.
+ value = toJSON(value, propertyName);
+ if (m_exec->hadException())
+ return StringifyFailed;
+ if (value.isUndefined() && !holder->inherits(&JSArray::info))
+ return StringifyFailedDueToUndefinedValue;
+
+ // Call the replacer function.
+ if (m_replacerCallType != CallTypeNone) {
+ JSValue list[] = { propertyName.value(m_exec), value };
+ ArgList args(list, sizeof(list) / sizeof(JSValue));
+ value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder, args);
+ if (m_exec->hadException())
+ return StringifyFailed;
+ }
+
+ if (value.isNull()) {
+ builder.append("null");
+ return StringifySucceeded;
+ }
+
+ value = unwrapBoxedPrimitive(value);
+
+ if (value.isBoolean()) {
+ builder.append(value.getBoolean() ? "true" : "false");
+ return StringifySucceeded;
+ }
+
+ UString stringValue;
+ if (value.getString(stringValue)) {
+ appendQuotedString(builder, stringValue);
+ return StringifySucceeded;
+ }
+
+ double numericValue;
+ if (value.getNumber(numericValue)) {
+ if (!isfinite(numericValue))
+ builder.append("null");
+ else
+ builder.append(UString::from(numericValue));
+ return StringifySucceeded;
+ }
+
+ if (!value.isObject())
+ return StringifyFailed;
+
+ JSObject* object = asObject(value);
+
+ // Handle cycle detection, and put the holder on the stack.
+ if (!m_holderCycleDetector.add(object).second) {
+ throwError(m_exec, TypeError);
+ return StringifyFailed;
+ }
+ bool holderStackWasEmpty = m_holderStack.isEmpty();
+ m_holderStack.append(object);
+ if (!holderStackWasEmpty)
+ return StringifySucceeded;
+
+ // If this is the outermost call, then loop to handle everything on the holder stack.
+ TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker);
+ localTimeoutChecker.reset();
+ unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck();
+ do {
+ while (m_holderStack.last().appendNextProperty(*this, builder)) {
+ if (m_exec->hadException())
+ return StringifyFailed;
+ if (!--tickCount) {
+ if (localTimeoutChecker.didTimeOut(m_exec)) {
+ m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+ return StringifyFailed;
+ }
+ tickCount = localTimeoutChecker.ticksUntilNextCheck();
+ }
+ }
+ m_holderCycleDetector.remove(m_holderStack.last().object());
+ m_holderStack.removeLast();
+ } while (!m_holderStack.isEmpty());
+ return StringifySucceeded;
+}
+
+inline bool Stringifier::willIndent() const
+{
+ return !m_gap.isEmpty();
+}
+
+inline void Stringifier::indent()
+{
+ // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent.
+ int newSize = m_indent.size() + m_gap.size();
+ if (newSize > m_repeatedGap.size())
+ m_repeatedGap.append(m_gap);
+ ASSERT(newSize <= m_repeatedGap.size());
+ m_indent = m_repeatedGap.substr(0, newSize);
+}
+
+inline void Stringifier::unindent()
+{
+ ASSERT(m_indent.size() >= m_gap.size());
+ m_indent = m_repeatedGap.substr(0, m_indent.size() - m_gap.size());
+}
+
+inline void Stringifier::startNewLine(StringBuilder& builder) const
+{
+ if (m_gap.isEmpty())
+ return;
+ builder.append('\n');
+ builder.append(m_indent);
+}
+
+inline Stringifier::Holder::Holder(JSObject* object)
+ : m_object(object)
+ , m_isArray(object->inherits(&JSArray::info))
+ , m_index(0)
+{
+}
+
+bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder)
+{
+ ASSERT(m_index <= m_size);
+
+ ExecState* exec = stringifier.m_exec;
+
+ // First time through, initialize.
+ if (!m_index) {
+ if (m_isArray) {
+ m_isJSArray = isJSArray(&exec->globalData(), m_object);
+ m_size = m_object->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
+ builder.append('[');
+ } else {
+ if (stringifier.m_usingArrayReplacer)
+ m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
+ else {
+ PropertyNameArray objectPropertyNames(exec);
+ m_object->getPropertyNames(exec, objectPropertyNames);
+ m_propertyNames = objectPropertyNames.releaseData();
+ }
+ m_size = m_propertyNames->propertyNameVector().size();
+ builder.append('{');
+ }
+ stringifier.indent();
+ }
+
+ // Last time through, finish up and return false.
+ if (m_index == m_size) {
+ stringifier.unindent();
+ if (m_size && builder[builder.size() - 1] != '{')
+ stringifier.startNewLine(builder);
+ builder.append(m_isArray ? ']' : '}');
+ return false;
+ }
+
+ // Handle a single element of the array or object.
+ unsigned index = m_index++;
+ unsigned rollBackPoint = 0;
+ StringifyResult stringifyResult;
+ if (m_isArray) {
+ // Get the value.
+ JSValue value;
+ if (m_isJSArray && asArray(m_object)->canGetIndex(index))
+ value = asArray(m_object)->getIndex(index);
+ else {
+ PropertySlot slot(m_object);
+ if (!m_object->getOwnPropertySlot(exec, index, slot))
+ slot.setUndefined();
+ if (exec->hadException())
+ return false;
+ value = slot.getValue(exec, index);
+ }
+
+ // Append the separator string.
+ if (index)
+ builder.append(',');
+ stringifier.startNewLine(builder);
+
+ // Append the stringified value.
+ stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, index);
+ } else {
+ // Get the value.
+ PropertySlot slot(m_object);
+ Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
+ if (!m_object->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ JSValue value = slot.getValue(exec, propertyName);
+ if (exec->hadException())
+ return false;
+
+ rollBackPoint = builder.size();
+
+ // Append the separator string.
+ if (builder[rollBackPoint - 1] != '{')
+ builder.append(',');
+ stringifier.startNewLine(builder);
+
+ // Append the property name.
+ appendQuotedString(builder, propertyName.ustring());
+ builder.append(':');
+ if (stringifier.willIndent())
+ builder.append(' ');
+
+ // Append the stringified value.
+ stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, propertyName);
+ }
+
+ // From this point on, no access to the this pointer or to any members, because the
+ // Holder object may have moved if the call to stringify pushed a new Holder onto
+ // m_holderStack.
+
+ switch (stringifyResult) {
+ case StringifyFailed:
+ builder.append("null");
+ break;
+ case StringifySucceeded:
+ break;
+ case StringifyFailedDueToUndefinedValue:
+ // This only occurs when get an undefined value for an object property.
+ // In this case we don't want the separator and property name that we
+ // already appended, so roll back.
+ builder = builder.substr(0, rollBackPoint);
+ break;
+ }
+
+ return true;
+}
+
+// ------------------------------ JSONObject --------------------------------
+
+const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable };
+
+/* Source for JSONObject.lut.h
+@begin jsonTable
+ parse JSONProtoFuncParse DontEnum|Function 1
+ stringify JSONProtoFuncStringify DontEnum|Function 1
+@end
+*/
+
+// ECMA 15.8
+
+bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ const HashEntry* entry = ExecState::jsonTable(exec)->entry(exec, propertyName);
+ if (!entry)
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+
+ ASSERT(entry->attributes() & Function);
+ setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
+ return true;
+}
+
+void JSONObject::markStringifiers(Stringifier* stringifier)
+{
+ stringifier->mark();
+}
+
+class Walker {
+public:
+ Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData)
+ : m_exec(exec)
+ , m_function(function)
+ , m_callType(callType)
+ , m_callData(callData)
+ {
+ }
+ JSValue walk(JSValue unfiltered);
+private:
+ JSValue callReviver(JSValue property, JSValue unfiltered)
+ {
+ JSValue args[] = { property, unfiltered };
+ ArgList argList(args, 2);
+ return call(m_exec, m_function, m_callType, m_callData, jsNull(), argList);
+ }
+
+ friend class Holder;
+
+ ExecState* m_exec;
+ JSObject* m_function;
+ CallType m_callType;
+ CallData m_callData;
+};
+
+enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
+ ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
+NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
+{
+ Vector<PropertyNameArray, 16> propertyStack;
+ Vector<uint32_t, 16> indexStack;
+ Vector<JSObject*, 16> objectStack;
+ Vector<JSArray*, 16> arrayStack;
+
+ Vector<WalkerState, 16> stateStack;
+ WalkerState state = StateUnknown;
+ JSValue inValue = unfiltered;
+ JSValue outValue = jsNull();
+ while (1) {
+ switch (state) {
+ arrayStartState:
+ case ArrayStartState: {
+ ASSERT(inValue.isObject());
+ ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)));
+ JSArray* array = asArray(inValue);
+ arrayStack.append(array);
+ indexStack.append(0);
+ // fallthrough
+ }
+ arrayStartVisitMember:
+ case ArrayStartVisitMember: {
+ JSArray* array = arrayStack.last();
+ uint32_t index = indexStack.last();
+ if (index == array->length()) {
+ outValue = array;
+ arrayStack.removeLast();
+ indexStack.removeLast();
+ break;
+ }
+ inValue = array->getIndex(index);
+ if (inValue.isObject()) {
+ stateStack.append(ArrayEndVisitMember);
+ goto stateUnknown;
+ } else
+ outValue = inValue;
+ // fallthrough
+ }
+ case ArrayEndVisitMember: {
+ JSArray* array = arrayStack.last();
+ array->setIndex(indexStack.last(), callReviver(jsString(m_exec, UString::from(indexStack.last())), outValue));
+ if (m_exec->hadException())
+ return jsNull();
+ indexStack.last()++;
+ goto arrayStartVisitMember;
+ }
+ objectStartState:
+ case ObjectStartState: {
+ ASSERT(inValue.isObject());
+ ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)));
+ JSObject* object = asObject(inValue);
+ objectStack.append(object);
+ indexStack.append(0);
+ propertyStack.append(PropertyNameArray(m_exec));
+ object->getPropertyNames(m_exec, propertyStack.last());
+ // fallthrough
+ }
+ objectStartVisitMember:
+ case ObjectStartVisitMember: {
+ JSObject* object = objectStack.last();
+ uint32_t index = indexStack.last();
+ PropertyNameArray& properties = propertyStack.last();
+ if (index == properties.size()) {
+ outValue = object;
+ objectStack.removeLast();
+ indexStack.removeLast();
+ propertyStack.removeLast();
+ break;
+ }
+ PropertySlot slot;
+ object->getOwnPropertySlot(m_exec, properties[index], slot);
+ inValue = slot.getValue(m_exec, properties[index]);
+ ASSERT(!m_exec->hadException());
+ if (inValue.isObject()) {
+ stateStack.append(ObjectEndVisitMember);
+ goto stateUnknown;
+ } else
+ outValue = inValue;
+ // fallthrough
+ }
+ case ObjectEndVisitMember: {
+ JSObject* object = objectStack.last();
+ Identifier prop = propertyStack.last()[indexStack.last()];
+ PutPropertySlot slot;
+ object->put(m_exec, prop, callReviver(jsString(m_exec, prop.ustring()), outValue), slot);
+ if (m_exec->hadException())
+ return jsNull();
+ indexStack.last()++;
+ goto objectStartVisitMember;
+ }
+ stateUnknown:
+ case StateUnknown:
+ if (!inValue.isObject()) {
+ outValue = inValue;
+ break;
+ }
+ if (isJSArray(&m_exec->globalData(), asObject(inValue)))
+ goto arrayStartState;
+ goto objectStartState;
+ }
+ if (stateStack.isEmpty())
+ break;
+ state = stateStack.last();
+ stateStack.removeLast();
+ }
+ return callReviver(jsEmptyString(m_exec), outValue);
+}
+
+// ECMA-262 v5 15.12.2
+JSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (args.isEmpty())
+ return throwError(exec, GeneralError, "JSON.parse requires at least one parameter");
+ JSValue value = args.at(0);
+ UString source = value.toString(exec);
+ if (exec->hadException())
+ return jsNull();
+
+ LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON);
+ JSValue unfiltered = jsonParser.tryLiteralParse();
+ if (!unfiltered)
+ return throwError(exec, SyntaxError, "Unable to parse JSON string");
+
+ if (args.size() < 2)
+ return unfiltered;
+
+ JSValue function = args.at(1);
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone)
+ return unfiltered;
+ return Walker(exec, asObject(function), callType, callData).walk(unfiltered);
+}
+
+// ECMA-262 v5 15.12.3
+JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (args.isEmpty())
+ return throwError(exec, GeneralError, "No input to stringify");
+ JSValue value = args.at(0);
+ JSValue replacer = args.at(1);
+ JSValue space = args.at(2);
+ return Stringifier(exec, replacer, space).stringify(value);
+}
+
+} // namespace JSC
--- /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 JSONObject_h
+#define JSONObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class Stringifier;
+
+ class JSONObject : public JSObject {
+ public:
+ JSONObject(PassRefPtr<Structure> structure)
+ : JSObject(structure)
+ {
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType));
+ }
+
+ static void markStringifiers(Stringifier*);
+
+ private:
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // JSONObject_h
JSCell::mark();
m_structure->mark();
+ PropertyStorage storage = propertyStorage();
+
size_t storageSize = m_structure->propertyStorageSize();
for (size_t i = 0; i < storageSize; ++i) {
- JSValuePtr v = m_propertyStorage[i];
+ JSValue v = JSValue::decode(storage[i]);
if (!v.marked())
v.mark();
}
}
// ECMA 8.6.2.2
-void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(value);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
if (!value.isObject() && !value.isNull())
return;
- JSValuePtr nextPrototypeValue = value;
+ JSValue nextPrototypeValue = value;
while (nextPrototypeValue && nextPrototypeValue.isObject()) {
JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
if (nextPrototype == this) {
}
// Check if there are any setters or getters in the prototype chain
- JSValuePtr prototype;
+ JSValue prototype;
for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
prototype = obj->prototype();
if (prototype.isNull()) {
- putDirect(propertyName, value, 0, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
return;
}
}
unsigned attributes;
- if ((m_structure->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
+ JSCell* specificValue;
+ if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly)
return;
for (JSObject* obj = this; ; obj = asObject(prototype)) {
- if (JSValuePtr gs = obj->getDirect(propertyName)) {
+ if (JSValue gs = obj->getDirect(propertyName)) {
if (gs.isGetterSetter()) {
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
CallData callData;
CallType callType = setterFunc->getCallData(callData);
- ArgList args;
+ MarkedArgumentBuffer args;
args.append(value);
call(exec, setterFunc, callType, callData, this, args);
return;
break;
}
- putDirect(propertyName, value, 0, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
return;
}
-void JSObject::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value)
{
PutPropertySlot slot;
put(exec, Identifier::from(exec, propertyName), value, slot);
}
-void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
{
- putDirect(propertyName, value, attributes);
+ putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot);
}
-void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValuePtr value, unsigned attributes)
+void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+ putDirectInternal(exec->globalData(), propertyName, value, attributes);
+}
+
+void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes)
{
putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
}
bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
unsigned attributes;
- if (m_structure->get(propertyName, attributes) != WTF::notFound) {
+ JSCell* specificValue;
+ if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) {
if ((attributes & DontDelete))
return false;
removeDirect(propertyName);
return deleteProperty(exec, Identifier::from(exec, propertyName));
}
-static ALWAYS_INLINE JSValuePtr callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
+static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
{
- JSValuePtr function = object->get(exec, propertyName);
+ JSValue function = object->get(exec, propertyName);
CallData callData;
CallType callType = function.getCallData(callData);
if (callType == CallTypeNone)
if (exec->hadException())
return exec->exception();
- JSValuePtr result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
+ JSValue 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 JSValue();
return result;
}
-bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValuePtr& result)
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
{
result = defaultValue(exec, PreferNumber);
number = result.toNumber(exec);
}
// ECMA 8.6.2.6
-JSValuePtr JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+JSValue 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);
+ JSValue 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);
+ JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
if (value)
return value;
value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
{
- JSValuePtr object = getDirect(propertyName);
+ JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
ASSERT(m_structure->hasGetterSetterProperties());
asGetterSetter(object)->setGetter(getterFunction);
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter;
- putDirect(propertyName, getterSetter, None, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, 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
void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
{
- JSValuePtr object = getDirect(propertyName);
+ JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
ASSERT(m_structure->hasGetterSetterProperties());
asGetterSetter(object)->setSetter(setterFunction);
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter;
- putDirect(propertyName, getterSetter, None, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, 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
getterSetter->setSetter(setterFunction);
}
-JSValuePtr JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
{
JSObject* object = this;
while (true) {
- if (JSValuePtr value = object->getDirect(propertyName)) {
+ if (JSValue value = object->getDirect(propertyName)) {
if (!value.isGetterSetter())
return jsUndefined();
JSObject* functionObject = asGetterSetter(value)->getter();
}
}
-JSValuePtr JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
{
JSObject* object = this;
while (true) {
- if (JSValuePtr value = object->getDirect(propertyName)) {
+ if (JSValue value = object->getDirect(propertyName)) {
if (!value.isGetterSetter())
return jsUndefined();
JSObject* functionObject = asGetterSetter(value)->setter();
}
}
-bool JSObject::hasInstance(ExecState* exec, JSValuePtr value, JSValuePtr proto)
+bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
{
+ if (!value.isObject())
+ return false;
+
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)
bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
{
- if (m_structure->get(propertyName, attributes) != WTF::notFound)
+ JSCell* specificValue;
+ if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
return true;
// Look in the static hashtable of properties
return false;
}
+bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
+{
+ unsigned attributes;
+ if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
+ return true;
+
+ // This could be a function within the static table? - should probably
+ // also look in the hash? This currently should not be a problem, since
+ // we've currently always call 'get' first, which should have populated
+ // the normal storage.
+ return false;
+}
+
void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
double JSObject::toNumber(ExecState* exec) const
{
- JSValuePtr primitive = toPrimitive(exec, PreferNumber);
+ JSValue 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);
+ JSValue primitive = toPrimitive(exec, PreferString);
if (exec->hadException())
return "";
return primitive.toString(exec);
void JSObject::removeDirect(const Identifier& propertyName)
{
size_t offset;
- if (m_structure->isDictionary()) {
+ if (m_structure->isUncacheableDictionary()) {
offset = m_structure->removePropertyWithoutTransition(propertyName);
if (offset != WTF::notFound)
- m_propertyStorage[offset] = jsUndefined();
+ putDirectOffset(offset, jsUndefined());
return;
}
RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset);
- if (offset != WTF::notFound)
- m_propertyStorage[offset] = jsUndefined();
setStructure(structure.release());
+ if (offset != WTF::notFound)
+ putDirectOffset(offset, jsUndefined());
}
void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
{
- putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr);
+ putDirectFunction(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);
+ putDirectFunctionWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
}
-NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValuePtr* location)
+NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location)
{
if (JSObject* getterFunction = asGetterSetter(*location)->getter())
slot.setGetterSlot(getterFunction);
#include "PutPropertySlot.h"
#include "ScopeChain.h"
#include "Structure.h"
+#include "JSGlobalData.h"
+#include <wtf/StdLibExtras.h>
namespace JSC {
+ inline JSCell* getJSFunction(JSGlobalData& globalData, JSValue value)
+ {
+ if (value.isCell() && (value.asCell()->vptr() == globalData.jsFunctionVPtr))
+ return value.asCell();
+ return 0;
+ }
+
class InternalFunction;
class PropertyNameArray;
class Structure;
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
+ Getter = 1 << 5, // property is a getter
+ Setter = 1 << 6 // property is a setter
};
- typedef JSValuePtr* PropertyStorage;
+ typedef EncodedJSValue* PropertyStorage;
+ typedef const EncodedJSValue* ConstPropertyStorage;
class JSObject : public JSCell {
friend class BatchedTransitionOptimizer;
bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
- JSValuePtr prototype() const;
- void setPrototype(JSValuePtr prototype);
+ JSValue prototype() const;
+ void setPrototype(JSValue 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;
+ JSValue get(ExecState*, const Identifier& propertyName) const;
+ JSValue 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 put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue value);
- virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes);
- virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValuePtr value, unsigned attributes);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
+ virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue value, unsigned attributes);
bool propertyIsEnumerable(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 JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
- virtual bool hasInstance(ExecState*, JSValuePtr, JSValuePtr prototypeProperty);
+ virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
- virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* unwrappedObject();
virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+ bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
// This get function only looks at the property map.
- JSValuePtr getDirect(const Identifier& propertyName) const
+ JSValue getDirect(const Identifier& propertyName) const
{
size_t offset = m_structure->get(propertyName);
- return offset != WTF::notFound ? m_propertyStorage[offset] : noValue();
+ return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
}
- JSValuePtr* getDirectLocation(const Identifier& propertyName)
+ JSValue* 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)
+ JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
{
- size_t offset = m_structure->get(propertyName, attributes);
+ JSCell* specificFunction;
+ size_t offset = m_structure->get(propertyName, attributes, specificFunction);
return offset != WTF::notFound ? locationForOffset(offset) : 0;
}
- size_t offsetForLocation(JSValuePtr* location)
- {
- return location - m_propertyStorage;
- }
-
- JSValuePtr* locationForOffset(size_t offset)
+ size_t offsetForLocation(JSValue* location) const
{
- return &m_propertyStorage[offset];
+ return location - reinterpret_cast<const JSValue*>(propertyStorage());
}
void transitionTo(Structure*);
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 putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+ void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
+
+ void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
+ void putDirectFunction(const Identifier& propertyName, JSCell* 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 putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0);
+ void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* 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; }
+ JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); }
+ void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); }
- void fillGetterPropertySlot(PropertySlot&, JSValuePtr* location);
+ void fillGetterPropertySlot(PropertySlot&, JSValue* 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 JSValue lookupGetter(ExecState*, const Identifier& propertyName);
+ virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
virtual bool isGlobalObject() const { return false; }
virtual bool isVariableObject() 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; }
+ bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
- static const size_t inlineStorageCapacity = 2;
+ static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
static const size_t nonInlineBaseStorageCapacity = 16;
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
}
- protected:
- bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ void flattenDictionaryObject()
+ {
+ m_structure->flattenDictionaryStructure(this);
+ }
private:
+ ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
+ PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
+
+ const JSValue* locationForOffset(size_t offset) const
+ {
+ return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]);
+ }
+
+ JSValue* locationForOffset(size_t offset)
+ {
+ return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
+ }
+
+ void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
+ void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+ void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0);
+
bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
Structure* createInheritorID();
- RefPtr<Structure> m_inheritorID;
+ union {
+ PropertyStorage m_externalStorage;
+ EncodedJSValue m_inlineStorage[inlineStorageCapacity];
+ };
- PropertyStorage m_propertyStorage;
- JSValuePtr m_inlineStorage[inlineStorageCapacity];
+ RefPtr<Structure> m_inheritorID;
};
+
+JSObject* constructEmptyObject(ExecState*);
- JSObject* asObject(JSValuePtr);
-
- JSObject* constructEmptyObject(ExecState*);
-
-inline JSObject* asObject(JSValuePtr value)
+inline JSObject* asObject(JSValue 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()));
+#if USE(JSVALUE64) || USE(JSVALUE32_64)
+ ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0);
+#endif
}
inline JSObject::~JSObject()
{
ASSERT(m_structure);
- if (m_propertyStorage != m_inlineStorage)
- delete [] m_propertyStorage;
+ if (!isUsingInlineStorage())
+ delete [] m_externalStorage;
m_structure->deref();
}
-inline JSValuePtr JSObject::prototype() const
+inline JSValue JSObject::prototype() const
{
return m_structure->storedPrototype();
}
-inline void JSObject::setPrototype(JSValuePtr prototype)
+inline void JSObject::setPrototype(JSValue prototype)
{
ASSERT(prototype);
RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype);
return createInheritorID();
}
+inline bool Structure::isUsingInlineStorage() const
+{
+ return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
+}
+
inline bool JSCell::isObject(const ClassInfo* info) const
{
for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
}
// this method is here to be after the inline declaration of JSCell::isObject
-inline bool JSValuePtr::isObject(const ClassInfo* classInfo) const
+inline bool JSValue::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 (JSValue* location = getDirectLocation(propertyName)) {
if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter())
fillGetterPropertySlot(slot, location);
else
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.
while (true) {
if (object->fastGetOwnPropertySlot(exec, propertyName, slot))
return true;
- JSValuePtr prototype = object->prototype();
+ JSValue prototype = object->prototype();
if (!prototype.isObject())
return false;
object = asObject(prototype);
while (true) {
if (object->getOwnPropertySlot(exec, propertyName, slot))
return true;
- JSValuePtr prototype = object->prototype();
+ JSValue prototype = object->prototype();
if (!prototype.isObject())
return false;
object = asObject(prototype);
}
}
-inline JSValuePtr JSObject::get(ExecState* exec, const Identifier& propertyName) const
+inline JSValue JSObject::get(ExecState* exec, const Identifier& propertyName) const
{
PropertySlot slot(this);
if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
return jsUndefined();
}
-inline JSValuePtr JSObject::get(ExecState* exec, unsigned propertyName) const
+inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
{
PropertySlot slot(this);
if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
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)
+inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
{
+ ASSERT(value);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
if (m_structure->isDictionary()) {
unsigned currentAttributes;
- size_t offset = m_structure->get(propertyName, currentAttributes);
+ JSCell* currentSpecificFunction;
+ size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
if (offset != WTF::notFound) {
+ if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
+ m_structure->despecifyDictionaryFunction(propertyName);
if (checkReadOnly && currentAttributes & ReadOnly)
return;
- m_propertyStorage[offset] = value;
- slot.setExistingProperty(this, offset);
+ putDirectOffset(offset, value);
+ if (!specificFunction && !currentSpecificFunction)
+ slot.setExistingProperty(this, offset);
return;
}
size_t currentCapacity = m_structure->propertyStorageCapacity();
- offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
+ offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
if (currentCapacity != m_structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
ASSERT(offset < m_structure->propertyStorageCapacity());
- m_propertyStorage[offset] = value;
- slot.setNewProperty(this, offset);
+ putDirectOffset(offset, value);
+ // See comment on setNewProperty call below.
+ if (!specificFunction)
+ 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 (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, 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());
+ putDirectOffset(offset, value);
+ // See comment on setNewProperty call below.
+ if (!specificFunction)
+ slot.setNewProperty(this, offset);
return;
}
unsigned currentAttributes;
- offset = m_structure->get(propertyName, currentAttributes);
+ JSCell* currentSpecificFunction;
+ offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
if (offset != WTF::notFound) {
if (checkReadOnly && currentAttributes & ReadOnly)
return;
- m_propertyStorage[offset] = value;
+
+ if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) {
+ setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName));
+ putDirectOffset(offset, value);
+ // Function transitions are not currently cachable, so leave the slot in an uncachable state.
+ return;
+ }
+ putDirectOffset(offset, value);
slot.setExistingProperty(this, offset);
return;
}
- RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, offset);
+ // If we have a specific function, we may have got to this point if there is
+ // already a transition with the correct property name and attributes, but
+ // specialized to a different function. In this case we just want to give up
+ // and despecialize the transition.
+ // In this case we clear the value of specificFunction which will result
+ // in us adding a non-specific transition, and any subsequent lookup in
+ // Structure::addPropertyTransitionToExistingStructure will just use that.
+ if (specificFunction && m_structure->hasTransition(propertyName, attributes))
+ specificFunction = 0;
+
+ RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, 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());
+ putDirectOffset(offset, value);
+ // Function transitions are not currently cachable, so leave the slot in an uncachable state.
+ if (!specificFunction)
+ slot.setNewProperty(this, offset);
+}
+
+inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+ ASSERT(value);
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
}
-inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+ PutPropertySlot slot;
+ putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+ ASSERT(value);
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+ PutPropertySlot slot;
+ putDirectInternal(propertyName, value, attributes, false, slot, 0);
+}
+
+inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+ putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value);
+}
+
+inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr)
+{
+ PutPropertySlot slot;
+ putDirectInternal(propertyName, value, attr, false, slot, value);
+}
+
+inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+ size_t currentCapacity = m_structure->propertyStorageCapacity();
+ size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0);
+ if (currentCapacity != m_structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+ putDirectOffset(offset, value);
+}
+
+inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes)
{
size_t currentCapacity = m_structure->propertyStorageCapacity();
- size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes);
+ size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value);
if (currentCapacity != m_structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
- m_propertyStorage[offset] = value;
+ putDirectOffset(offset, value);
}
inline void JSObject::transitionTo(Structure* newStructure)
setStructure(newStructure);
}
-inline JSValuePtr JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return defaultValue(exec, preferredType);
}
-inline JSValuePtr JSValuePtr::get(ExecState* exec, const Identifier& propertyName) const
+inline JSValue JSValue::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
+inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const
{
if (UNLIKELY(!isCell())) {
- JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ JSObject* prototype = synthesizePrototype(exec);
+ if (propertyName == exec->propertyNames().underscoreProto)
+ return prototype;
if (!prototype->getPropertySlot(exec, propertyName, slot))
return jsUndefined();
return slot.getValue(exec, propertyName);
if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
return slot.getValue(exec, propertyName);
ASSERT(cell->isObject());
- JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype();
+ JSValue prototype = static_cast<JSObject*>(cell)->prototype();
if (!prototype.isObject())
return jsUndefined();
cell = asObject(prototype);
}
}
-inline JSValuePtr JSValuePtr::get(ExecState* exec, unsigned propertyName) const
+inline JSValue JSValue::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
+inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
{
if (UNLIKELY(!isCell())) {
- JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ JSObject* prototype = synthesizePrototype(exec);
if (!prototype->getPropertySlot(exec, propertyName, slot))
return jsUndefined();
return slot.getValue(exec, propertyName);
if (cell->getOwnPropertySlot(exec, propertyName, slot))
return slot.getValue(exec, propertyName);
ASSERT(cell->isObject());
- JSValuePtr prototype = static_cast<JSObject*>(cell)->prototype();
+ JSValue 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)
+inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (UNLIKELY(!isCell())) {
- JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot);
+ synthesizeObject(exec)->put(exec, propertyName, value, slot);
return;
}
asCell()->put(exec, propertyName, value, slot);
}
-inline void JSValuePtr::put(ExecState* exec, unsigned propertyName, JSValuePtr value)
+inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
{
if (UNLIKELY(!isCell())) {
- JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value);
+ synthesizeObject(exec)->put(exec, propertyName, value);
return;
}
asCell()->put(exec, propertyName, value);
{
ASSERT(newSize > oldSize);
- JSValuePtr* oldPropertyStorage = m_propertyStorage;
- m_propertyStorage = new JSValuePtr[newSize];
+ // It's important that this function not rely on m_structure, since
+ // we might be in the middle of a transition.
+ bool wasInline = (oldSize == JSObject::inlineStorageCapacity);
+
+ PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage);
+ PropertyStorage newPropertyStorage = new EncodedJSValue[newSize];
for (unsigned i = 0; i < oldSize; ++i)
- m_propertyStorage[i] = oldPropertyStorage[i];
+ newPropertyStorage[i] = oldPropertyStorage[i];
- if (oldPropertyStorage != m_inlineStorage)
+ if (!wasInline)
delete [] oldPropertyStorage;
+
+ m_externalStorage = newPropertyStorage;
}
} // namespace JSC
{
}
-JSValuePtr JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
+JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
- return noValue();
+ return JSValue();
}
-bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValuePtr&)
+bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&)
{
ASSERT_NOT_REACHED();
return false;
class JSPropertyNameIterator : public JSCell {
public:
- static JSPropertyNameIterator* create(ExecState*, JSValuePtr);
+ static JSPropertyNameIterator* create(ExecState*, JSValue);
virtual ~JSPropertyNameIterator();
- virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double&, JSValuePtr&);
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual void mark();
- JSValuePtr next(ExecState*);
+ JSValue next(ExecState*);
void invalidate();
private:
{
}
-inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValuePtr v)
+inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v)
{
if (v.isUndefinedOrNull())
return new (exec) JSPropertyNameIterator;
return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData());
}
-inline JSValuePtr JSPropertyNameIterator::next(ExecState* exec)
+inline JSValue JSPropertyNameIterator::next(ExecState* exec)
{
if (m_position == m_end)
- return noValue();
+ return JSValue();
if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec))
return jsOwnedString(exec, (*m_position++).ustring());
m_position++;
} while (m_position != m_end);
- return noValue();
+ return JSValue();
}
} // namespace JSC
return exec->globalThisValue();
}
-void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot&)
+void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&)
{
if (symbolTablePut(propertyName, value))
return;
ASSERT_NOT_REACHED();
}
-void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes)
{
if (symbolTablePutWithAttributes(propertyName, value, attributes))
return;
return symbolTableGet(propertyName, slot);
}
-inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
-{
- return symbolTableGet(propertyName, slot, slotIsWriteable);
-}
-
}
};
public:
- JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValuePtr value, unsigned attributes)
+ JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes)
: JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData())
{
d()->registerStore = value;
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);
+ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+ void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
- static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
private:
JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
namespace JSC {
-JSValuePtr JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
+JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
return const_cast<JSString*>(this);
}
-bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value)
+bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
{
value = this;
number = m_value.toDouble();
// This function should only be called by JSValue::get.
if (getStringPropertySlot(exec, propertyName, slot))
return true;
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValue(exec->lexicalGlobalObject()->stringPrototype());
+ return true;
+ }
slot.setBase(this);
JSObject* object;
- for (JSValuePtr prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
+ for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
object = asObject(prototype);
if (object->getOwnPropertySlot(exec, propertyName, slot))
return true;
#ifndef JSString_h
#define JSString_h
-#include "CommonIdentifiers.h"
#include "CallFrame.h"
+#include "CommonIdentifiers.h"
#include "Identifier.h"
#include "JSNumberCell.h"
#include "PropertySlot.h"
class JSString : public JSCell {
friend class JIT;
- friend class Interpreter;
+ friend class VPtrSet;
public:
JSString(JSGlobalData* globalData, const UString& value)
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)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
private:
enum VPtrStealingHackType { VPtrStealingHack };
{
}
- virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
UString m_value;
};
- JSString* asString(JSValuePtr);
+ JSString* asString(JSValue);
- inline JSString* asString(JSValuePtr value)
+ inline JSString* asString(JSValue value)
{
ASSERT(asCell(value)->isString());
return static_cast<JSString*>(asCell(value));
return false;
}
+ inline bool isJSString(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsStringVPtr; }
+
// --- JSValue inlines ----------------------------
- inline JSString* JSValuePtr::toThisJSString(ExecState* exec)
+ inline JSString* JSValue::toThisJSString(ExecState* exec)
{
- return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec);
+ return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec));
}
} // namespace JSC
#include "config.h"
#include "JSValue.h"
+#include "BooleanConstructor.h"
+#include "BooleanPrototype.h"
+#include "ExceptionHelpers.h"
+#include "JSGlobalObject.h"
#include "JSFunction.h"
+#include "JSNotAnObject.h"
+#include "NumberObject.h"
#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
namespace JSC {
static const double D32 = 4294967296.0;
// ECMA 9.4
-double JSValuePtr::toInteger(ExecState* exec) const
+double JSValue::toInteger(ExecState* exec) const
{
- if (isInt32Fast())
- return getInt32Fast();
+ if (isInt32())
+ return asInt32();
double d = toNumber(exec);
return isnan(d) ? 0.0 : trunc(d);
}
-double JSValuePtr::toIntegerPreserveNaN(ExecState* exec) const
+double JSValue::toIntegerPreserveNaN(ExecState* exec) const
{
- if (isInt32Fast())
- return getInt32Fast();
+ if (isInt32())
+ return asInt32();
return trunc(toNumber(exec));
}
+JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
+{
+ ASSERT(!isCell());
+
+ if (isInt32() || isDouble())
+ return constructNumber(exec, asValue());
+ if (isTrue() || isFalse())
+ return constructBooleanFromImmediateBoolean(exec, asValue());
+ ASSERT(isUndefinedOrNull());
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
+{
+ ASSERT(!isCell());
+
+ if (isInt32() || isDouble())
+ return constructNumber(exec, asValue());
+ if (isTrue() || isFalse())
+ return constructBooleanFromImmediateBoolean(exec, asValue());
+ ASSERT(isUndefinedOrNull());
+ return exec->globalThisValue();
+}
+
+JSObject* JSValue::synthesizeObject(ExecState* exec) const
+{
+ ASSERT(!isCell());
+ if (isNumber())
+ return constructNumber(exec, asValue());
+ if (isBoolean())
+ return constructBooleanFromImmediateBoolean(exec, asValue());
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+JSObject* JSValue::synthesizePrototype(ExecState* exec) const
+{
+ ASSERT(!isCell());
+ if (isNumber())
+ return exec->lexicalGlobalObject()->numberPrototype();
+ if (isBoolean())
+ return exec->lexicalGlobalObject()->booleanPrototype();
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+#ifndef NDEBUG
+char* JSValue::description()
+{
+ static const size_t size = 32;
+ static char description[size];
+ if (isInt32())
+ snprintf(description, size, "Int32: %d", asInt32());
+ else if (isDouble())
+ snprintf(description, size, "Double: %lf", asDouble());
+ else if (isCell())
+ snprintf(description, size, "Cell: %p", asCell());
+ else if (isTrue())
+ snprintf(description, size, "True");
+ else if (isFalse())
+ snprintf(description, size, "False");
+ else if (isNull())
+ snprintf(description, size, "Null");
+ else {
+ ASSERT(isUndefined());
+ snprintf(description, size, "Undefined");
+ }
+
+ return description;
+}
+#endif
+
int32_t toInt32SlowCase(double d, bool& ok)
{
ok = true;
return static_cast<uint32_t>(d32);
}
+NEVER_INLINE double nonInlineNaN()
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
} // namespace JSC
#include "CallData.h"
#include "ConstructData.h"
+#include <math.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashTraits.h>
+#include <wtf/MathExtras.h>
namespace JSC {
class Identifier;
class JSCell;
+ class JSGlobalData;
+ class JSImmediate;
class JSObject;
class JSString;
class PropertySlot;
enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
- class JSImmediate;
- class JSValueEncodedAsPointer;
+#if USE(JSVALUE32_64)
+ typedef int64_t EncodedJSValue;
+#else
+ typedef void* EncodedJSValue;
+#endif
- class JSValuePtr {
- friend class JSImmediate;
+ double nonInlineNaN();
+ int32_t toInt32SlowCase(double, bool& ok);
+ uint32_t toUInt32SlowCase(double, bool& ok);
- static JSValuePtr makeImmediate(intptr_t value)
- {
- return JSValuePtr(reinterpret_cast<JSCell*>(value));
- }
+ class JSValue {
+ friend class JSImmediate;
+ friend struct EncodedJSValueHashTraits;
+ friend class JIT;
+ friend class JITStubs;
+ friend class JITStubCall;
- 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));
- }
+ static EncodedJSValue encode(JSValue value);
+ static JSValue decode(EncodedJSValue ptr);
+#if !USE(JSVALUE32_64)
+ private:
+ static JSValue makeImmediate(intptr_t value);
+ intptr_t immediateValue();
+ public:
+#endif
+ enum JSNullTag { JSNull };
+ enum JSUndefinedTag { JSUndefined };
+ enum JSTrueTag { JSTrue };
+ enum JSFalseTag { JSFalse };
+
+ JSValue();
+ JSValue(JSNullTag);
+ JSValue(JSUndefinedTag);
+ JSValue(JSTrueTag);
+ JSValue(JSFalseTag);
+ JSValue(JSCell* ptr);
+ JSValue(const JSCell* ptr);
+
+ // Numbers
+ JSValue(ExecState*, double);
+ JSValue(ExecState*, char);
+ JSValue(ExecState*, unsigned char);
+ JSValue(ExecState*, short);
+ JSValue(ExecState*, unsigned short);
+ JSValue(ExecState*, int);
+ JSValue(ExecState*, unsigned);
+ JSValue(ExecState*, long);
+ JSValue(ExecState*, unsigned long);
+ JSValue(ExecState*, long long);
+ JSValue(ExecState*, unsigned long long);
+ JSValue(JSGlobalData*, double);
+ JSValue(JSGlobalData*, int);
+ JSValue(JSGlobalData*, unsigned);
+
+ operator bool() const;
+ bool operator==(const JSValue& other) const;
+ bool operator!=(const JSValue& other) const;
+
+ bool isInt32() const;
+ bool isUInt32() const;
+ bool isDouble() const;
+ bool isTrue() const;
+ bool isFalse() const;
+
+ int32_t asInt32() const;
+ uint32_t asUInt32() const;
+ double asDouble() const;
// Querying the type.
bool isUndefined() const;
// 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&);
+ JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
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.
+ JSValue 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).
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);
+ JSValue get(ExecState*, const Identifier& propertyName) const;
+ JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
+ JSValue get(ExecState*, unsigned propertyName) const;
+ JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
+ void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ void put(ExecState*, unsigned propertyName, JSValue);
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);
+ static bool equal(ExecState* exec, JSValue v1, JSValue v2);
+ static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
+ static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
+ static bool strictEqual(JSValue v1, JSValue v2);
+ static bool strictEqualSlowCase(JSValue v1, JSValue v2);
+ static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2);
- JSValuePtr getJSNumber(); // noValue() if this is not a JSNumber or number object
+ JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
bool isCell() const;
JSCell* asCell() const;
+#ifndef NDEBUG
+ char* description();
+#endif
+
private:
- inline const JSValuePtr asValue() const { return *this; }
+ enum HashTableDeletedValueTag { HashTableDeletedValue };
+ JSValue(HashTableDeletedValueTag);
+
+ inline const JSValue asValue() const { return *this; }
+ JSObject* toObjectSlowCase(ExecState*) const;
+ JSObject* toThisObjectSlowCase(ExecState*) const;
+
+ enum { Int32Tag = 0xffffffff };
+ enum { CellTag = 0xfffffffe };
+ enum { TrueTag = 0xfffffffd };
+ enum { FalseTag = 0xfffffffc };
+ enum { NullTag = 0xfffffffb };
+ enum { UndefinedTag = 0xfffffffa };
+ enum { DeletedValueTag = 0xfffffff9 };
+
+ enum { LowestTag = DeletedValueTag };
+
+ uint32_t tag() const;
+ int32_t payload() const;
+
+ JSObject* synthesizePrototype(ExecState*) const;
+ JSObject* synthesizeObject(ExecState*) const;
+
+#if USE(JSVALUE32_64)
+ union {
+ EncodedJSValue asEncodedJSValue;
+ double asDouble;
+#if PLATFORM(BIG_ENDIAN)
+ struct {
+ int32_t tag;
+ int32_t payload;
+ } asBits;
+#else
+ struct {
+ int32_t payload;
+ int32_t tag;
+ } asBits;
+#endif
+ } u;
+#else // USE(JSVALUE32_64)
+ JSCell* m_ptr;
+#endif // USE(JSVALUE32_64)
+ };
- bool isDoubleNumber() const;
- double getDoubleNumber() const;
+#if USE(JSVALUE32_64)
+ typedef IntHash<EncodedJSValue> EncodedJSValueHash;
- JSCell* m_ptr;
+ struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
+ static const bool emptyValueIsZero = false;
+ static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); }
+ static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
+ static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
};
+#else
+ typedef PtrHash<EncodedJSValue> EncodedJSValueHash;
+
+ struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> {
+ static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
+ static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); }
+ };
+#endif
+
+ // Stand-alone helper functions.
+ inline JSValue jsNull()
+ {
+ return JSValue(JSValue::JSNull);
+ }
+
+ inline JSValue jsUndefined()
+ {
+ return JSValue(JSValue::JSUndefined);
+ }
+
+ inline JSValue jsBoolean(bool b)
+ {
+ return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
+ {
+ return JSValue(exec, d);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
+ {
+ return JSValue(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
+ {
+ return JSValue(globalData, d);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
+ {
+ return JSValue(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
+ {
+ return JSValue(globalData, i);
+ }
+
+ inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
+ inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; }
+
+ inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
+ inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
+
+ 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);
+ }
+
+ ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
+ {
+ if (isInt32())
+ return asInt32();
+ bool ignored;
+ return toInt32SlowCase(toNumber(exec), ignored);
+ }
+
+ inline uint32_t JSValue::toUInt32(ExecState* exec) const
+ {
+ if (isUInt32())
+ return asInt32();
+ bool ignored;
+ return toUInt32SlowCase(toNumber(exec), ignored);
+ }
+
+ inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
+ {
+ if (isInt32()) {
+ ok = true;
+ return asInt32();
+ }
+ return toInt32SlowCase(toNumber(exec), ok);
+ }
+
+ inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
+ {
+ if (isUInt32()) {
+ ok = true;
+ return asInt32();
+ }
+ return toUInt32SlowCase(toNumber(exec), ok);
+ }
+
+#if USE(JSVALUE32_64)
+ inline JSValue jsNaN(ExecState* exec)
+ {
+ return JSValue(exec, nonInlineNaN());
+ }
+
+ // JSValue member functions.
+ inline EncodedJSValue JSValue::encode(JSValue value)
+ {
+ return value.u.asEncodedJSValue;
+ }
+
+ inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
+ {
+ JSValue v;
+ v.u.asEncodedJSValue = encodedJSValue;
+ return v;
+ }
+
+ inline JSValue::JSValue()
+ {
+ u.asBits.tag = CellTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSNullTag)
+ {
+ u.asBits.tag = NullTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSUndefinedTag)
+ {
+ u.asBits.tag = UndefinedTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSTrueTag)
+ {
+ u.asBits.tag = TrueTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSFalseTag)
+ {
+ u.asBits.tag = FalseTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(HashTableDeletedValueTag)
+ {
+ u.asBits.tag = DeletedValueTag;
+ u.asBits.payload = 0;
+ }
+
+ inline JSValue::JSValue(JSCell* ptr)
+ {
+ u.asBits.tag = CellTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(ptr);
+ }
+
+ inline JSValue::JSValue(const JSCell* ptr)
+ {
+ u.asBits.tag = CellTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
+ }
+
+ inline JSValue::operator bool() const
+ {
+ return u.asBits.payload || tag() != CellTag;
+ }
+
+ inline bool JSValue::operator==(const JSValue& other) const
+ {
+ return u.asEncodedJSValue == other.u.asEncodedJSValue;
+ }
+
+ inline bool JSValue::operator!=(const JSValue& other) const
+ {
+ return u.asEncodedJSValue != other.u.asEncodedJSValue;
+ }
+
+ inline bool JSValue::isUndefined() const
+ {
+ return tag() == UndefinedTag;
+ }
+
+ inline bool JSValue::isNull() const
+ {
+ return tag() == NullTag;
+ }
+
+ inline bool JSValue::isUndefinedOrNull() const
+ {
+ return isUndefined() || isNull();
+ }
+
+ inline bool JSValue::isCell() const
+ {
+ return tag() == CellTag;
+ }
+
+ inline bool JSValue::isInt32() const
+ {
+ return tag() == Int32Tag;
+ }
+
+ inline bool JSValue::isUInt32() const
+ {
+ return tag() == Int32Tag && asInt32() > -1;
+ }
+
+ inline bool JSValue::isDouble() const
+ {
+ return tag() < LowestTag;
+ }
+
+ inline bool JSValue::isTrue() const
+ {
+ return tag() == TrueTag;
+ }
+
+ inline bool JSValue::isFalse() const
+ {
+ return tag() == FalseTag;
+ }
+
+ inline uint32_t JSValue::tag() const
+ {
+ return u.asBits.tag;
+ }
+
+ inline int32_t JSValue::payload() const
+ {
+ return u.asBits.payload;
+ }
+
+ inline int32_t JSValue::asInt32() const
+ {
+ ASSERT(isInt32());
+ return u.asBits.payload;
+ }
+
+ inline uint32_t JSValue::asUInt32() const
+ {
+ ASSERT(isUInt32());
+ return u.asBits.payload;
+ }
+
+ inline double JSValue::asDouble() const
+ {
+ ASSERT(isDouble());
+ return u.asDouble;
+ }
+
+ ALWAYS_INLINE JSCell* JSValue::asCell() const
+ {
+ ASSERT(isCell());
+ return reinterpret_cast<JSCell*>(u.asBits.payload);
+ }
+
+ inline JSValue::JSValue(ExecState* exec, double d)
+ {
+ const int32_t asInt32 = static_cast<int32_t>(d);
+ if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
+ u.asDouble = d;
+ return;
+ }
+ *this = JSValue(exec, static_cast<int32_t>(d));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, char i)
+ {
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, unsigned char i)
+ {
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, short i)
+ {
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, unsigned short i)
+ {
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState*, int i)
+ {
+ u.asBits.tag = Int32Tag;
+ u.asBits.payload = i;
+ }
+
+ inline JSValue::JSValue(ExecState* exec, unsigned i)
+ {
+ if (static_cast<int32_t>(i) < 0) {
+ *this = JSValue(exec, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, long i)
+ {
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(exec, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, unsigned long i)
+ {
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(exec, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(exec, static_cast<uint32_t>(i));
+ }
+
+ inline JSValue::JSValue(ExecState* exec, long long i)
+ {
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(exec, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(exec, static_cast<int32_t>(i));
+ }
- inline JSValuePtr noValue()
+ inline JSValue::JSValue(ExecState* exec, unsigned long long i)
{
- return JSValuePtr();
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(exec, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(exec, static_cast<uint32_t>(i));
}
- 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 JSValue::JSValue(JSGlobalData* globalData, double d)
+ {
+ const int32_t asInt32 = static_cast<int32_t>(d);
+ if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
+ u.asDouble = d;
+ return;
+ }
+ *this = JSValue(globalData, static_cast<int32_t>(d));
+ }
+
+ inline JSValue::JSValue(JSGlobalData*, int i)
+ {
+ u.asBits.tag = Int32Tag;
+ u.asBits.payload = i;
+ }
+
+ inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
+ {
+ if (static_cast<int32_t>(i) < 0) {
+ *this = JSValue(globalData, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(globalData, static_cast<int32_t>(i));
+ }
- 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 JSValue::isNumber() const
+ {
+ return isInt32() || isDouble();
+ }
+
+ inline bool JSValue::isBoolean() const
+ {
+ return isTrue() || isFalse();
+ }
+
+ inline bool JSValue::getBoolean(bool& v) const
+ {
+ if (isTrue()) {
+ v = true;
+ return true;
+ }
+ if (isFalse()) {
+ v = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline bool JSValue::getBoolean() const
+ {
+ ASSERT(isBoolean());
+ return tag() == TrueTag;
+ }
+
+ inline double JSValue::uncheckedGetNumber() const
+ {
+ ASSERT(isNumber());
+ return isInt32() ? asInt32() : asDouble();
+ }
+
+ ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
+ {
+ return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
+ }
+
+ inline bool JSValue::getNumber(double& result) const
+ {
+ if (isInt32()) {
+ result = asInt32();
+ return true;
+ }
+ if (isDouble()) {
+ result = asDouble();
+ return true;
+ }
+ return false;
+ }
+
+#else // USE(JSVALUE32_64)
+
+ // JSValue member functions.
+ inline EncodedJSValue JSValue::encode(JSValue value)
+ {
+ return reinterpret_cast<EncodedJSValue>(value.m_ptr);
+ }
+
+ inline JSValue JSValue::decode(EncodedJSValue ptr)
+ {
+ return JSValue(reinterpret_cast<JSCell*>(ptr));
+ }
+
+ inline JSValue JSValue::makeImmediate(intptr_t value)
+ {
+ return JSValue(reinterpret_cast<JSCell*>(value));
+ }
+
+ inline intptr_t JSValue::immediateValue()
+ {
+ return reinterpret_cast<intptr_t>(m_ptr);
+ }
+
+ // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
+ inline JSValue::JSValue()
+ : m_ptr(0)
+ {
+ }
+
+ // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
+ inline JSValue::JSValue(HashTableDeletedValueTag)
+ : m_ptr(reinterpret_cast<JSCell*>(0x4))
+ {
+ }
+
+ inline JSValue::JSValue(JSCell* ptr)
+ : m_ptr(ptr)
+ {
+ }
+
+ inline JSValue::JSValue(const JSCell* ptr)
+ : m_ptr(const_cast<JSCell*>(ptr))
+ {
+ }
+
+ inline JSValue::operator bool() const
+ {
+ return m_ptr;
+ }
+
+ inline bool JSValue::operator==(const JSValue& other) const
+ {
+ return m_ptr == other.m_ptr;
+ }
+
+ inline bool JSValue::operator!=(const JSValue& other) const
+ {
+ return m_ptr != other.m_ptr;
+ }
+
+ inline bool JSValue::isUndefined() const
+ {
+ return asValue() == jsUndefined();
+ }
+
+ inline bool JSValue::isNull() const
+ {
+ return asValue() == jsNull();
+ }
+#endif // USE(JSVALUE32_64)
} // namespace JSC
public:
SymbolTable& symbolTable() const { return *d->symbolTable; }
- virtual void putWithAttributes(ExecState*, const Identifier&, JSValuePtr, unsigned attributes) = 0;
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
virtual bool deleteProperty(ExecState*, const Identifier&);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
bool symbolTableGet(const Identifier&, PropertySlot&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
- bool symbolTablePut(const Identifier&, JSValuePtr);
- bool symbolTablePutWithAttributes(const Identifier&, JSValuePtr, unsigned attributes);
+ bool symbolTablePut(const Identifier&, JSValue);
+ bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
JSVariableObjectData* d;
};
return false;
}
- inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValuePtr value)
+ inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue value)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
return true;
}
- inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValuePtr value, unsigned attributes)
+ inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
explicit JSWrapperObject(PassRefPtr<Structure>);
public:
- JSValuePtr internalValue() const { return m_internalValue; }
- void setInternalValue(JSValuePtr);
+ JSValue internalValue() const { return m_internalValue; }
+ void setInternalValue(JSValue);
virtual void mark();
private:
- JSValuePtr m_internalValue;
+ JSValue m_internalValue;
};
inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure)
: JSObject(structure)
- , m_internalValue(noValue())
{
}
- inline void JSWrapperObject::setInternalValue(JSValuePtr value)
+ inline void JSWrapperObject::setInternalValue(JSValue value)
{
ASSERT(value);
ASSERT(!value.isObject());
--- /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 "LiteralParser.h"
+
+#include "JSArray.h"
+#include "JSString.h"
+#include "Lexer.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/dtoa.h>
+
+namespace JSC {
+
+LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
+{
+ while (m_ptr < m_end && isASCIISpace(*m_ptr))
+ ++m_ptr;
+
+ ASSERT(m_ptr <= m_end);
+ if (m_ptr >= m_end) {
+ token.type = TokEnd;
+ token.start = token.end = m_ptr;
+ return TokEnd;
+ }
+ token.type = TokError;
+ token.start = m_ptr;
+ switch (*m_ptr) {
+ case '[':
+ token.type = TokLBracket;
+ token.end = ++m_ptr;
+ return TokLBracket;
+ case ']':
+ token.type = TokRBracket;
+ token.end = ++m_ptr;
+ return TokRBracket;
+ case '(':
+ token.type = TokLParen;
+ token.end = ++m_ptr;
+ return TokLBracket;
+ case ')':
+ token.type = TokRParen;
+ token.end = ++m_ptr;
+ return TokRBracket;
+ case '{':
+ token.type = TokLBrace;
+ token.end = ++m_ptr;
+ return TokLBrace;
+ case '}':
+ token.type = TokRBrace;
+ token.end = ++m_ptr;
+ return TokRBrace;
+ case ',':
+ token.type = TokComma;
+ token.end = ++m_ptr;
+ return TokComma;
+ case ':':
+ token.type = TokColon;
+ token.end = ++m_ptr;
+ return TokColon;
+ case '"':
+ if (m_mode == StrictJSON)
+ return lexString<StrictJSON>(token);
+ return lexString<NonStrictJSON>(token);
+ case 't':
+ if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') {
+ m_ptr += 4;
+ token.type = TokTrue;
+ token.end = m_ptr;
+ return TokTrue;
+ }
+ break;
+ case 'f':
+ if (m_end - m_ptr >= 5 && m_ptr[1] == 'a' && m_ptr[2] == 'l' && m_ptr[3] == 's' && m_ptr[4] == 'e') {
+ m_ptr += 5;
+ token.type = TokFalse;
+ token.end = m_ptr;
+ return TokFalse;
+ }
+ break;
+ case 'n':
+ if (m_end - m_ptr >= 4 && m_ptr[1] == 'u' && m_ptr[2] == 'l' && m_ptr[3] == 'l') {
+ m_ptr += 4;
+ token.type = TokNull;
+ token.end = m_ptr;
+ return TokNull;
+ }
+ break;
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return lexNumber(token);
+ }
+ return TokError;
+}
+
+template <LiteralParser::ParserMode mode> static inline bool isSafeStringCharacter(UChar c)
+{
+ return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != '"') || c == '\t';
+}
+
+template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
+{
+ ++m_ptr;
+ const UChar* runStart;
+ token.stringToken = UString();
+ do {
+ runStart = m_ptr;
+ while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr))
+ ++m_ptr;
+ if (runStart < m_ptr)
+ token.stringToken.append(runStart, m_ptr - runStart);
+ if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
+ ++m_ptr;
+ if (m_ptr >= m_end)
+ return TokError;
+ switch (*m_ptr) {
+ case '"':
+ token.stringToken.append('"');
+ m_ptr++;
+ break;
+ case '\\':
+ token.stringToken.append('\\');
+ m_ptr++;
+ break;
+ case '/':
+ token.stringToken.append('/');
+ m_ptr++;
+ break;
+ case 'b':
+ token.stringToken.append('\b');
+ m_ptr++;
+ break;
+ case 'f':
+ token.stringToken.append('\f');
+ m_ptr++;
+ break;
+ case 'n':
+ token.stringToken.append('\n');
+ m_ptr++;
+ break;
+ case 'r':
+ token.stringToken.append('\r');
+ m_ptr++;
+ break;
+ case 't':
+ token.stringToken.append('\t');
+ m_ptr++;
+ break;
+
+ case 'u':
+ if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
+ return TokError;
+ for (int i = 1; i < 5; i++) {
+ if (!isASCIIHexDigit(m_ptr[i]))
+ return TokError;
+ }
+ token.stringToken.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
+ m_ptr += 5;
+ break;
+
+ default:
+ return TokError;
+ }
+ }
+ } while ((mode == StrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != '"');
+
+ if (m_ptr >= m_end || *m_ptr != '"')
+ return TokError;
+
+ token.type = TokString;
+ token.end = ++m_ptr;
+ return TokString;
+}
+
+LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token)
+{
+ // ES5 and json.org define numbers as
+ // number
+ // int
+ // int frac? exp?
+ //
+ // int
+ // -? 0
+ // -? digit1-9 digits?
+ //
+ // digits
+ // digit digits?
+ //
+ // -?(0 | [1-9][0-9]*) ('.' [0-9]+)? ([eE][+-]? [0-9]+)?
+
+ if (m_ptr < m_end && *m_ptr == '-') // -?
+ ++m_ptr;
+
+ // (0 | [1-9][0-9]*)
+ if (m_ptr < m_end && *m_ptr == '0') // 0
+ ++m_ptr;
+ else if (m_ptr < m_end && *m_ptr >= '1' && *m_ptr <= '9') { // [1-9]
+ ++m_ptr;
+ // [0-9]*
+ while (m_ptr < m_end && isASCIIDigit(*m_ptr))
+ ++m_ptr;
+ } else
+ return TokError;
+
+ // ('.' [0-9]+)?
+ if (m_ptr < m_end && *m_ptr == '.') {
+ ++m_ptr;
+ // [0-9]+
+ if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+ return TokError;
+
+ ++m_ptr;
+ while (m_ptr < m_end && isASCIIDigit(*m_ptr))
+ ++m_ptr;
+ }
+
+ // ([eE][+-]? [0-9]+)?
+ if (m_ptr < m_end && (*m_ptr == 'e' || *m_ptr == 'E')) { // [eE]
+ ++m_ptr;
+
+ // [-+]?
+ if (m_ptr < m_end && (*m_ptr == '-' || *m_ptr == '+'))
+ ++m_ptr;
+
+ // [0-9]+
+ if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+ return TokError;
+
+ ++m_ptr;
+ while (m_ptr < m_end && isASCIIDigit(*m_ptr))
+ ++m_ptr;
+ }
+
+ token.type = TokNumber;
+ token.end = m_ptr;
+ Vector<char, 64> buffer(token.end - token.start + 1);
+ int i;
+ for (i = 0; i < token.end - token.start; i++) {
+ ASSERT(static_cast<char>(token.start[i]) == token.start[i]);
+ buffer[i] = static_cast<char>(token.start[i]);
+ }
+ buffer[i] = 0;
+ char* end;
+ token.numberToken = WTF::strtod(buffer.data(), &end);
+ ASSERT(buffer.data() + (token.end - token.start) == end);
+ return TokNumber;
+}
+
+JSValue LiteralParser::parse(ParserState initialState)
+{
+ ParserState state = initialState;
+ MarkedArgumentBuffer objectStack;
+ JSValue lastValue;
+ Vector<ParserState, 16> stateStack;
+ Vector<Identifier, 16> identifierStack;
+ while (1) {
+ switch(state) {
+ startParseArray:
+ case StartParseArray: {
+ JSArray* array = constructEmptyArray(m_exec);
+ objectStack.append(array);
+ // fallthrough
+ }
+ doParseArrayStartExpression:
+ case DoParseArrayStartExpression: {
+ if (m_lexer.next() == TokRBracket) {
+ m_lexer.next();
+ lastValue = objectStack.last();
+ objectStack.removeLast();
+ break;
+ }
+
+ stateStack.append(DoParseArrayEndExpression);
+ goto startParseExpression;
+ }
+ case DoParseArrayEndExpression: {
+ asArray(objectStack.last())->push(m_exec, lastValue);
+
+ if (m_lexer.currentToken().type == TokComma)
+ goto doParseArrayStartExpression;
+
+ if (m_lexer.currentToken().type != TokRBracket)
+ return JSValue();
+
+ m_lexer.next();
+ lastValue = objectStack.last();
+ objectStack.removeLast();
+ break;
+ }
+ startParseObject:
+ case StartParseObject: {
+ JSObject* object = constructEmptyObject(m_exec);
+ objectStack.append(object);
+
+ TokenType type = m_lexer.next();
+ if (type == TokString) {
+ Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+
+ // Check for colon
+ if (m_lexer.next() != TokColon)
+ return JSValue();
+
+ m_lexer.next();
+ identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
+ stateStack.append(DoParseObjectEndExpression);
+ goto startParseExpression;
+ } else if (type != TokRBrace)
+ return JSValue();
+ m_lexer.next();
+ lastValue = objectStack.last();
+ objectStack.removeLast();
+ break;
+ }
+ doParseObjectStartExpression:
+ case DoParseObjectStartExpression: {
+ TokenType type = m_lexer.next();
+ if (type != TokString)
+ return JSValue();
+ Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+
+ // Check for colon
+ if (m_lexer.next() != TokColon)
+ return JSValue();
+
+ m_lexer.next();
+ identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
+ stateStack.append(DoParseObjectEndExpression);
+ goto startParseExpression;
+ }
+ case DoParseObjectEndExpression:
+ {
+ asObject(objectStack.last())->putDirect(identifierStack.last(), lastValue);
+ identifierStack.removeLast();
+ if (m_lexer.currentToken().type == TokComma)
+ goto doParseObjectStartExpression;
+ if (m_lexer.currentToken().type != TokRBrace)
+ return JSValue();
+ m_lexer.next();
+ lastValue = objectStack.last();
+ objectStack.removeLast();
+ break;
+ }
+ startParseExpression:
+ case StartParseExpression: {
+ switch (m_lexer.currentToken().type) {
+ case TokLBracket:
+ goto startParseArray;
+ case TokLBrace:
+ goto startParseObject;
+ case TokString: {
+ Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
+ m_lexer.next();
+ lastValue = jsString(m_exec, stringToken.stringToken);
+ break;
+ }
+ case TokNumber: {
+ Lexer::LiteralParserToken numberToken = m_lexer.currentToken();
+ m_lexer.next();
+ lastValue = jsNumber(m_exec, numberToken.numberToken);
+ break;
+ }
+ case TokNull:
+ m_lexer.next();
+ lastValue = jsNull();
+ break;
+
+ case TokTrue:
+ m_lexer.next();
+ lastValue = jsBoolean(true);
+ break;
+
+ case TokFalse:
+ m_lexer.next();
+ lastValue = jsBoolean(false);
+ break;
+
+ default:
+ // Error
+ return JSValue();
+ }
+ break;
+ }
+ case StartParseStatement: {
+ switch (m_lexer.currentToken().type) {
+ case TokLBracket:
+ case TokNumber:
+ case TokString:
+ goto startParseExpression;
+
+ case TokLParen: {
+ m_lexer.next();
+ stateStack.append(StartParseStatementEndStatement);
+ goto startParseExpression;
+ }
+ default:
+ return JSValue();
+ }
+ }
+ case StartParseStatementEndStatement: {
+ ASSERT(stateStack.isEmpty());
+ if (m_lexer.currentToken().type != TokRParen)
+ return JSValue();
+ if (m_lexer.next() == TokEnd)
+ return lastValue;
+ return JSValue();
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ if (stateStack.isEmpty())
+ return lastValue;
+ state = stateStack.last();
+ stateStack.removeLast();
+ continue;
+ }
+}
+
+}
--- /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 LiteralParser_h
+#define LiteralParser_h
+
+#include "JSGlobalObjectFunctions.h"
+#include "JSValue.h"
+#include "UString.h"
+
+namespace JSC {
+
+ class LiteralParser {
+ public:
+ typedef enum { StrictJSON, NonStrictJSON } ParserMode;
+ LiteralParser(ExecState* exec, const UString& s, ParserMode mode)
+ : m_exec(exec)
+ , m_lexer(s, mode)
+ , m_mode(mode)
+ {
+ }
+
+ JSValue tryLiteralParse()
+ {
+ m_lexer.next();
+ JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
+ if (m_lexer.currentToken().type != TokEnd)
+ return JSValue();
+ return result;
+ }
+ private:
+ enum ParserState { StartParseObject, StartParseArray, StartParseExpression,
+ StartParseStatement, StartParseStatementEndStatement,
+ DoParseObjectStartExpression, DoParseObjectEndExpression,
+ DoParseArrayStartExpression, DoParseArrayEndExpression };
+ enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace,
+ TokString, TokIdentifier, TokNumber, TokColon,
+ TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
+ TokNull, TokEnd, TokError };
+
+ class Lexer {
+ public:
+ struct LiteralParserToken {
+ TokenType type;
+ const UChar* start;
+ const UChar* end;
+ UString stringToken;
+ double numberToken;
+ };
+ Lexer(const UString& s, ParserMode mode)
+ : m_string(s)
+ , m_mode(mode)
+ , m_ptr(s.data())
+ , m_end(s.data() + s.size())
+ {
+ }
+
+ TokenType next()
+ {
+ return lex(m_currentToken);
+ }
+
+ const LiteralParserToken& currentToken()
+ {
+ return m_currentToken;
+ }
+
+ private:
+ TokenType lex(LiteralParserToken&);
+ template <ParserMode parserMode> TokenType lexString(LiteralParserToken&);
+ TokenType lexNumber(LiteralParserToken&);
+ LiteralParserToken m_currentToken;
+ UString m_string;
+ ParserMode m_mode;
+ const UChar* m_ptr;
+ const UChar* m_end;
+ };
+
+ class StackGuard;
+ JSValue parse(ParserState);
+
+ ExecState* m_exec;
+ LiteralParser::Lexer m_lexer;
+ ParserMode m_mode;
+ };
+}
+
+#endif
#include "config.h"
#include "Lookup.h"
+#include "JSFunction.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];
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();
void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
{
ASSERT(entry->attributes() & Function);
- JSValuePtr* location = thisObj->getDirectLocation(propertyName);
+ JSValue* location = thisObj->getDirectLocation(propertyName);
if (!location) {
- PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function());
- thisObj->putDirect(propertyName, function, entry->attributes());
+ InternalFunction* function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function());
+
+ thisObj->putDirectFunction(propertyName, function, entry->attributes());
location = thisObj->getDirectLocation(propertyName);
}
#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
+// Bug #26843: Work around Metrowerks compiler bug
+#if COMPILER(WINSCW)
+#define JSC_CONST_HASHTABLE
+#else
+#define JSC_CONST_HASHTABLE const
+#endif
namespace JSC {
};
// FIXME: There is no reason this get function can't be simpler.
- // ie. typedef JSValuePtr (*GetFunction)(ExecState*, JSObject* baseObject)
+ // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject)
typedef PropertySlot::GetValueFunc GetFunction;
- typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValuePtr value);
+ typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
class HashEntry {
public:
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; }
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;
} 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.
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];
} while (entry);
return 0;
-#endif
}
// Convert the hash table keys to identifiers.
* 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)
+ inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue 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))
+ if (entry->attributes() & Function) { // function: put as override property
+ if (LIKELY(value.isCell()))
+ thisObj->putDirectFunction(propertyName, value.asCell());
+ else
+ thisObj->putDirect(propertyName, value);
+ } else if (!(entry->attributes() & ReadOnly))
entry->propertyPutter()(exec, thisObj, value);
return true;
* 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)
+ inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue 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
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&);
+static JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*, JSObject*, JSValue, const ArgList&);
}
// ------------------------------ Functions --------------------------------
-JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, fabs(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, fabs(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, acos(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, acos(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, asin(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, asin(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, atan(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, atan(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, atan2(args.at(exec, 0).toNumber(exec), args.at(exec, 1).toNumber(exec)));
+ return jsNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec)));
}
-JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, ceil(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, ceil(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, cos(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, cos(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, exp(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, exp(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, floor(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, floor(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, log(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, log(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, 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);
+ double val = args.at(k).toNumber(exec);
if (isnan(val)) {
result = NaN;
break;
return jsNumber(exec, result);
}
-JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec, JSObject*, JSValue, 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);
+ double val = args.at(k).toNumber(exec);
if (isnan(val)) {
result = NaN;
break;
return jsNumber(exec, result);
}
-JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, 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);
+ double arg = args.at(0).toNumber(exec);
+ double arg2 = args.at(1).toNumber(exec);
if (isnan(arg2))
return jsNaN(exec);
return jsNumber(exec, pow(arg, arg2));
}
-JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
+JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&)
{
return jsNumber(exec, WTF::weakRandomNumber());
}
-JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- double arg = args.at(exec, 0).toNumber(exec);
+ double arg = args.at(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)
+JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, sin(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, sin(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, sqrt(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, sqrt(args.at(0).toNumber(exec)));
}
-JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, tan(args.at(exec, 0).toNumber(exec)));
+ return jsNumber(exec, tan(args.at(0).toNumber(exec)));
}
} // namespace JSC
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
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)));
+ if (!args.at(0).isUndefined())
+ object->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec)));
return object;
}
constructData.native.function = constructWithNativeErrorConstructor;
return ConstructTypeHost;
}
-
-static JSValuePtr callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValuePtr, const ArgList& args)
+
+static JSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValue, const ArgList& args)
{
return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
}
--- /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 NativeFunctionWrapper_h
+#define NativeFunctionWrapper_h
+
+namespace JSC {
+#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+ class JSFunction;
+ typedef JSFunction NativeFunctionWrapper;
+#else
+ class PrototypeFunction;
+ typedef PrototypeFunction NativeFunctionWrapper;
+#endif
+}
+
+#endif
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&);
+static JSValue numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&);
} // namespace JSC
return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
}
-JSValuePtr numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
+static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNaN(exec);
}
-JSValuePtr numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+static JSValue numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNumber(exec, -Inf);
}
-JSValuePtr numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+static JSValue numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNumber(exec, Inf);
}
-JSValuePtr numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&)
+static JSValue numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNumber(exec, 1.7976931348623157E+308);
}
-JSValuePtr numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&)
+static JSValue numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNumber(exec, 5E-324);
}
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);
+ double n = args.isEmpty() ? 0 : args.at(0).toNumber(exec);
object->setInternalValue(jsNumber(exec, n));
return object;
}
}
// ECMA 15.7.2
-static JSValuePtr callNumberConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
- return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0).toNumber(exec));
+ return jsNumber(exec, args.isEmpty() ? 0 : args.at(0).toNumber(exec));
}
CallType NumberConstructor::getCallData(CallData& callData)
NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- JSValuePtr getValueProperty(ExecState*, int token) const;
+ JSValue getValueProperty(ExecState*, int token) const;
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
}
{
}
-JSValuePtr NumberObject::getJSNumber()
+JSValue NumberObject::getJSNumber()
{
return internalValue();
}
-NumberObject* constructNumber(ExecState* exec, JSValuePtr number)
+NumberObject* constructNumber(ExecState* exec, JSValue number)
{
NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
object->setInternalValue(number);
private:
virtual const ClassInfo* classInfo() const { return &info; }
- virtual JSValuePtr getJSNumber();
+ virtual JSValue getJSNumber();
};
- NumberObject* constructNumber(ExecState*, JSValuePtr);
+ NumberObject* constructNumber(ExecState*, JSValue);
} // namespace JSC
#include "NumberPrototype.h"
#include "Error.h"
+#include "JSFunction.h"
#include "JSString.h"
#include "PrototypeFunction.h"
#include "dtoa.h"
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&);
+static JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue, const ArgList&);
// ECMA 15.7.4
// 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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
}
// ------------------------------ Functions ---------------------------
{
int decimalPoint;
int sign;
- char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+ char result[80];
+ WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL);
bool resultIsInfOrNan = (decimalPoint == 9999);
size_t length = strlen(result);
else {
Vector<char, 1024> buf(decimalPoint + 1);
- // FIXME: Remove use of strcpy() and strncpy()
+ // FIXME: Remove use of strncpy()
if (static_cast<int>(length) <= decimalPoint) {
- strcpy(buf.data(), result);
+ ASSERT(decimalPoint < 1024);
+ memcpy(buf.data(), result, length);
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;
}
return static_cast<double>(result);
}
-JSValuePtr numberProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue 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())
+ double radixAsDouble = args.at(0).toInteger(exec); // nan -> 0
+ if (radixAsDouble == 10 || args.at(0).isUndefined())
return jsString(exec, v.toString(exec));
if (radixAsDouble < 2 || radixAsDouble > 36)
return jsString(exec, startOfResultString);
}
-JSValuePtr numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
// FIXME: Not implemented yet.
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue v = thisValue.getJSNumber();
if (!v)
return throwError(exec, TypeError);
return jsString(exec, v.toString(exec));
}
-JSValuePtr numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue v = thisValue.getJSNumber();
if (!v)
return throwError(exec, TypeError);
return v;
}
-JSValuePtr numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue v = thisValue.getJSNumber();
if (!v)
return throwError(exec, TypeError);
- JSValuePtr fractionDigits = args.at(exec, 0);
+ JSValue fractionDigits = args.at(0);
double df = fractionDigits.toInteger(exec);
if (!(df >= 0 && df <= 20))
return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");
strncpy(buf + i, result + 1, fractionalDigits);
i += fractionalDigits;
} else {
- // FIXME: Remove use of strcpy()
- strcpy(buf + i, result + 1);
+ ASSERT(i + resultLength - 1 < 80);
+ memcpy(buf + i, result + 1, resultLength - 1);
i += static_cast<int>(resultLength) - 1;
}
}
buf[i++] = static_cast<char>('0' + exponential % 10);
}
-JSValuePtr numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue v = thisValue.getJSNumber();
if (!v)
return throwError(exec, TypeError);
if (isnan(x) || isinf(x))
return jsString(exec, UString::from(x));
- JSValuePtr fractionalDigitsValue = args.at(exec, 0);
+ JSValue fractionalDigitsValue = args.at(0);
double df = fractionalDigitsValue.toInteger(exec);
if (!(df >= 0 && df <= 20))
return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");
int decimalPoint;
int sign;
- char* result = WTF::dtoa(x, 0, &decimalPoint, &sign, NULL);
+ char result[80];
+ WTF::dtoa(result, x, 0, &decimalPoint, &sign, NULL);
size_t resultLength = strlen(result);
decimalPoint += decimalAdjust;
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 {
+ // ? 9999 is the magical "result is Inf or NaN" value. what's 999??
+ if (decimalPoint == 999) {
+ ASSERT(i + resultLength < 80);
+ memcpy(buf + i, result, resultLength);
+ buf[i + resultLength] = '\0';
+ } else {
buf[i++] = result[0];
if (includeAllDigits)
}
ASSERT(i <= 80);
- WTF::freedtoa(result);
-
return jsString(exec, buf);
}
-JSValuePtr numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- JSValuePtr v = thisValue.getJSNumber();
+ JSValue v = thisValue.getJSNumber();
if (!v)
return throwError(exec, TypeError);
- double doublePrecision = args.at(exec, 0).toIntegerPreserveNaN(exec);
+ double doublePrecision = args.at(0).toIntegerPreserveNaN(exec);
double x = v.uncheckedGetNumber();
- if (args.at(exec, 0).isUndefined() || isnan(x) || isinf(x))
+ if (args.at(0).isUndefined() || isnan(x) || isinf(x))
return jsString(exec, v.toString(exec));
UString s;
#include "config.h"
#include "ObjectConstructor.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "ObjectPrototype.h"
// ECMA 15.2.2
static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)
{
- JSValuePtr arg = args.at(exec, 0);
+ JSValue arg = args.at(0);
if (arg.isUndefinedOrNull())
return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
return arg.toObject(exec);
return ConstructTypeHost;
}
-static JSValuePtr callObjectConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
return constructObject(exec, args);
}
#include "ObjectPrototype.h"
#include "Error.h"
+#include "JSFunction.h"
#include "JSString.h"
#include "PrototypeFunction.h"
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&);
+static JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, 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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(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&)
+JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
return thisValue.toThisObject(exec);
}
-JSValuePtr objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0).toString(exec))));
+ return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(0).toString(exec))));
}
-JSValuePtr objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSObject* thisObj = thisValue.toThisObject(exec);
- if (!args.at(exec, 0).isObject())
+ if (!args.at(0).isObject())
return jsBoolean(false);
- JSValuePtr v = asObject(args.at(exec, 0))->prototype();
+ JSValue v = asObject(args.at(0))->prototype();
while (true) {
if (!v.isObject())
}
}
-JSValuePtr objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
CallData callData;
- if (args.at(exec, 1).getCallData(callData) == CallTypeNone)
+ if (args.at(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)));
+ thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
return jsUndefined();
}
-JSValuePtr objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
CallData callData;
- if (args.at(exec, 1).getCallData(callData) == CallTypeNone)
+ if (args.at(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)));
+ thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
return jsUndefined();
}
-JSValuePtr objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)));
+ return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(0).toString(exec)));
}
-JSValuePtr objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0).toString(exec)));
+ return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(0).toString(exec)));
}
-JSValuePtr objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0).toString(exec))));
+ return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(0).toString(exec))));
}
-JSValuePtr objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
return thisValue.toThisJSString(exec);
}
-JSValuePtr objectProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]");
}
ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
};
- JSValuePtr objectProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
+ JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
} // namespace JSC
namespace JSC {
-bool JSValuePtr::equalSlowCase(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2)
{
return equalSlowCaseInline(exec, v1, v2);
}
-bool JSValuePtr::strictEqualSlowCase(JSValuePtr v1, JSValuePtr v2)
+bool JSValue::strictEqualSlowCase(JSValue v1, JSValue v2)
{
return strictEqualSlowCaseInline(v1, v2);
}
-NEVER_INLINE JSValuePtr throwOutOfMemoryError(ExecState* exec)
+NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec)
{
JSObject* error = Error::create(exec, GeneralError, "Out of memory");
exec->setException(error);
return error;
}
+NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
+{
+ // exception for the Date exception in defaultValue()
+ JSValue p1 = v1.toPrimitive(callFrame);
+ JSValue 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));
+}
+
+JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue 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");
+}
+
+bool jsIsObjectType(JSValue 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;
+}
+
+bool jsIsFunctionType(JSValue v)
+{
+ if (v.isObject()) {
+ CallData callData;
+ if (asObject(v)->getCallData(callData) != CallTypeNone)
+ return true;
+ }
+ return false;
+}
+
} // namespace JSC
#ifndef Operations_h
#define Operations_h
+#include "Interpreter.h"
#include "JSImmediate.h"
#include "JSNumberCell.h"
#include "JSString.h"
namespace JSC {
+ NEVER_INLINE JSValue throwOutOfMemoryError(ExecState*);
+ NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
+ JSValue jsTypeStringForValue(CallFrame*, JSValue);
+ bool jsIsObjectType(JSValue);
+ bool jsIsFunctionType(JSValue);
+
// ECMA 11.9.3
- inline bool JSValuePtr::equal(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+ inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
{
- if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ if (v1.isInt32() && v2.isInt32())
return v1 == v2;
return equalSlowCase(exec, v1, v2);
}
- ALWAYS_INLINE bool JSValuePtr::equalSlowCaseInline(ExecState* exec, JSValuePtr v1, JSValuePtr v2)
+ ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
{
- ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2));
-
do {
if (v1.isNumber() && v2.isNumber())
return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
if (v1.isUndefinedOrNull()) {
if (v2.isUndefinedOrNull())
return true;
- if (JSImmediate::isImmediate(v2))
+ if (!v2.isCell())
return false;
return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
}
if (v2.isUndefinedOrNull()) {
- if (JSImmediate::isImmediate(v1))
+ if (!v1.isCell())
return false;
return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined();
}
if (v1.isObject()) {
if (v2.isObject())
return v1 == v2;
- JSValuePtr p1 = v1.toPrimitive(exec);
+ JSValue p1 = v1.toPrimitive(exec);
if (exec->hadException())
return false;
v1 = p1;
- if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ if (v1.isInt32() && v2.isInt32())
return v1 == v2;
continue;
}
if (v2.isObject()) {
- JSValuePtr p2 = v2.toPrimitive(exec);
+ JSValue p2 = v2.toPrimitive(exec);
if (exec->hadException())
return false;
v2 = p2;
- if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ if (v1.isInt32() && v2.isInt32())
return v1 == v2;
continue;
}
}
// ECMA 11.9.3
- inline bool JSValuePtr::strictEqual(JSValuePtr v1, JSValuePtr v2)
+ ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2)
+ {
+ ASSERT(v1.isCell() && v2.isCell());
+
+ if (v1.asCell()->isString() && v2.asCell()->isString())
+ return asString(v1)->value() == asString(v2)->value();
+
+ return v1 == v2;
+ }
+
+ inline bool JSValue::strictEqual(JSValue v1, JSValue v2)
{
- if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2))
+ if (v1.isInt32() && v2.isInt32())
return v1 == v2;
if (v1.isNumber() && v2.isNumber())
return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
- if (JSImmediate::isEitherImmediate(v1, v2))
+ if (!v1.isCell() || !v2.isCell())
return v1 == v2;
- return strictEqualSlowCase(v1, v2);
+ return strictEqualSlowCaseInline(v1, v2);
}
- ALWAYS_INLINE bool JSValuePtr::strictEqualSlowCaseInline(JSValuePtr v1, JSValuePtr v2)
+ inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
{
- ASSERT(!JSImmediate::isEitherImmediate(v1, v2));
+ if (v1.isInt32() && v2.isInt32())
+ return v1.asInt32() < v2.asInt32();
- if (v1.asCell()->isString() && v2.asCell()->isString())
- return asString(v1)->value() == asString(v2)->value();
+ double n1;
+ double n2;
+ if (v1.getNumber(n1) && v2.getNumber(n2))
+ return n1 < n2;
- return v1 == v2;
+ JSGlobalData* globalData = &callFrame->globalData();
+ if (isJSString(globalData, v1) && isJSString(globalData, v2))
+ return asString(v1)->value() < asString(v2)->value();
+
+ JSValue p1;
+ JSValue 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();
+ }
+
+ inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
+ {
+ if (v1.isInt32() && v2.isInt32())
+ return v1.asInt32() <= v2.asInt32();
+
+ double n1;
+ double n2;
+ if (v1.getNumber(n1) && v2.getNumber(n2))
+ return n1 <= n2;
+
+ JSGlobalData* globalData = &callFrame->globalData();
+ if (isJSString(globalData, v1) && isJSString(globalData, v2))
+ return !(asString(v2)->value() < asString(v1)->value());
+
+ JSValue p1;
+ JSValue 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());
+ }
+
+ // 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
+
+ ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue 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.isInt32() ?
+ concatenate(asString(v1)->value().rep(), v2.asInt32()) :
+ 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);
+ }
+
+ inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset)
+ {
+ JSCell* cell = asCell(base);
+ size_t count = 0;
+
+ while (slotBase != cell) {
+ JSValue v = cell->structure()->prototypeForLookup(callFrame);
+
+ // If we didn't find slotBase in base's prototype chain, then base
+ // 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)->flattenDictionaryObject();
+ if (slotBase == cell)
+ slotOffset = cell->structure()->get(propertyName);
+ }
+
+ ++count;
+ }
+
+ ASSERT(count);
+ return count;
+ }
+
+ ALWAYS_INLINE JSValue resolveBase(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 JSValue();
+ }
+
+ ALWAYS_INLINE JSValue concatenateStrings(CallFrame* callFrame, Register* strings, unsigned count)
+ {
+ ASSERT(count >= 3);
+
+ // Estimate the amount of space required to hold the entire string. If all
+ // arguments are strings, we can easily calculate the exact amount of space
+ // required. For any other arguments, for now let's assume they may require
+ // 11 UChars of storage. This is enouch to hold any int, and likely is also
+ // reasonable for the other immediates. We may want to come back and tune
+ // this value at some point.
+ unsigned bufferSize = 0;
+ for (unsigned i = 0; i < count; ++i) {
+ JSValue v = strings[i].jsValue();
+ if (LIKELY(v.isString()))
+ bufferSize += asString(v)->value().size();
+ else
+ bufferSize += 11;
+ }
+
+ // Allocate an output string to store the result.
+ // If the first argument is a String, and if it has the capacity (or can grow
+ // its capacity) to hold the entire result then use this as a base to concatenate
+ // onto. Otherwise, allocate a new empty output buffer.
+ JSValue firstValue = strings[0].jsValue();
+ RefPtr<UString::Rep> resultRep;
+ if (firstValue.isString() && (resultRep = asString(firstValue)->value().rep())->reserveCapacity(bufferSize)) {
+ // We're going to concatenate onto the first string - remove it from the list of items to be appended.
+ ++strings;
+ --count;
+ } else
+ resultRep = UString::Rep::createEmptyBuffer(bufferSize);
+ UString result(resultRep);
+
+ // Loop over the openards, writing them into the output buffer.
+ for (unsigned i = 0; i < count; ++i) {
+ JSValue v = strings[i].jsValue();
+ if (LIKELY(v.isString()))
+ result.append(asString(v)->value());
+ else if (v.isInt32())
+ result.appendNumeric(v.asInt32());
+ else {
+ double d;
+ if (v.getNumber(d))
+ result.appendNumeric(d);
+ else
+ result.append(v.toString(callFrame));
+ }
+ }
+
+ return jsString(callFrame, result);
}
- JSValuePtr throwOutOfMemoryError(ExecState*);
+} // namespace JSC
-}
-#endif
+#endif // Operations_h
UString::Rep* key;
unsigned offset;
unsigned attributes;
+ JSCell* specificValue;
unsigned index;
- PropertyMapEntry(UString::Rep* key, unsigned attributes)
+ PropertyMapEntry(UString::Rep* key, unsigned attributes, JSCell* specificValue)
: key(key)
, offset(0)
, attributes(attributes)
+ , specificValue(specificValue)
, index(0)
{
}
- PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, unsigned index)
+ PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index)
: key(key)
, offset(offset)
, attributes(attributes)
+ , specificValue(specificValue)
, index(index)
{
}
namespace JSC {
-JSValuePtr PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
// Prevent getter functions from observing execution if an exception is pending.
if (exec->hadException())
#include "Identifier.h"
#include "JSValue.h"
-#include "JSImmediate.h"
#include "Register.h"
#include <wtf/Assertions.h>
#include <wtf/NotFound.h>
class PropertySlot {
public:
PropertySlot()
- : m_offset(WTF::notFound)
{
clearBase();
+ clearOffset();
clearValue();
}
- explicit PropertySlot(const JSValuePtr base)
+ explicit PropertySlot(const JSValue base)
: m_slotBase(base)
- , m_offset(WTF::notFound)
{
+ clearOffset();
clearValue();
}
- typedef JSValuePtr (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
+ typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
- JSValuePtr getValue(ExecState* exec, const Identifier& propertyName) const
+ JSValue 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_data.registerSlot).jsValue();
return m_getValue(exec, propertyName, *this);
}
- JSValuePtr getValue(ExecState* exec, unsigned propertyName) const
+ JSValue 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_data.registerSlot).jsValue();
return m_getValue(exec, Identifier::from(exec, propertyName), *this);
}
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)
+ void setValueSlot(JSValue* valueSlot)
{
ASSERT(valueSlot);
- m_getValue = JSC_VALUE_SLOT_MARKER;
clearBase();
+ clearOffset();
+ m_getValue = JSC_VALUE_SLOT_MARKER;
m_data.valueSlot = valueSlot;
}
- void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot)
+ void setValueSlot(JSValue slotBase, JSValue* valueSlot)
{
ASSERT(valueSlot);
m_getValue = JSC_VALUE_SLOT_MARKER;
m_data.valueSlot = valueSlot;
}
- void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot, size_t offset)
+ void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset)
{
ASSERT(valueSlot);
m_getValue = JSC_VALUE_SLOT_MARKER;
m_offset = offset;
}
- void setValue(JSValuePtr value)
+ void setValue(JSValue value)
{
ASSERT(value);
- m_getValue = JSC_VALUE_SLOT_MARKER;
clearBase();
+ clearOffset();
+ m_getValue = JSC_VALUE_SLOT_MARKER;
m_value = value;
m_data.valueSlot = &m_value;
}
void setRegisterSlot(Register* registerSlot)
{
ASSERT(registerSlot);
- m_getValue = JSC_REGISTER_SLOT_MARKER;
clearBase();
+ clearOffset();
+ m_getValue = JSC_REGISTER_SLOT_MARKER;
m_data.registerSlot = registerSlot;
}
- void setCustom(JSValuePtr slotBase, GetValueFunc getValue)
+ void setCustom(JSValue slotBase, GetValueFunc getValue)
{
ASSERT(slotBase);
ASSERT(getValue);
m_slotBase = slotBase;
}
- void setCustomIndex(JSValuePtr slotBase, unsigned index, GetValueFunc getValue)
+ void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue)
{
ASSERT(slotBase);
ASSERT(getValue);
void setUndefined()
{
- clearBase();
setValue(jsUndefined());
}
- JSValuePtr slotBase() const
+ JSValue slotBase() const
{
- ASSERT(m_slotBase);
return m_slotBase;
}
- void setBase(JSValuePtr base)
+ void setBase(JSValue base)
{
ASSERT(m_slotBase);
ASSERT(base);
void clearBase()
{
#ifndef NDEBUG
- m_slotBase = noValue();
+ m_slotBase = JSValue();
#endif
}
void clearValue()
{
#ifndef NDEBUG
- m_value = noValue();
+ m_value = JSValue();
#endif
}
+ void clearOffset()
+ {
+ // Clear offset even in release builds, in case this PropertySlot has been used before.
+ // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
+ m_offset = WTF::notFound;
+ }
+
unsigned index() const { return m_data.index; }
private:
- static JSValuePtr functionGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&);
GetValueFunc m_getValue;
- JSValuePtr m_slotBase;
+ JSValue m_slotBase;
union {
JSObject* getterFunc;
- JSValuePtr* valueSlot;
+ JSValue* valueSlot;
Register* registerSlot;
unsigned index;
} m_data;
- JSValuePtr m_value;
+ JSValue m_value;
size_t m_offset;
};
gcUnprotect(val);
}
- inline void gcProtect(JSValuePtr value)
+ inline void gcProtect(JSValue value)
{
if (value && value.isCell())
gcProtect(asCell(value));
}
- inline void gcUnprotect(JSValuePtr value)
+ inline void gcUnprotect(JSValue value)
{
if (value && value.isCell())
gcUnprotect(asCell(value));
T* get() const { return m_ptr; }
operator T*() const { return m_ptr; }
- operator JSValuePtr() const { return JSValuePtr(m_ptr); }
+ operator JSValue() const { return JSValue(m_ptr); }
T* operator->() const { return m_ptr; }
operator bool() const { return m_ptr; }
T* m_ptr;
};
- class ProtectedJSValuePtr {
+ class ProtectedJSValue {
public:
- ProtectedJSValuePtr() {}
- ProtectedJSValuePtr(JSValuePtr value);
- ProtectedJSValuePtr(const ProtectedJSValuePtr&);
- ~ProtectedJSValuePtr();
+ ProtectedJSValue() {}
+ ProtectedJSValue(JSValue value);
+ ProtectedJSValue(const ProtectedJSValue&);
+ ~ProtectedJSValue();
- template <class U> ProtectedJSValuePtr(const ProtectedPtr<U>&);
+ template <class U> ProtectedJSValue(const ProtectedPtr<U>&);
- JSValuePtr get() const { return m_value; }
- operator JSValuePtr() const { return m_value; }
- JSValuePtr operator->() const { return m_value; }
+ JSValue get() const { return m_value; }
+ operator JSValue() const { return m_value; }
+ JSValue operator->() const { return m_value; }
operator bool() const { return m_value; }
bool operator!() const { return !m_value; }
- ProtectedJSValuePtr& operator=(const ProtectedJSValuePtr&);
- ProtectedJSValuePtr& operator=(JSValuePtr);
+ ProtectedJSValue& operator=(const ProtectedJSValue&);
+ ProtectedJSValue& operator=(JSValue);
private:
- JSValuePtr m_value;
+ JSValue m_value;
};
template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr)
return *this;
}
- inline ProtectedJSValuePtr::ProtectedJSValuePtr(JSValuePtr value)
+ inline ProtectedJSValue::ProtectedJSValue(JSValue value)
: m_value(value)
{
gcProtect(m_value);
}
- inline ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedJSValuePtr& o)
+ inline ProtectedJSValue::ProtectedJSValue(const ProtectedJSValue& o)
: m_value(o.get())
{
gcProtect(m_value);
}
- inline ProtectedJSValuePtr::~ProtectedJSValuePtr()
+ inline ProtectedJSValue::~ProtectedJSValue()
{
gcUnprotect(m_value);
}
- template <class U> ProtectedJSValuePtr::ProtectedJSValuePtr(const ProtectedPtr<U>& o)
+ template <class U> ProtectedJSValue::ProtectedJSValue(const ProtectedPtr<U>& o)
: m_value(o.get())
{
gcProtect(m_value);
}
- inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(const ProtectedJSValuePtr& o)
+ inline ProtectedJSValue& ProtectedJSValue::operator=(const ProtectedJSValue& o)
{
- JSValuePtr ovalue = o.m_value;
+ JSValue ovalue = o.m_value;
gcProtect(ovalue);
gcUnprotect(m_value);
m_value = ovalue;
return *this;
}
- inline ProtectedJSValuePtr& ProtectedJSValuePtr::operator=(JSValuePtr ovalue)
+ inline ProtectedJSValue& ProtectedJSValue::operator=(JSValue ovalue)
{
gcProtect(ovalue);
gcUnprotect(m_value);
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(); }
+ inline bool operator==(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() == b.get(); }
+ inline bool operator==(const ProtectedJSValue& a, const JSValue b) { return a.get() == b; }
+ template <class T> inline bool operator==(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() == JSValue(b.get()); }
+ inline bool operator==(const JSValue a, const ProtectedJSValue& b) { return a == b.get(); }
+ template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) == b.get(); }
+
+ inline bool operator!=(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() != b.get(); }
+ inline bool operator!=(const ProtectedJSValue& a, const JSValue b) { return a.get() != b; }
+ template <class T> inline bool operator!=(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() != JSValue(b.get()); }
+ inline bool operator!=(const JSValue a, const ProtectedJSValue& b) { return a != b.get(); }
+ template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) != b.get(); }
} // namespace JSC
namespace JSC {
class JSObject;
+ class JSFunction;
class PutPropertySlot {
public:
- enum Type { Invalid, ExistingProperty, NewProperty };
+ enum Type { Uncachable, ExistingProperty, NewProperty };
PutPropertySlot()
- : m_type(Invalid)
+ : m_type(Uncachable)
, m_base(0)
- , m_wasTransition(false)
{
}
Type type() const { return m_type; }
JSObject* base() const { return m_base; }
- bool isCacheable() const { return m_type != Invalid; }
+ bool isCacheable() const { return m_type != Uncachable; }
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;
};
/*
* Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
* Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#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>
+
+#if ENABLE(YARR)
+
+#include "yarr/RegexCompiler.h"
+#if ENABLE(YARR_JIT)
+#include "yarr/RegexJIT.h"
+#else
+#include "yarr/RegexInterpreter.h"
+#endif
+
+#else
+
+#if ENABLE(WREC)
+#include "JIT.h"
+#include "WRECGenerator.h"
+#endif
+#include <pcre/pcre.h>
+
+#endif
+
namespace JSC {
#if ENABLE(WREC)
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));
+ compile(globalData);
}
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)
{
// 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) {
+ if (flags.find('i') != -1)
m_flagBits |= IgnoreCase;
- ignoreCaseOption = JSRegExpIgnoreCase;
- }
-
- JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
- if (flags.find('m') != -1) {
+ 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);
+ compile(globalData);
+}
+
+#if !ENABLE(YARR)
+RegExp::~RegExp()
+{
+ jsRegExpFree(m_regExp);
+}
#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)
+{
+ return adoptRef(new RegExp(globalData, pattern));
}
PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
return adoptRef(new RegExp(globalData, pattern, flags));
}
-RegExp::~RegExp()
+#if ENABLE(YARR)
+
+void RegExp::compile(JSGlobalData* globalData)
{
- jsRegExpFree(m_regExp);
+#if ENABLE(YARR_JIT)
+ Yarr::jitCompileRegex(globalData, m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline());
+#else
+ UNUSED_PARAM(globalData);
+ m_regExpBytecode.set(Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline()));
+#endif
}
-int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
+int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
+{
+ if (startOffset < 0)
+ startOffset = 0;
+ if (ovector)
+ ovector->clear();
+
+ if (startOffset > s.size() || s.isNull())
+ return -1;
+
+#if ENABLE(YARR_JIT)
+ if (!!m_regExpJITCode) {
+#else
+ if (m_regExpBytecode) {
+#endif
+ int offsetVectorSize = (m_numSubpatterns + 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
+ int* offsetVector;
+ Vector<int, 32> nonReturnedOvector;
+ if (ovector) {
+ ovector->resize(offsetVectorSize);
+ offsetVector = ovector->data();
+ } else {
+ nonReturnedOvector.resize(offsetVectorSize);
+ offsetVector = nonReturnedOvector.data();
+ }
+
+ ASSERT(offsetVector);
+ for (int j = 0; j < offsetVectorSize; ++j)
+ offsetVector[j] = -1;
+
+
+#if ENABLE(YARR_JIT)
+ int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize);
+#else
+ int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.data(), startOffset, s.size(), offsetVector);
+#endif
+
+ 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;
+ }
+
+ return -1;
+}
+
+#else
+
+void RegExp::compile(JSGlobalData* globalData)
+{
+ m_regExp = 0;
+#if ENABLE(WREC)
+ m_wrecFunction = Generator::compileRegExp(globalData, m_pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, ignoreCase(), multiline());
+ if (m_wrecFunction || m_constructionError)
+ return;
+ // Fall through to non-WREC case.
+#else
+ UNUSED_PARAM(globalData);
+#endif
+
+ JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase;
+ JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine;
+ m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+}
+
+int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
{
if (startOffset < 0)
startOffset = 0;
#if ENABLE(WREC)
if (m_wrecFunction) {
int offsetVectorSize = (m_numSubpatterns + 1) * 2;
- int* offsetVector = new int [offsetVectorSize];
+ int* offsetVector;
+ Vector<int, 32> nonReturnedOvector;
+ if (ovector) {
+ ovector->resize(offsetVectorSize);
+ offsetVector = ovector->data();
+ } else {
+ nonReturnedOvector.resize(offsetVectorSize);
+ offsetVector = nonReturnedOvector.data();
+ }
+ ASSERT(offsetVector);
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) {
offsetVector = fixedSizeOffsetVector;
} else {
offsetVectorSize = (m_numSubpatterns + 1) * 3;
- offsetVector = new int [offsetVectorSize];
- ovector->set(offsetVector);
+ ovector->resize(offsetVectorSize);
+ offsetVector = ovector->data();
}
int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
return -1;
}
+#endif
+
} // namespace JSC
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "ExecutableAllocator.h"
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
+#include "yarr/RegexJIT.h"
+#include "yarr/RegexInterpreter.h"
struct JSRegExp;
public:
static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern);
static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+#if !ENABLE(YARR)
~RegExp();
+#endif
bool global() const { return m_flagBits & Global; }
bool ignoreCase() const { return m_flagBits & IgnoreCase; }
bool isValid() const { return !m_constructionError; }
const char* errorMessage() const { return m_constructionError; }
- int match(const UString&, int startOffset, OwnArrayPtr<int>* ovector = 0);
+ int match(const UString&, int startOffset, Vector<int, 32>* 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();
+ void compile(JSGlobalData*);
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(YARR_JIT)
+ Yarr::RegexCodeBlock m_regExpJITCode;
+#elif ENABLE(YARR)
+ OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
+#else
#if ENABLE(WREC)
WREC::CompiledRegExp m_wrecFunction;
RefPtr<ExecutablePool> m_executablePool;
+#endif
+ JSRegExp* m_regExp;
#endif
};
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
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);
+static JSValue regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&);
+
+static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue);
+static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue);
} // namespace JSC
RegExpConstructorPrivate()
: lastNumSubPatterns(0)
, multiline(false)
+ , lastOvectorIndex(0)
{
}
+ const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
+ Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
+ Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
+ void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
+
UString input;
UString lastInput;
- OwnArrayPtr<int> lastOvector;
- unsigned lastNumSubPatterns : 31;
+ Vector<int, 32> ovector[2];
+ unsigned lastNumSubPatterns : 30;
bool multiline : 1;
+ unsigned lastOvectorIndex : 1;
};
RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
*/
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);
+ position = r->match(s, startOffset, &d->tempOvector());
if (ovector)
- *ovector = tmpOvector.get();
+ *ovector = d->tempOvector().data();
if (position != -1) {
- ASSERT(tmpOvector);
+ ASSERT(!d->tempOvector().isEmpty());
- length = tmpOvector[1] - tmpOvector[0];
+ length = d->tempOvector()[1] - d->tempOvector()[0];
d->input = s;
d->lastInput = s;
- d->lastOvector.set(tmpOvector.release());
+ d->changeLastOvector();
d->lastNumSubPatterns = r->numSubpatterns();
}
}
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->lastOvector().resize(offsetVectorSize);
+ memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int));
// d->multiline is not needed, and remains uninitialized
setLazyCreationData(d);
unsigned lastNumSubpatterns = d->lastNumSubPatterns;
for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
- int start = d->lastOvector[2 * 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));
+ 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().index, jsNumber(exec, d->lastOvector()[0]), slot);
JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot);
delete d;
return new (exec) RegExpMatchesArray(exec, d.get());
}
-JSValuePtr RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
+JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
{
- if (d->lastOvector && i <= d->lastNumSubPatterns) {
- int start = d->lastOvector[2 * i];
+ if (!d->lastOvector().isEmpty() && 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 jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
}
return jsEmptyString(exec);
}
-JSValuePtr RegExpConstructor::getLastParen(ExecState* exec) const
+JSValue RegExpConstructor::getLastParen(ExecState* exec) const
{
unsigned i = d->lastNumSubPatterns;
if (i > 0) {
- ASSERT(d->lastOvector);
- int start = d->lastOvector[2 * i];
+ ASSERT(!d->lastOvector().isEmpty());
+ int start = d->lastOvector()[2 * i];
if (start >= 0)
- return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+ return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
}
return jsEmptyString(exec);
}
-JSValuePtr RegExpConstructor::getLeftContext(ExecState* exec) const
+JSValue RegExpConstructor::getLeftContext(ExecState* exec) const
{
- if (d->lastOvector)
- return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]);
+ if (!d->lastOvector().isEmpty())
+ return jsSubstring(exec, d->lastInput, 0, d->lastOvector()[0]);
return jsEmptyString(exec);
}
-JSValuePtr RegExpConstructor::getRightContext(ExecState* exec) const
+JSValue RegExpConstructor::getRightContext(ExecState* exec) const
{
- if (d->lastOvector)
- return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]);
+ if (!d->lastOvector().isEmpty())
+ return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.size() - d->lastOvector()[1]);
return jsEmptyString(exec);
}
return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
}
-JSValuePtr regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
}
-JSValuePtr regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2);
}
-JSValuePtr regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3);
}
-JSValuePtr regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4);
}
-JSValuePtr regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5);
}
-JSValuePtr regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6);
}
-JSValuePtr regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7);
}
-JSValuePtr regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8);
}
-JSValuePtr regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9);
}
-JSValuePtr regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return jsString(exec, asRegExpConstructor(slot.slotBase())->input());
}
-JSValuePtr regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline());
}
-JSValuePtr regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0);
}
-JSValuePtr regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getLastParen(exec);
}
-JSValuePtr regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getLeftContext(exec);
}
-JSValuePtr regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue 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)
+void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot);
}
-void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
{
asRegExpConstructor(baseObject)->setInput(value.toString(exec));
}
-void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue 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);
+ JSValue arg0 = args.at(0);
+ JSValue arg1 = args.at(1);
if (arg0.isObject(&RegExpObject::info)) {
if (!arg1.isUndefined())
}
// ECMA 15.10.3
-static JSValuePtr callRegExpConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
return constructRegExp(exec, args);
}
public:
RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*);
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
}
- virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
static const ClassInfo info;
void setMultiline(bool);
bool multiline() const;
- JSValuePtr getBackref(ExecState*, unsigned) const;
- JSValuePtr getLastParen(ExecState*) const;
- JSValuePtr getLeftContext(ExecState*) const;
- JSValuePtr getRightContext(ExecState*) const;
+ JSValue getBackref(ExecState*, unsigned) const;
+ JSValue getLastParen(ExecState*) const;
+ JSValue getLeftContext(ExecState*) const;
+ JSValue getRightContext(ExecState*) const;
private:
virtual ConstructType getConstructData(ConstructData&);
OwnPtr<RegExpConstructorPrivate> d;
};
- RegExpConstructor* asRegExpConstructor(JSValuePtr);
+ RegExpConstructor* asRegExpConstructor(JSValue);
JSObject* constructRegExp(ExecState*, const ArgList&);
- inline RegExpConstructor* asRegExpConstructor(JSValuePtr value)
+ inline RegExpConstructor* asRegExpConstructor(JSValue value)
{
ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
return static_cast<RegExpConstructor*>(asObject(value));
return JSArray::getOwnPropertySlot(exec, propertyName, slot);
}
- virtual void put(ExecState* exec, const Identifier& propertyName, JSValuePtr v, PutPropertySlot& slot)
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
{
if (lazyCreationData())
fillArrayInstance(exec);
JSArray::put(exec, propertyName, v, slot);
}
- virtual void put(ExecState* exec, unsigned propertyName, JSValuePtr v)
+ virtual void put(ExecState* exec, unsigned propertyName, JSValue v)
{
if (lazyCreationData())
fillArrayInstance(exec);
#include "config.h"
#include "RegExpObject.h"
+#include "Error.h"
#include "JSArray.h"
#include "JSGlobalObject.h"
#include "JSString.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);
+static JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
+static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
} // namespace JSC
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
}
-JSValuePtr regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
+JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
}
-JSValuePtr regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
+JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase());
}
-JSValuePtr regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline());
}
-JSValuePtr regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
+JSValue 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)
+JSValue 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)
+void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
}
-void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValuePtr value)
+void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
{
asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec));
}
-JSValuePtr RegExpObject::test(ExecState* exec, const ArgList& args)
+JSValue RegExpObject::test(ExecState* exec, const ArgList& args)
{
return jsBoolean(match(exec, args));
}
-JSValuePtr RegExpObject::exec(ExecState* exec, const ArgList& args)
+JSValue 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)
+static JSValue JSC_HOST_CALL callRegExpObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
{
return asRegExpObject(function)->exec(exec, args);
}
{
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
- UString input = args.isEmpty() ? regExpConstructor->input() : args.at(exec, 0).toString(exec);
+ UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec);
if (input.isNull()) {
throwError(exec, GeneralError, "No input to " + toString(exec) + ".");
return false;
void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; }
double lastIndex() const { return d->lastIndex; }
- JSValuePtr test(ExecState*, const ArgList&);
- JSValuePtr exec(ExecState*, const ArgList&);
+ JSValue test(ExecState*, const ArgList&);
+ JSValue exec(ExecState*, const ArgList&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
OwnPtr<RegExpObjectData> d;
};
- RegExpObject* asRegExpObject(JSValuePtr);
+ RegExpObject* asRegExpObject(JSValue);
- inline RegExpObject* asRegExpObject(JSValuePtr value)
+ inline RegExpObject* asRegExpObject(JSValue value)
{
ASSERT(asObject(value)->inherits(&RegExpObject::info));
return static_cast<RegExpObject*>(asObject(value));
#include "ArrayPrototype.h"
#include "JSArray.h"
+#include "JSFunction.h"
#include "JSObject.h"
#include "JSString.h"
#include "JSValue.h"
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&);
+static JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
// ECMA 15.10.5
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
}
// ------------------------------ Functions ---------------------------
-JSValuePtr regExpProtoFuncTest(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue 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)
+JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue 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);
+ JSValue arg0 = args.at(0);
+ JSValue arg1 = args.at(1);
if (arg0.isObject(&RegExpObject::info)) {
if (!arg1.isUndefined())
return jsUndefined();
}
-JSValuePtr regExpProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
if (!thisValue.isObject(&RegExpObject::info)) {
if (thisValue.isObject(&RegExpPrototype::info))
#ifndef ScopeChain_h
#define ScopeChain_h
-#include <wtf/Assertions.h>
+#include "FastAllocBase.h"
namespace JSC {
class JSObject;
class ScopeChainIterator;
- class ScopeChainNode {
+ class ScopeChainNode : public FastAllocBase {
public:
ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
: next(next)
{
ASSERT(globalData);
}
+#ifndef NDEBUG
+ // Due to the number of subtle and timing dependent bugs that have occurred due
+ // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the
+ // contents in debug builds.
+ ~ScopeChainNode()
+ {
+ next = 0;
+ object = 0;
+ globalData = 0;
+ globalThis = 0;
+ }
+#endif
ScopeChainNode* next;
JSObject* object;
{
if (m_node)
m_node->deref();
+#ifndef NDEBUG
+ m_node = 0;
+#endif
}
void swap(ScopeChain&);
};
SmallStringsStorage::SmallStringsStorage()
+ : m_base(m_characters, numCharactersToStore)
{
- 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();
+ for (unsigned i = 0; i < numCharactersToStore; ++i)
+ m_characters[i] = i;
+
memset(&m_reps, 0, sizeof(m_reps));
for (unsigned i = 0; i < numCharactersToStore; ++i) {
m_reps[i].offset = i;
#include "config.h"
#include "StringConstructor.h"
+#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "PrototypeFunction.h"
#include "StringPrototype.h"
namespace JSC {
-static NEVER_INLINE JSValuePtr stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
+static NEVER_INLINE JSValue 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));
+ *p++ = static_cast<UChar>((*it).toUInt32(exec));
return jsString(exec, UString(buf, p - buf, false));
}
-static JSValuePtr stringFromCharCode(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (LIKELY(args.size() == 1))
- return jsSingleCharacterString(exec, args.at(exec, 0).toUInt32(exec));
+ return jsSingleCharacterString(exec, args.at(0).toUInt32(exec));
return stringFromCharCodeSlowCase(exec, args);
}
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);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
// no. of arguments for constructor
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
{
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));
+ return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(0).toString(exec));
}
ConstructType StringConstructor::getConstructData(ConstructData& constructData)
}
// ECMA 15.5.1
-static JSValuePtr callStringConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
+static JSValue JSC_HOST_CALL callStringConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (args.isEmpty())
return jsEmptyString(exec);
- return jsString(exec, args.at(exec, 0).toString(exec));
+ return jsString(exec, args.at(0).toString(exec));
}
CallType StringConstructor::getCallData(CallData& callData)
return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
-void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (propertyName == exec->propertyNames().length)
return;
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 void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
+ static const JS_EXPORTDATA ClassInfo info;
JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
virtual JSString* toThisJSString(ExecState*);
};
- StringObject* asStringObject(JSValuePtr);
+ StringObject* asStringObject(JSValue);
- inline StringObject* asStringObject(JSValuePtr value)
+ inline StringObject* asStringObject(JSValue value)
{
ASSERT(asObject(value)->inherits(&StringObject::info));
return static_cast<StringObject*>(asObject(value));
{
}
- static PassRefPtr<Structure> createStructure(JSValuePtr proto)
+ static PassRefPtr<Structure> createStructure(JSValue proto)
{
return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined));
}
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "config.h"
#include "StringPrototype.h"
+#include "CachedCall.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "ObjectPrototype.h"
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&);
+static JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue, const ArgList&);
+
+static JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&);
}
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)
+JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
JSString* sourceVal = thisValue.toThisJSString(exec);
const UString& source = sourceVal->value();
- JSValuePtr pattern = args.at(exec, 0);
+ JSValue pattern = args.at(0);
- JSValuePtr replacement = args.at(exec, 1);
+ JSValue replacement = args.at(1);
UString replacementString;
CallData callData;
CallType callType = replacement.getCallData(callData);
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 (global && callType == CallTypeJS) {
+ // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
+ int argCount = reg->numSubpatterns() + 1 + 2;
+ JSFunction* func = asFunction(replacement);
+ CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
+ if (exec->hadException())
+ return jsNull();
+ while (true) {
+ 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) {
+ unsigned i = 0;
+ for (; i < reg->numSubpatterns() + 1; ++i) {
int matchStart = ovector[i * 2];
int matchLen = ovector[i * 2 + 1] - matchStart;
if (matchStart < 0)
- args.append(jsUndefined());
+ cachedCall.setArgument(i, jsUndefined());
else
- args.append(jsSubstring(exec, source, matchStart, matchLen));
+ cachedCall.setArgument(i, 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));
+ cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
+ cachedCall.setArgument(i++, sourceVal);
+
+ cachedCall.setThis(exec->globalThisValue());
+ replacements.append(cachedCall.call().toString(cachedCall.newCallFrame()));
if (exec->hadException())
break;
- } else
- replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
- lastIndex = matchIndex + matchLen;
- startPosition = lastIndex;
+ lastIndex = matchIndex + matchLen;
+ startPosition = lastIndex;
- // special case of empty match
- if (matchLen == 0) {
- startPosition++;
- if (startPosition > source.size())
+ // special case of empty match
+ if (matchLen == 0) {
+ startPosition++;
+ if (startPosition > source.size())
+ break;
+ }
+ }
+ } else {
+ do {
+ int matchIndex;
+ int matchLen;
+ int* ovector;
+ regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+ if (matchIndex < 0)
break;
- }
- } while (global);
- if (lastIndex < source.size())
- sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
+ sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
+
+ if (callType != CallTypeNone) {
+ int completeMatchStart = ovector[0];
+ MarkedArgumentBuffer 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));
+ }
- UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
+ args.append(jsNumber(exec, completeMatchStart));
+ args.append(sourceVal);
- if (result == source)
+ 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 && replacements.isEmpty())
return sourceVal;
- return jsString(exec, result);
+ if (lastIndex < source.size())
+ sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
+
+ return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(),
+ replacements.data(), replacements.size()));
}
- // First arg is a string
+ // Not a regular expression, so treat the pattern as a string.
+
UString patternString = pattern.toString(exec);
int matchPos = source.find(patternString);
- int matchLen = patternString.size();
- // Do the replacement
+
if (matchPos == -1)
return sourceVal;
+ int matchLen = patternString.size();
if (callType != CallTypeNone) {
- ArgList args;
+ MarkedArgumentBuffer args;
args.append(jsSubstring(exec, source, matchPos, matchLen));
args.append(jsNumber(exec, matchPos));
args.append(sourceVal);
}
int ovector[2] = { matchPos, matchPos + matchLen };
- return jsString(exec, source.substr(0, matchPos)
- + substituteBackreferences(replacementString, source, ovector, 0)
- + source.substr(matchPos + matchLen));
+ return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)));
}
-JSValuePtr stringProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
// Also used for valueOf.
return throwError(exec, TypeError);
}
-JSValuePtr stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue 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();
+ JSValue a0 = args.at(0);
+ if (a0.isUInt32()) {
+ uint32_t i = a0.asUInt32();
if (i < len)
return jsSingleCharacterSubstring(exec, s, i);
return jsEmptyString(exec);
return jsEmptyString(exec);
}
-JSValuePtr stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue 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();
+ JSValue a0 = args.at(0);
+ if (a0.isUInt32()) {
+ uint32_t i = a0.asUInt32();
if (i < len)
return jsNumber(exec, s.data()[i]);
return jsNaN(exec);
return jsNaN(exec);
}
-JSValuePtr stringProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue 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);
+ s += (*it).toString(exec);
return jsString(exec, s);
}
-JSValuePtr stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue 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);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(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 if (a1.isUInt32())
+ pos = min<uint32_t>(a1.asUInt32(), len);
else {
double dpos = a1.toInteger(exec);
if (dpos < 0)
return jsNumber(exec, s.find(u2, pos));
}
-JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue 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);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(1);
UString u2 = a0.toString(exec);
double dpos = a1.toIntegerPreserveNaN(exec);
return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
}
-JSValuePtr stringProtoFuncMatch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
UString u = s;
RefPtr<RegExp> reg;
}
// return array of matches
- ArgList list;
+ MarkedArgumentBuffer list;
int lastIndex = 0;
while (pos >= 0) {
list.append(jsSubstring(exec, u, pos, matchLength));
return constructArray(exec, list);
}
-JSValuePtr stringProtoFuncSearch(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
UString u = s;
RefPtr<RegExp> reg;
return jsNumber(exec, pos);
}
-JSValuePtr stringProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue 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);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(1);
// The arg processing is very much like ArrayProtoFunc::Slice
double start = a0.toInteger(exec);
return jsEmptyString(exec);
}
-JSValuePtr stringProtoFuncSplit(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
- JSValuePtr a1 = args.at(exec, 1);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(1);
JSArray* result = constructEmptyArray(exec);
unsigned i = 0;
}
int pos = 0;
while (i != limit && pos < s.size()) {
- OwnArrayPtr<int> ovector;
+ Vector<int, 32> ovector;
int mpos = reg->match(s, pos, &ovector);
if (mpos < 0)
break;
return result;
}
-JSValuePtr stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue 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);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(1);
double start = a0.toInteger(exec);
double length = a1.isUndefined() ? len : a1.toInteger(exec);
return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length));
}
-JSValuePtr stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue 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);
+ JSValue a0 = args.at(0);
+ JSValue a1 = args.at(1);
double start = a0.toNumber(exec);
double end = a1.toNumber(exec);
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&)
+JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
JSString* sVal = thisValue.toThisJSString(exec);
const UString& s = sVal->value();
return jsString(exec, UString(buffer.releaseBuffer(), length, false));
}
-JSValuePtr stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
JSString* sVal = thisValue.toThisJSString(exec);
const UString& s = sVal->value();
return jsString(exec, UString(buffer.releaseBuffer(), length, false));
}
-JSValuePtr stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
if (args.size() < 1)
return jsNumber(exec, 0);
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
return jsNumber(exec, localeCompare(s, a0.toString(exec)));
}
-JSValuePtr stringProtoFuncBig(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<big>" + s + "</big>");
}
-JSValuePtr stringProtoFuncSmall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<small>" + s + "</small>");
}
-JSValuePtr stringProtoFuncBlink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<blink>" + s + "</blink>");
}
-JSValuePtr stringProtoFuncBold(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<b>" + s + "</b>");
}
-JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsString(exec, "<tt>" + s + "</tt>");
}
-JSValuePtr stringProtoFuncItalics(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<i>" + s + "</i>");
}
-JSValuePtr stringProtoFuncStrike(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<strike>" + s + "</strike>");
}
-JSValuePtr stringProtoFuncSub(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<sub>" + s + "</sub>");
}
-JSValuePtr stringProtoFuncSup(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
+JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
UString s = thisValue.toThisString(exec);
return jsNontrivialString(exec, "<sup>" + s + "</sup>");
}
-JSValuePtr stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
}
-JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
uint32_t smallInteger;
if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
}
-JSValuePtr stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
}
-JSValuePtr stringProtoFuncLink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
+JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
UString s = thisValue.toThisString(exec);
- JSValuePtr a0 = args.at(exec, 0);
+ JSValue a0 = args.at(0);
UString linkText = a0.toString(exec);
unsigned linkTextSize = linkText.size();
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
static WTF::RefCountedLeakCounter structureCounter("Structure");
#if ENABLE(JSC_MULTIPLE_THREADS)
-static Mutex ignoreSetMutex;
+static Mutex& ignoreSetMutex = *(new Mutex);
#endif
static bool shouldIgnoreLeaks;
-static HashSet<Structure*> ignoreSet;
+static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>);
#endif
#if DUMP_STRUCTURE_ID_STATISTICS
-static HashSet<Structure*> liveStructureSet;
+static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>);
#endif
+static int comparePropertyMapEntryIndices(const void* a, const void* b);
+
void Structure::dumpStatistics()
{
#if DUMP_STRUCTURE_ID_STATISTICS
#endif
}
-Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo)
+Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
: m_typeInfo(typeInfo)
, m_prototype(prototype)
+ , m_specificValueInPrevious(0)
, m_propertyTable(0)
, m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
, m_offset(noOffset)
- , m_isDictionary(false)
+ , m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
, m_usingSingleTransitionSlot(true)
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));
+ ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious));
+ m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
}
}
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);
+ PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
insertIntoPropertyMapHashTable(entry);
}
}
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
- bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
if (shouldCache && m_cachedPropertyNameArrayData) {
if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
}
if (shouldCache) {
+ StructureChain* protoChain = prototypeChain(exec);
m_cachedPropertyNameArrayData = propertyNames.data();
- m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec));
+ if (!protoChain->isCacheable())
+ return;
+ m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
m_cachedPropertyNameArrayData->setCachedStructure(this);
}
}
m_propertyStorageCapacity *= 2;
}
-PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
+void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
+{
+ const UString::Rep* rep = propertyName._ustring.rep();
+
+ materializePropertyMapIfNecessary();
+
+ ASSERT(isDictionary());
+ ASSERT(m_propertyTable);
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ ASSERT(entryIndex != emptyEntryIndex);
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return;
+ }
+
+#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];
+ ASSERT(entryIndex != emptyEntryIndex);
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return;
+ }
+ }
+}
+
+PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->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) {
+ if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
+ && existingTransition->m_attributesInPrevious == attributes
+ && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0)) {
+
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))) {
+ if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
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)
+PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
- ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
+ ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
if (structure->transitionCount() > s_maxTransitionLength) {
- RefPtr<Structure> transition = toDictionaryTransition(structure);
- offset = transition->put(propertyName, attributes);
+ RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
+ ASSERT(structure != transition);
+ offset = transition->put(propertyName, attributes, specificValue);
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_specificValueInPrevious = specificValue;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
transition->createPropertyMapHashTable();
}
- offset = transition->put(propertyName, attributes);
+ offset = transition->put(propertyName, attributes, specificValue);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
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);
+ transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
}
- structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
+ structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
return transition.release();
}
PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = toDictionaryTransition(structure);
+ RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
offset = transition->remove(propertyName);
return transition.release();
}
-PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValuePtr prototype)
+PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
{
RefPtr<Structure> transition = create(prototype, structure->typeInfo());
return transition.release();
}
+PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
+{
+ RefPtr<Structure> transition = create(structure->storedPrototype(), 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;
+
+ bool removed = transition->despecifyFunction(replaceFunction);
+ ASSERT_UNUSED(removed, removed);
+
+ return transition.release();
+}
+
PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
{
RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
return transition.release();
}
-PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure)
+PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
{
- ASSERT(!structure->m_isDictionary);
-
+ ASSERT(!structure->isUncacheableDictionary());
+
RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
- transition->m_isDictionary = true;
+ transition->m_dictionaryKind = kind;
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)
+PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
{
- ASSERT(structure->m_isDictionary);
+ return toDictionaryTransition(structure, CachedDictionaryKind);
+}
- // 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.
+PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
+{
+ return toDictionaryTransition(structure, UncachedDictionaryKind);
+}
- // 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;
+PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
+{
+ ASSERT(isDictionary());
+ if (isUncacheableDictionary()) {
+ ASSERT(m_propertyTable);
+ Vector<PropertyMapEntry*> sortedPropertyEntries(m_propertyTable->keyCount);
+ PropertyMapEntry** p = sortedPropertyEntries.data();
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; i++) {
+ if (m_propertyTable->entries()[i].key)
+ *p++ = &m_propertyTable->entries()[i];
+ }
+ size_t propertyCount = p - sortedPropertyEntries.data();
+ qsort(sortedPropertyEntries.data(), propertyCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
+ sortedPropertyEntries.resize(propertyCount);
+
+ // We now have the properties currently defined on this object
+ // in the order that they are expected to be in, but we need to
+ // reorder the storage, so we have to copy the current values out
+ Vector<JSValue> values(propertyCount);
+ // FIXME: Remove this workaround with the next merge.
+ unsigned anonymousSlotCount = 0;
+ for (unsigned i = 0; i < propertyCount; i++) {
+ PropertyMapEntry* entry = sortedPropertyEntries[i];
+ values[i] = object->getDirectOffset(entry->offset);
+ // Update property table to have the new property offsets
+ entry->offset = anonymousSlotCount + i;
+ entry->index = i;
+ }
+
+ // Copy the original property values into their final locations
+ for (unsigned i = 0; i < propertyCount; i++)
+ object->putDirectOffset(anonymousSlotCount + i, values[i]);
+
+ if (m_propertyTable->deletedOffsets) {
+ delete m_propertyTable->deletedOffsets;
+ m_propertyTable->deletedOffsets = 0;
+ }
+ }
- return structure;
+ m_dictionaryKind = NoneDictionaryKind;
+ return this;
}
-size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes)
+size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!m_transitions.singleTransition);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
- size_t offset = put(propertyName, attributes);
+ size_t offset = put(propertyName, attributes, specificValue);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
clearEnumerationCache();
size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
{
- ASSERT(!m_transitions.singleTransition);
- ASSERT(m_isDictionary);
+ ASSERT(isUncacheableDictionary());
materializePropertyMapIfNecessary();
return newTable;
}
-size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
+size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue)
{
- ASSERT(!propertyName.isNull());
-
materializePropertyMapIfNecessary();
if (!m_propertyTable)
return notFound;
- UString::Rep* rep = propertyName._ustring.rep();
-
unsigned i = rep->computedHash();
#if DUMP_PROPERTYMAP_STATS
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
return m_propertyTable->entries()[entryIndex - 1].offset;
}
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
return m_propertyTable->entries()[entryIndex - 1].offset;
}
}
}
-size_t Structure::put(const Identifier& propertyName, unsigned attributes)
+bool Structure::despecifyFunction(const Identifier& propertyName)
+{
+ ASSERT(!propertyName.isNull());
+
+ materializePropertyMapIfNecessary();
+ if (!m_propertyTable)
+ return false;
+
+ 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 false;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return true;
+ }
+
+#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 false;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return true;
+ }
+ }
+}
+
+size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!propertyName.isNull());
ASSERT(get(propertyName) == notFound);
rep->ref();
m_propertyTable->entries()[entryIndex - 1].key = rep;
m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
+ m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue;
m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
unsigned newOffset;
return newOffset;
}
+bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
+{
+ if (m_usingSingleTransitionSlot) {
+ return m_transitions.singleTransition
+ && m_transitions.singleTransition->m_nameInPrevious == rep
+ && m_transitions.singleTransition->m_attributesInPrevious == attributes;
+ }
+ return m_transitions.table->hasTransition(make_pair(rep, attributes));
+}
+
size_t Structure::remove(const Identifier& propertyName)
{
ASSERT(!propertyName.isNull());
key->deref();
m_propertyTable->entries()[entryIndex - 1].key = 0;
m_propertyTable->entries()[entryIndex - 1].attributes = 0;
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
m_propertyTable->entries()[entryIndex - 1].offset = 0;
if (!m_propertyTable->deletedOffsets)
checkConsistency();
}
-static int comparePropertyMapEntryIndices(const void* a, const void* b)
+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;
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))
class Structure : public RefCounted<Structure> {
public:
friend class JIT;
- static PassRefPtr<Structure> create(JSValuePtr prototype, const TypeInfo& typeInfo)
+ static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo)
{
return adoptRef(new Structure(prototype, typeInfo));
}
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> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+ static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
- static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValuePtr prototype);
+ static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
+ static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
static PassRefPtr<Structure> getterSetterTransition(Structure*);
- static PassRefPtr<Structure> toDictionaryTransition(Structure*);
- static PassRefPtr<Structure> fromDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
+
+ PassRefPtr<Structure> flattenDictionaryStructure(JSObject*);
~Structure();
}
// These should be used with caution.
- size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes);
+ size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t removePropertyWithoutTransition(const Identifier& propertyName);
- void setPrototypeWithoutTransition(JSValuePtr prototype) { m_prototype = prototype; }
-
- bool isDictionary() const { return m_isDictionary; }
+ void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
+
+ bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
+ bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
const TypeInfo& typeInfo() const { return m_typeInfo; }
- JSValuePtr storedPrototype() const { return m_prototype; }
- JSValuePtr prototypeForLookup(ExecState*) const;
+ JSValue storedPrototype() const { return m_prototype; }
+ JSValue 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; }
+ bool isUsingInlineStorage() const;
size_t get(const Identifier& propertyName);
- size_t get(const Identifier& propertyName, unsigned& attributes);
+ size_t get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue);
+ size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
+ {
+ ASSERT(!propertyName.isNull());
+ return get(propertyName.ustring().rep(), attributes, specificValue);
+ }
+ bool transitionedFor(const JSCell* specificValue)
+ {
+ return m_specificValueInPrevious == specificValue;
+ }
+ bool hasTransition(UString::Rep*, unsigned attributes);
+ bool hasTransition(const Identifier& propertyName, unsigned attributes)
+ {
+ return hasTransition(propertyName._ustring.rep(), attributes);
+ }
+
void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
- private:
- Structure(JSValuePtr prototype, const TypeInfo&);
+ JSCell* specificValue() { return m_specificValueInPrevious; }
+ void despecifyDictionaryFunction(const Identifier& propertyName);
- size_t put(const Identifier& propertyName, unsigned attributes);
+ private:
+ Structure(JSValue prototype, const TypeInfo&);
+
+ typedef enum {
+ NoneDictionaryKind = 0,
+ CachedDictionaryKind = 1,
+ UncachedDictionaryKind = 2
+ } DictionaryKind;
+ static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
+
+ size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t remove(const Identifier& propertyName);
void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
void insertIntoPropertyMapHashTable(const PropertyMapEntry&);
void checkConsistency();
+ bool despecifyFunction(const Identifier&);
+
PropertyMapHashTable* copyPropertyTable();
void materializePropertyMap();
void materializePropertyMapIfNecessary()
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.
TypeInfo m_typeInfo;
- JSValuePtr m_prototype;
+ JSValue m_prototype;
mutable RefPtr<StructureChain> m_cachedPrototypeChain;
RefPtr<Structure> m_previous;
RefPtr<UString::Rep> m_nameInPrevious;
+ JSCell* m_specificValueInPrevious;
union {
Structure* singleTransition;
size_t m_propertyStorageCapacity;
signed char m_offset;
- bool m_isDictionary : 1;
+ unsigned m_dictionaryKind : 2;
bool m_isPinnedPropertyTable : 1;
bool m_hasGetterSetterProperties : 1;
bool m_usingSingleTransitionSlot : 1;
- unsigned m_attributesInPrevious : 5;
+ unsigned m_attributesInPrevious : 7;
};
inline size_t Structure::get(const Identifier& propertyName)
return m_propertyTable->entries()[entryIndex - 1].offset;
}
}
+
+ bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+ {
+ TransitionTable::iterator find = m_table.find(key);
+ if (find == m_table.end())
+ return false;
+
+ return find->second.first || find->second.second->transitionedFor(specificValue);
+ }
+ Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
+ {
+ Transition transition = m_table.get(key);
+ if (transition.second && transition.second->transitionedFor(specificValue))
+ return transition.second;
+ return transition.first;
+ }
} // namespace JSC
#endif // Structure_h
m_vector[i] = 0;
}
+bool StructureChain::isCacheable() const
+{
+ uint32_t i = 0;
+
+ while (m_vector[i]) {
+ // Both classes of dictionary structure may change arbitrarily so we can't cache them
+ if (m_vector[i++]->isDictionary())
+ return false;
+ }
+ return true;
+}
+
} // namespace JSC
public:
static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
RefPtr<Structure>* head() { return m_vector.get(); }
+ bool isCacheable() const;
private:
StructureChain(Structure* head);
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
struct StructureTransitionTableHashTraits {
typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
typedef WTF::GenericHashTraits<unsigned> SecondTraits;
- typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
+ 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 bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
- typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable;
+ class StructureTransitionTable {
+ typedef std::pair<Structure*, Structure*> Transition;
+ typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
+ public:
+ // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
+ // for the given key they will consider that transition to be a match. If a specialised transition
+ // exists and it matches the provided specificValue, get will return the specific transition.
+ inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
+ inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
+ bool hasTransition(const StructureTransitionTableHash::Key& key)
+ {
+ return m_table.contains(key);
+ }
+ void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+ {
+ TransitionTable::iterator find = m_table.find(key);
+ if (!specificValue)
+ find->second.first = 0;
+ else
+ find->second.second = 0;
+ if (!find->second.first && !find->second.second)
+ m_table.remove(find);
+ }
+ void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
+ {
+ if (!specificValue) {
+ TransitionTable::iterator find = m_table.find(key);
+ if (find == m_table.end())
+ m_table.add(key, Transition(structure, 0));
+ else
+ find->second.first = structure;
+ } else {
+ // If we're adding a transition to a specific value, then there cannot be
+ // an existing transition
+ ASSERT(!m_table.contains(key));
+ m_table.add(key, Transition(0, structure));
+ }
+
+ }
+ private:
+ TransitionTable m_table;
+ };
} // 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.
+ */
+
+#include "config.h"
+#include "TimeoutChecker.h"
+
+#include "CallFrame.h"
+#include "JSGlobalObject.h"
+
+#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 {
+
+// Number of ticks before the first timeout check is done.
+static const int ticksUntilFirstCheck = 1024;
+
+// Number of milliseconds between each timeout check.
+static const int intervalBetweenChecks = 1000;
+
+// 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
+}
+
+TimeoutChecker::TimeoutChecker()
+ : m_timeoutInterval(0)
+ , m_startCount(0)
+{
+ reset();
+}
+
+void TimeoutChecker::reset()
+{
+ m_ticksUntilNextCheck = ticksUntilFirstCheck;
+ m_timeAtLastCheck = 0;
+ m_timeExecuting = 0;
+}
+
+bool TimeoutChecker::didTimeOut(ExecState* exec)
+{
+ unsigned currentTime = getCPUTime();
+
+ if (!m_timeAtLastCheck) {
+ // Suspicious amount of looping in a script -- start timing it
+ m_timeAtLastCheck = currentTime;
+ return false;
+ }
+
+ unsigned timeDiff = currentTime - m_timeAtLastCheck;
+
+ if (timeDiff == 0)
+ timeDiff = 1;
+
+ m_timeExecuting += timeDiff;
+ m_timeAtLastCheck = currentTime;
+
+ // Adjust the tick threshold so we get the next checkTimeout call in the
+ // interval specified in intervalBetweenChecks.
+ m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck);
+ // 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_ticksUntilNextCheck == 0)
+ m_ticksUntilNextCheck = ticksUntilFirstCheck;
+
+ if (exec->dynamicGlobalObject()->shouldInterruptScriptBeforeTimeout())
+ return true;
+
+ if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
+ if (exec->dynamicGlobalObject()->shouldInterruptScript())
+ return true;
+
+ reset();
+ }
+
+ return false;
+}
+
+} // 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 TimeoutChecker_h
+#define TimeoutChecker_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ class ExecState;
+
+ class TimeoutChecker {
+ public:
+ TimeoutChecker();
+
+ void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; }
+
+ unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; }
+
+ void start()
+ {
+ if (!m_startCount)
+ reset();
+ ++m_startCount;
+ }
+
+ void stop()
+ {
+ ASSERT(m_startCount);
+ --m_startCount;
+ }
+
+ void reset();
+
+ bool didTimeOut(ExecState*);
+
+ private:
+ unsigned m_timeoutInterval;
+ unsigned m_timeAtLastCheck;
+ unsigned m_timeExecuting;
+ unsigned m_startCount;
+ unsigned m_ticksUntilNextCheck;
+ };
+
+} // namespace JSC
+
+#endif // TimeoutChecker_h
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;
+ static const unsigned ImplementsDefaultHasInstance = 1 << 3;
+ static const unsigned NeedsThisConversion = 1 << 4;
+ static const unsigned HasStandardGetOwnPropertySlot = 1 << 5;
class TypeInfo {
friend class JIT;
public:
- TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { }
+ TypeInfo(JSType type, unsigned flags = 0)
+ : m_type(type)
+ {
+ // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
+ if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
+ m_flags = flags | ImplementsDefaultHasInstance;
+ else
+ m_flags = flags;
+ }
JSType type() const { return m_type; }
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (c) 2009, Google 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
extern const double NaN;
extern const double Inf;
+// This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
+static const int minLengthToShare = 10;
+
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); }
memcpy(destination, source, numCharacters * sizeof(UChar));
}
-COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
+COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes);
CString::CString(const char* c)
: m_length(strlen(c))
UString::BaseString* UString::Rep::emptyBaseString;
UString* UString::nullUString;
-static void initializeStaticBaseString(int len, UChar* buf, UString::BaseString& base)
+static void initializeStaticBaseString(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::nullBaseString = new UString::BaseString(0, 0);
+ initializeStaticBaseString(*UString::Rep::nullBaseString);
- UString::Rep::emptyBaseString = new UString::BaseString;
- initializeStaticBaseString(0, &sharedEmptyChar, *UString::Rep::emptyBaseString);
+ UString::Rep::emptyBaseString = new UString::BaseString(&sharedEmptyChar, 0);
+ initializeStaticBaseString(*UString::Rep::emptyBaseString);
UString::nullUString = new UString;
}
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::createCopying(buffer.data(), p - buffer.data());
}
+PassRefPtr<UString::Rep> UString::Rep::create(UChar* string, int length, PassRefPtr<UString::SharedUChar> sharedBuffer)
+{
+ PassRefPtr<UString::Rep> rep = create(string, length);
+ rep->baseString()->setSharedBuffer(sharedBuffer);
+ rep->checkConsistency();
+ return rep;
+}
+
+UString::SharedUChar* UString::Rep::sharedBuffer()
+{
+ UString::BaseString* base = baseString();
+ if (len < minLengthToShare)
+ return 0;
+
+ return base->sharedBuffer();
+}
+
void UString::Rep::destroy()
{
checkConsistency();
if (!isStatic()) {
if (identifierTable())
Identifier::remove(this);
+
UString::BaseString* base = baseString();
- if (base == this)
- fastFree(base->buf);
- else
+ if (base == this) {
+ if (m_sharedBuffer)
+ m_sharedBuffer->deref();
+ else
+ fastFree(base->buf);
+ } else
base->deref();
delete this;
}
#endif
-// put these early so they can be inlined
-static inline size_t expandedSize(size_t size, size_t otherSize)
+UString::SharedUChar* UString::BaseString::sharedBuffer()
{
- // Do the size calculation in two parts, returning overflowIndicator if
- // we overflow the maximum value that we can handle.
+ if (!m_sharedBuffer)
+ setSharedBuffer(SharedUChar::create(new OwnFastMallocPtr<UChar>(buf)));
+ return m_sharedBuffer;
+}
- if (size > maxUChars())
- return overflowIndicator();
+void UString::BaseString::setSharedBuffer(PassRefPtr<UString::SharedUChar> sharedBuffer)
+{
+ // The manual steps below are because m_sharedBuffer can't be a RefPtr. m_sharedBuffer
+ // is in a union with another variable to avoid making BaseString any larger.
+ if (m_sharedBuffer)
+ m_sharedBuffer->deref();
+ m_sharedBuffer = sharedBuffer.releaseRef();
+}
- size_t expandedSize = ((size + 10) / 10 * 11) + 1;
- if (maxUChars() - expandedSize < otherSize)
+bool UString::BaseString::slowIsBufferReadOnly()
+{
+ // The buffer may not be modified as soon as the underlying data has been shared with another class.
+ if (m_sharedBuffer->isShared())
+ return true;
+
+ // At this point, we know it that the underlying buffer isn't shared outside of this base class,
+ // so get rid of m_sharedBuffer.
+ OwnPtr<OwnFastMallocPtr<UChar> > mallocPtr(m_sharedBuffer->release());
+ UChar* unsharedBuf = const_cast<UChar*>(mallocPtr->release());
+ setSharedBuffer(0);
+ preCapacity += (buf - unsharedBuf);
+ buf = unsharedBuf;
+ return false;
+}
+
+// Put these early so they can be inlined.
+static inline size_t expandedSize(size_t capacitySize, size_t precapacitySize)
+{
+ // Combine capacitySize & precapacitySize to produce a single size to allocate,
+ // check that doing so does not result in overflow.
+ size_t size = capacitySize + precapacitySize;
+ if (size < capacitySize)
return overflowIndicator();
- return expandedSize + otherSize;
+ // Small Strings (up to 4 pages):
+ // Expand the allocation size to 112.5% of the amount requested. This is largely sicking
+ // to our previous policy, however 112.5% is cheaper to calculate.
+ if (size < 0x4000) {
+ size_t expandedSize = ((size + (size >> 3)) | 15) + 1;
+ // Given the limited range within which we calculate the expansion in this
+ // fashion the above calculation should never overflow.
+ ASSERT(expandedSize >= size);
+ ASSERT(expandedSize < maxUChars());
+ return expandedSize;
+ }
+
+ // Medium Strings (up to 128 pages):
+ // For pages covering multiple pages over-allocation is less of a concern - any unused
+ // space will not be paged in if it is not used, so this is purely a VM overhead. For
+ // these strings allocate 2x the requested size.
+ if (size < 0x80000) {
+ size_t expandedSize = ((size + size) | 0xfff) + 1;
+ // Given the limited range within which we calculate the expansion in this
+ // fashion the above calculation should never overflow.
+ ASSERT(expandedSize >= size);
+ ASSERT(expandedSize < maxUChars());
+ return expandedSize;
+ }
+
+ // Large Strings (to infinity and beyond!):
+ // Revert to our 112.5% policy - probably best to limit the amount of unused VM we allow
+ // any individual string be responsible for.
+ size_t expandedSize = ((size + (size >> 3)) | 0xfff) + 1;
+
+ // Check for overflow - any result that is at least as large as requested (but
+ // still below the limit) is okay.
+ if ((expandedSize >= size) && (expandedSize < maxUChars()))
+ return expandedSize;
+ return overflowIndicator();
}
static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
{
rep->checkConsistency();
+ ASSERT(!rep->baseString()->isBufferReadOnly());
UString::BaseString* base = rep->baseString();
return true;
}
+bool UString::Rep::reserveCapacity(int capacity)
+{
+ // If this is an empty string there is no point 'growing' it - just allocate a new one.
+ // If the BaseString is shared with another string that is using more capacity than this
+ // string is, then growing the buffer won't help.
+ // If the BaseString's buffer is readonly, then it isn't allowed to grow.
+ UString::BaseString* base = baseString();
+ if (!base->buf || !base->capacity || (offset + len) != base->usedCapacity || base->isBufferReadOnly())
+ return false;
+
+ // If there is already sufficient capacity, no need to grow!
+ if (capacity <= base->capacity)
+ return true;
+
+ checkConsistency();
+
+ size_t newCapacity = expandedSize(capacity, 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;
+
+ checkConsistency();
+ return true;
+}
+
void UString::expandCapacity(int requiredLength)
{
if (!JSC::expandCapacity(m_rep.get(), requiredLength))
void UString::expandPreCapacity(int requiredPreCap)
{
m_rep->checkConsistency();
+ ASSERT(!m_rep->baseString()->isBufferReadOnly());
BaseString* base = m_rep->baseString();
} else if (thisSize == 0) {
// this is empty
rep = UString::Rep::createCopying(tData, tSize);
- } else if (rep == base && rep->rc == 1) {
+ } else if (rep == base && !base->isShared()) {
// 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();
rep->len = length;
rep->_hash = 0;
}
- } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
// 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();
rep = UString::Rep::create(rep, 0, length);
}
} else {
- // this is shared with someone using more capacity, gotta make a whole new string
+ // This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
UChar* d = allocChars(newCapacity);
if (!d)
rep = createRep(t);
} else if (tSize == 0) {
// t is empty, we'll just return *this below.
- } else if (rep == base && rep->rc == 1) {
+ } else if (rep == base && !base->isShared()) {
// 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();
rep->len = length;
rep->_hash = 0;
}
- } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
// this string reaches the end of the buffer - extend it
expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length));
UChar* d = rep->data();
rep = UString::Rep::create(rep, 0, length);
}
} else {
- // this is shared with someone using more capacity, gotta make a whole new string
+ // This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
UChar* d = allocChars(newCapacity);
if (!d)
b->checkConsistency();
int aSize = a->size();
- int aOffset = a->offset;
int bSize = b->size();
- int bOffset = b->offset;
- int length = aSize + bSize;
+ int aOffset = a->offset;
// possible cases:
+ UString::BaseString* aBase = a->baseString();
+ if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity && !aBase->isBufferReadOnly()) {
+ // b is a single character (common fast case)
+ ++aBase->usedCapacity;
+ a->data()[aSize] = b->data()[0];
+ return UString::Rep::create(a, 0, aSize + 1);
+ }
+
// a is empty
if (aSize == 0)
return b;
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);
- }
+ int bOffset = b->offset;
+ int length = aSize + bSize;
UString::BaseString* bBase = b->baseString();
if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize
- && (-bOffset != bBase->usedPreCapacity || aSize >= bSize)) {
+ && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) && !aBase->isBufferReadOnly()) {
// - 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
return result;
}
- if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
+ if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize && !bBase->isBufferReadOnly()) {
// - 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
int decimalPoint;
int sign;
- char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+ char result[80];
+ WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL);
int length = static_cast<int>(strlen(result));
int i = 0;
buf[i++] = '\0';
}
- WTF::freedtoa(result);
-
- return concatenate(rep, buf);
+ return concatenate(rep, buf);
}
UString UString::from(int i)
char buf[80];
int decimalPoint;
int sign;
-
- char* result = WTF::dtoa(d, 0, &decimalPoint, &sign, NULL);
+
+ char result[80];
+ WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL);
int length = static_cast<int>(strlen(result));
int i = 0;
ASSERT(i <= static_cast<int>(sizeof(buf)));
}
- WTF::freedtoa(result);
-
- return UString(buf);
+ return UString(buf);
}
UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
return UString::Rep::create(buffer, totalLength);
}
+UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
+{
+ m_rep->checkConsistency();
+
+ int replacementLength = replacement.size();
+ int totalLength = size() - rangeLength + replacementLength;
+ if (totalLength == 0)
+ return "";
+
+ UChar* buffer = allocChars(totalLength);
+ if (!buffer)
+ return null();
+
+ copyChars(buffer, data(), rangeStart);
+ copyChars(buffer + rangeStart, replacement.data(), replacementLength);
+ int rangeEnd = rangeStart + rangeLength;
+ copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
+
+ return UString::Rep::create(buffer, totalLength);
+}
+
+
UString& UString::append(const UString &t)
{
m_rep->checkConsistency();
*this = t;
} else if (tSize == 0) {
// t is empty
- } else if (m_rep == base && m_rep->rc == 1) {
+ } else if (m_rep == base && !base->isShared()) {
// this is direct and has refcount of 1 (so we can just alter it directly)
expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
if (data()) {
m_rep->len = length;
m_rep->_hash = 0;
}
- } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
+ } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
// this reaches the end of the buffer - extend it if it's long enough to append to
expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
if (data()) {
m_rep = Rep::create(m_rep, 0, length);
}
} else {
- // this is shared with someone using more capacity, gotta make a whole new string
+ // This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
UChar* d = allocChars(newCapacity);
if (!d)
return *this;
}
+UString& UString::appendNumeric(int i)
+{
+ m_rep = concatenate(rep(), i);
+ return *this;
+}
+
+UString& UString::appendNumeric(double d)
+{
+ m_rep = concatenate(rep(), d);
+ return *this;
+}
+
UString& UString::append(const char* t)
{
m_rep = concatenate(m_rep.release(), t);
m_rep = Rep::create(d, 1);
m_rep->baseString()->capacity = newCapacity;
}
- } else if (m_rep == base && m_rep->rc == 1) {
+ } else if (m_rep == base && !base->isShared()) {
// 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();
m_rep->len = length + 1;
m_rep->_hash = 0;
}
- } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) {
+ } else if (thisOffset + length == base->usedCapacity && length >= minShareSize && !base->isBufferReadOnly()) {
// this reaches the end of the string - extend it and share
expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true));
UChar* d = m_rep->data();
m_rep = Rep::create(m_rep, 0, length + 1);
}
} else {
- // this is shared with someone using more capacity, gotta make a whole new string
+ // This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length + 1, 0);
UChar* d = allocChars(newCapacity);
if (!d)
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) {
+ if (!base->isShared() && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) {
d = base->buf;
m_rep->_hash = 0;
m_rep->len = l;
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)
/*
* 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.
+ * 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
#include <stdint.h>
#include <string.h>
#include <wtf/Assertions.h>
+#include <wtf/CrossThreadRefCounted.h>
+#include <wtf/OwnFastMallocPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/PtrAndFlags.h>
#include <wtf/RefPtr.h>
friend class JIT;
public:
+ typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar;
struct BaseString;
struct Rep : Noncopyable {
friend class JIT;
- static PassRefPtr<Rep> create(UChar*, int);
+ static PassRefPtr<Rep> create(UChar* buffer, int length)
+ {
+ return adoptRef(new BaseString(buffer, length));
+ }
+
+ static PassRefPtr<Rep> createEmptyBuffer(size_t size)
+ {
+ // Guard against integer overflow
+ if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) {
+ if (void * buf = tryFastMalloc(size * sizeof(UChar)))
+ return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size));
+ }
+ return adoptRef(new BaseString(0, 0, 0));
+ }
+
static PassRefPtr<Rep> createCopying(const UChar*, int);
static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
// Returns UString::Rep::null for null input or conversion failure.
static PassRefPtr<Rep> createFromUTF8(const char*);
+ // Uses SharedUChar to have joint ownership over the UChar*.
+ static PassRefPtr<Rep> create(UChar*, int, PassRefPtr<SharedUChar>);
+
+ SharedUChar* sharedBuffer();
void destroy();
bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); }
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; }
+ bool reserveCapacity(int capacity);
+
+ protected:
+ // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose.
+ Rep(int length)
+ : offset(0)
+ , len(length)
+ , rc(1)
+ , _hash(0)
+ , m_baseString(0)
+ {
+ }
+
+ Rep(PassRefPtr<BaseString> base, int offsetInBase, int length)
+ : offset(offsetInBase)
+ , len(length)
+ , rc(1)
+ , _hash(0)
+ , m_baseString(base.releaseRef())
+ {
+ checkConsistency();
+ }
+
+ union {
+ // If !baseIsSelf()
+ BaseString* m_baseString;
+ // If baseIsSelf()
+ SharedUChar* m_sharedBuffer;
+ };
+
private:
+ // For SmallStringStorage which allocates an array and does initialization manually.
+ Rep() { }
+
+ friend class SmallStringsStorage;
friend void initializeUString();
- static BaseString* nullBaseString;
- static BaseString* emptyBaseString;
+ JS_EXPORTDATA static BaseString* nullBaseString;
+ JS_EXPORTDATA static BaseString* emptyBaseString;
};
+
struct BaseString : public Rep {
- BaseString()
+ bool isShared() { return rc != 1 || isBufferReadOnly(); }
+ void setSharedBuffer(PassRefPtr<SharedUChar>);
+
+ bool isBufferReadOnly()
{
- m_identifierTableAndFlags.setFlag(BaseStringFlag);
+ if (!m_sharedBuffer)
+ return false;
+ return slowIsBufferReadOnly();
}
// potentially shared data.
int usedCapacity;
size_t reportedCost;
+
+ private:
+ BaseString(UChar* buffer, int length, int additionalCapacity = 0)
+ : Rep(length)
+ , buf(buffer)
+ , preCapacity(0)
+ , usedPreCapacity(0)
+ , capacity(length + additionalCapacity)
+ , usedCapacity(length)
+ , reportedCost(0)
+ {
+ m_identifierTableAndFlags.setFlag(BaseStringFlag);
+ checkConsistency();
+ }
+
+ SharedUChar* sharedBuffer();
+ bool slowIsBufferReadOnly();
+
+ friend struct Rep;
+ friend class SmallStringsStorage;
+ friend void initializeUString();
};
public:
UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
+ UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) 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);
+ UString& appendNumeric(int);
+ UString& appendNumeric(double);
bool getCString(CStringBuffer&) const;
size_t cost() const;
+ // Attempt to grow this string such that it can grow to a total length of 'capacity'
+ // without reallocation. This may fail a number of reasons - if the BasicString is
+ // shared and another string is using part of the capacity beyond our end point, if
+ // the realloc fails, or if this string is empty and has no storage.
+ //
+ // This method returns a boolean indicating success.
+ bool reserveCapacity(int capacity)
+ {
+ return m_rep->reserveCapacity(capacity);
+ }
+
private:
void expandCapacity(int requiredLength);
void expandPreCapacity(int requiredPreCap);
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)
+ {
+ int size = s1.size();
+ switch (size) {
+ case 0:
+ return !s2.size();
+ case 1:
+ return s2.size() == 1 && s1.data()[0] == s2.data()[0];
+ case 2: {
+ if (s2.size() != 2)
+ return false;
+ const UChar* d1 = s1.data();
+ const UChar* d2 = s2.data();
+ return (d1[0] == d2[0]) & (d1[1] == d2[1]);
+ }
+ default:
+ return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
+ }
+ }
+
inline bool operator!=(const UString& s1, const UString& s2)
{
bool equal(const UString::Rep*, const UString::Rep*);
+ inline PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<UString::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);
+
+ // Steal the single reference this Rep was created with.
+ return adoptRef(new Rep(base, repOffset + offset, length));
+ }
+
inline UChar* UString::Rep::data() const
{
const BaseString* base = baseString();
inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base)
{
ASSERT(base != this);
+ ASSERT(!baseIsSelf());
m_baseString = base.releaseRef();
}
inline UString::BaseString* UString::Rep::baseString()
{
- return reinterpret_cast<BaseString*>(baseIsSelf() ? this : m_baseString);
+ return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ;
}
inline const UString::BaseString* UString::Rep::baseString() const
{
- return const_cast<const BaseString*>(const_cast<Rep*>(this)->baseString());
+ return const_cast<Rep*>(this)->baseString();
}
#ifdef NDEBUG
Author: christine@netscape.com
Date: 12 november 1997
+
+
+The test case described above is correct, however the second test case in this file is not,
+'o instanceof o' should thow an exception. According to ECMA-262:
+
+ 8.6.2 Internal Properties and Methods:
+ "... only Function objects implement [[HasInstance]]"
+ 11.8.6 The instanceof operator:
+ "6.If Result(4) does not have a [[HasInstance]] method, throw a TypeError exception."
+
+{} does not implement [[HasInstance]] (since it is not a function), so passing it as the
+constructor to be tested to instanceof should result in a TypeError being thrown.
+
*/
var SECTION = "instanceof-003";
var VERSION = "ECMA_2";
theproto instanceof Foo );
- var o = {};
-
AddTestCase(
"o = {}; o instanceof o",
- false,
- o instanceof o );
+ "EXCEPTION",
+ (function(){ try { var o = {}; o instanceof o; return "no exception"; } catch (e) { return "EXCEPTION"; } } )() );
test();
* Author:
*/
- var SECTION = "instanceof"; // provide a document reference (ie, ECMA section)
- var VERSION = "ECMA_2"; // Version of JavaScript or ECMA
- var TITLE = "Regression test for Bugzilla #7635"; // Provide ECMA section title or a description
- var BUGNUMBER = "http://bugzilla.mozilla.org/show_bug.cgi?id=7635"; // Provide URL to bugsplat or bugzilla report
+var SECTION = "instanceof"; // provide a document reference (ie, ECMA section)
+var VERSION = "ECMA_2"; // Version of JavaScript or ECMA
+var TITLE = "Regression test for Bugzilla #7635"; // Provide ECMA section title or a description
+var BUGNUMBER = "http://bugzilla.mozilla.org/show_bug.cgi?id=7635"; // Provide URL to bugsplat or bugzilla report
- startTest(); // leave this alone
+startTest(); // leave this alone
- /*
- * Calls to AddTestCase here. AddTestCase is a function that is defined
- * in shell.js and takes three arguments:
- * - a string representation of what is being tested
- * - the expected result
- * - the actual result
- *
- * For example, a test might look like this:
- *
- * var zip = /[\d]{5}$/;
- *
- * AddTestCase(
- * "zip = /[\d]{5}$/; \"PO Box 12345 Boston, MA 02134\".match(zip)", // description of the test
- * "02134", // expected result
- * "PO Box 12345 Boston, MA 02134".match(zip) ); // actual result
- *
- */
-
- function Foo() {}
- theproto = {};
- Foo.prototype = theproto
- theproto instanceof Foo
+/*
+ * Calls to AddTestCase here. AddTestCase is a function that is defined
+ * in shell.js and takes three arguments:
+ * - a string representation of what is being tested
+ * - the expected result
+ * - the actual result
+ *
+ * For example, a test might look like this:
+ *
+ * var zip = /[\d]{5}$/;
+ *
+ * AddTestCase(
+ * "zip = /[\d]{5}$/; \"PO Box 12345 Boston, MA 02134\".match(zip)", // description of the test
+ * "02134", // expected result
+ * "PO Box 12345 Boston, MA 02134".match(zip) ); // actual result
+ *
+ */
+function Foo() {}
+theproto = {};
+Foo.prototype = theproto
+theproto instanceof Foo
- AddTestCase( "function Foo() {}; theproto = {}; Foo.prototype = theproto; theproto instanceof Foo",
- false,
- theproto instanceof Foo );
-
- var o = {};
- AddTestCase( "var o = {}; o instanceof o", false, o instanceof o );
+AddTestCase( "function Foo() {}; theproto = {}; Foo.prototype = theproto; theproto instanceof Foo",
+ false,
+ theproto instanceof Foo );
- var f = new Function();
+var f = new Function();
- AddTestCase( "var f = new Function(); f instanceof f", false, f instanceof f );
+AddTestCase( "var f = new Function(); f instanceof f", false, f instanceof f );
- test(); // leave this alone. this executes the test cases and
- // displays results.
+test(); // leave this alone. this executes the test cases and
+ // displays results.
<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, 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>
+Skip List: ecma/Date/15.9.2.1.js, ecma/Date/15.9.2.2-1.js, ecma/Date/15.9.2.2-2.js, ecma/Date/15.9.2.2-3.js, ecma/Date/15.9.2.2-4.js, ecma/Date/15.9.2.2-5.js, ecma/Date/15.9.2.2-6.js, ecma_3/Date/15.9.5.7.js<br>
+1127 test(s) selected, 1119 test(s) completed, 49 failures reported (4.37% failed)<br>
+Engine command line: "/Volumes/Big/ggaren/build/Debug/jsc" <br>
+OS type: Darwin il0301a-dhcp53.apple.com 9.7.0 Darwin Kernel Version 9.7.0: Tue Mar 31 22:52:17 PDT 2009; root:xnu-1228.12.14~1/RELEASE_I386 i386<br>
+Testcase execution time: 3 minutes, 18 seconds.<br>
+Tests completed on Tue Apr 21 12:56:28 2009.<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>
Failure messages were:<br>
eval("function f(){}function g(){}") (threw no exception thrown = fail FAILED! expected: pass<br>
</tt><br>
-<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Date/15.9.5.7.js'>ecma_3/Date/15.9.5.7.js</a> failed</b> <br>
+<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br>
[ <a href='#failure2'>Previous Failure</a> | <a href='#failure4'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt><br>
+<tt>STATUS: Function Expression Statements basic test.<br>
Failure messages were:<br>
-(Wed Dec 31 1969 16:00:00 GMT-0800 (PST)).toLocaleTimeString() = 4:00:00 PM PST FAILED! expected: 16:00:00<br>
-(Wed Dec 31 1969 08:00:00 GMT-0800 (PST)).toLocaleTimeString() = 8:00:00 AM PST FAILED! expected: 08:00:00<br>
-(Sun Dec 31 1899 16:00:00 GMT-0800 (PST)).toLocaleTimeString() = 5:00:00 PM PDT FAILED! expected: 16:00:00<br>
-(Mon Jan 01 1900 00:00:00 GMT-0800 (PST)).toLocaleTimeString() = 1:00:00 AM PDT FAILED! expected: 00:00:00<br>
-(Fri Dec 31 1999 16:00:00 GMT-0800 (PST)).toLocaleTimeString() = 4:00:00 PM PST FAILED! expected: 16:00:00<br>
-(Sat Jan 01 2000 00:00:00 GMT-0800 (PST)).toLocaleTimeString() = 12:00:00 AM PST FAILED! expected: 00:00:00<br>
-(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>
-(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>
+FAILED!: [reported from test()] Both functions were defined.<br>
+FAILED!: [reported from test()] Expected value '1', Actual value '0'<br>
+FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br>
+<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/15.10.2-1.js'>ecma_3/RegExp/15.10.2-1.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=(none)' target='other_window'>Bug Number (none)</a><br>
[ <a href='#failure3'>Previous Failure</a> | <a href='#failure5'>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='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/15.10.2-1.js'>ecma_3/RegExp/15.10.2-1.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=(none)' target='other_window'>Bug Number (none)</a><br>
- [ <a href='#failure4'>Previous Failure</a> | <a href='#failure6'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: RegExp conformance test<br>
Failure messages were:<br>
FAILED!: [reported from test()] Section 7 of test -<br>
FAILED!: [reported from test()] Actual: ["baaabaac", "ba", "aa", "abaac"]<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/perlstress-001.js'>ecma_3/RegExp/perlstress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=85721' target='other_window'>Bug Number 85721</a><br>
- [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/perlstress-001.js'>ecma_3/RegExp/perlstress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=85721' target='other_window'>Bug Number 85721</a><br>
+ [ <a href='#failure4'>Previous Failure</a> | <a href='#failure6'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Testing regular expression edge cases<br>
Failure messages were:<br>
FAILED!: [reported from test()] Section 218 of test -<br>
FAILED!: [reported from test()] Actual: ["aabbaa", "aa", "bb"]<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/regress-209919.js'>ecma_3/RegExp/regress-209919.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=209919' target='other_window'>Bug Number 209919</a><br>
- [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/regress-209919.js'>ecma_3/RegExp/regress-209919.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=209919' target='other_window'>Bug Number 209919</a><br>
+ [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Testing regexp submatches with quantifiers<br>
Failure messages were:<br>
FAILED!: [reported from test()] Section 1 of test -<br>
FAILED!: [reported from test()] Actual: ["1.000,00", "", ",00"]<br>
FAILED!: [reported from test()] <br>
</tt><br>
-<a name='failure8'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br>
- [ <a href='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br>
+ [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>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='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>
+<a name='failure8'></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='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt>STATUS: Unicode format-control character (Category Cf) test.<br>
Failure messages were:<br>
FAILED!: [reported from test()] Unicode format-control character test (Category Cf.)<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='./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>
+<a name='failure9'></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='#failure8'>Previous Failure</a> | <a href='#failure10'>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='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>
+<a name='failure10'></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='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
<tt><br>
Failure messages were:<br>
f.arity = undefined FAILED! expected: 3<br>
-(new Function()).toString() = function anonymous() {} FAILED! expected: <br>
+} FAILED! expected: <br>
</tt><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>
+<a name='failure11'></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='#failure10'>Previous Failure</a> | <a href='#failure12'>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='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>
+<a name='failure12'></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='#failure11'>Previous Failure</a> | <a href='#failure13'>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>
-f.toString() = function anonymous() {return "hello!"} FAILED! expected: <br>
+} FAILED! expected: <br>
</tt><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>
+<a name='failure13'></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='#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>
</tt><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>
+<a name='failure14'></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='#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>
(new String('x') == 'x') = true FAILED! expected: false<br>
('x' == new String('x')) = true FAILED! expected: false<br>
</tt><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>
+<a name='failure15'></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='#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>
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='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>
+<a name='failure16'></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='#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>
(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='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>
+<a name='failure17'></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='#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>
(['$*'] == 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='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>
+<a name='failure18'></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='#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>
123xyz'.match(new RegExp('^\d+')) = null FAILED! expected: 123<br>
</tt><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>
+<a name='failure19'></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='#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>
xyz'.match(new RegExp('\d+$')) = null FAILED! expected: 890<br>
</tt><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>
+<a name='failure20'></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='#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>
'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='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>
+<a name='failure21'></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='#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>
new Boolean(false) = true FAILED! expected: false<br>
</tt><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>
+<a name='failure22'></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='#failure21'>Previous Failure</a> | <a href='#failure23'>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='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>
+<a name='failure23'></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='#failure22'>Previous Failure</a> | <a href='#failure24'>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='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>
+<a name='failure24'></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='#failure23'>Previous Failure</a> | <a href='#failure25'>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>
</tt><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>
+<a name='failure25'></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='#failure24'>Previous Failure</a> | <a href='#failure26'>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='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 name='failure26'></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='#failure25'>Previous Failure</a> | <a href='#failure27'>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='failure27'></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='#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 name='failure28'></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='#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-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br>
+<a name='failure29'></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='#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/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br>
+<a name='failure30'></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='#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/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>
+BUGNUMBER: 50447<br>
+STATUS: Test (non-ECMA) Error object properties fileName, lineNumber<br>
+</tt><br>
+<a name='failure31'></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='#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>
-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/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br>
+Testcase produced no output!</tt><br>
+<a name='failure32'></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='#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>
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 name='failure33'></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='#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-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br>
+<a name='failure34'></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='#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/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br>
+<a name='failure35'></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='#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-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br>
+<a name='failure36'></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='#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>
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 name='failure37'></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='#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>
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 name='failure38'></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='#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>
-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>
BUGNUMBER: 44009<br>
STATUS: Testing that we don't crash on obj.toSource()<br>
</tt><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>
+<a name='failure39'></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='#failure38'>Previous Failure</a> | <a href='#failure40'>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='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>
+<a name='failure40'></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='#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>
Testcase produced no output!</tt><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>
+<a name='failure41'></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='#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='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>
+<a name='failure42'></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='#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>
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>
+<a name='failure43'></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='#failure42'>Previous Failure</a> | <a href='#failure44'>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='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>
+<a name='failure44'></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='#failure43'>Previous Failure</a> | <a href='#failure45'>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='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>
+<a name='failure45'></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='#failure44'>Previous Failure</a> | <a href='#failure46'>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='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>
+<a name='failure46'></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='#failure45'>Previous Failure</a> | <a href='#failure47'>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='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>
+<a name='failure47'></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='#failure46'>Previous Failure</a> | <a href='#failure48'>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='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>
+<a name='failure48'></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='#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='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>
+<a name='failure49'></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='#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>
<pre>
<a name='retest_list'></a>
<h2>Retest List</h2><br>
-# Retest List, squirrelfish, generated Thu Sep 18 02:24:54 2008.
+# Retest List, squirrelfish, generated Tue Apr 21 12:56:28 2009.
# Original test base was: All tests.
-# 1127 of 1135 test(s) were completed, 50 failures reported.
+# 1119 of 1127 test(s) were completed, 49 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/FunExpr/fe-001.js
ecma_3/RegExp/15.10.2-1.js
ecma_3/RegExp/perlstress-001.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
+js1_6/String/regress-306591.js
\ No newline at end of file
}
*numSubpatterns_ptr = parser.numSubpatterns();
- pool = globalData->poolForSize(generator.size());
+ pool = globalData->executableAllocator.poolForSize(generator.size());
return reinterpret_cast<CompiledRegExp>(generator.copyCode(pool.get()));
}
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
+#if PLATFORM(X86)
// On x86 edi & esi are callee preserved registers.
push(X86::edi);
push(X86::esi);
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()
{
+ ASSERT(returnRegister != index);
+ ASSERT(returnRegister != output);
+
// Set return value.
- pop(X86::eax); // match begin
- store32(X86::eax, output);
+ pop(returnRegister); // match begin
+ store32(returnRegister, output);
store32(index, Address(output, 4)); // match end
// Restore callee save registers.
-#if !PLATFORM(X86_64)
+#if PLATFORM(X86)
pop(X86::esi);
pop(X86::edi);
#endif
{
peek(index);
if (failure)
- *failure = je32(length, index);
+ *failure = branch32(Equal, length, index);
add32(Imm32(1), index);
poke(index);
}
void Generator::generateLoadCharacter(JumpList& failures)
{
- failures.append(je32(length, index));
+ failures.append(branch32(Equal, length, index));
load16(BaseIndex(input, index, TimesTwo), character);
}
// were part of the input string.
void Generator::generateJumpIfNotEndOfInput(Label target)
{
- jle32(index, length, target);
+ branch32(LessThanOrEqual, index, length, target);
}
void Generator::generateReturnFailure()
{
pop();
- move(Imm32(-1), X86::eax);
-#if !PLATFORM(X86_64)
+ move(Imm32(-1), returnRegister);
+
+#if PLATFORM(X86)
pop(X86::esi);
pop(X86::edi);
#endif
GenerateBackreferenceFunctor functor(subpatternId);
load32(Address(output, (2 * subpatternId) * sizeof(int)), character);
- Jump skipIfEmpty = je32(Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character);
+ Jump skipIfEmpty = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character);
ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy);
if (quantifierType == Quantifier::Greedy)
Label alternativeFailed(this);
pop(index);
if (max != Quantifier::Infinity)
- je32(repeatCount, Imm32(max), quantifierFailed);
+ branch32(Equal, repeatCount, Imm32(max), quantifierFailed);
// (1) Read an atom.
if (min)
// (2) Keep reading if we're under the minimum.
if (min > 1)
- jl32(repeatCount, Imm32(min), readAtom);
+ branch32(LessThan, repeatCount, Imm32(min), readAtom);
// (3) Test the rest of the alternative.
if (!min)
else if (max == 1)
doneReadingAtomsList.append(jump());
else {
- jne32(repeatCount, Imm32(max), readAtom);
+ branch32(NotEqual, repeatCount, Imm32(max), readAtom);
doneReadingAtomsList.append(jump());
}
// (2) Verify that we have enough atoms.
doneReadingAtomsList.link(this);
- jl32(repeatCount, Imm32(min), quantifierFailed);
+ branch32(LessThan, repeatCount, Imm32(min), quantifierFailed);
// (3) Test the rest of the alternative.
push(index);
// Optimistically consume 2 characters.
add32(Imm32(2), index);
- failures.append(jg32(index, length));
+ failures.append(branch32(GreaterThan, index, length));
// Load the characters we just consumed, offset -2 characters from index.
load32(BaseIndex(input, index, TimesTwo, -2 * 2), character);
}
int pair = ch1 | (ch2 << 16);
- failures.append(jne32(character, Imm32(pair)));
+ failures.append(branch32(NotEqual, character, Imm32(pair)));
return true;
}
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));
+ isUpper = branch32(Equal, 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)));
+ failures.append(branch32(NotEqual, character, Imm32((unsigned short)ch)));
if (m_parser.ignoreCase() && hasUpper) {
// for unicode case insensitive matches, branch here if upper matches.
// 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));
+ Jump loOrAbove = branch32(GreaterThanOrEqual, 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])));
+ matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex])));
++*matchIndex;
}
failures.append(jump());
loOrAbove.link(this);
} else if (which) {
- Jump loOrAbove = jge32(character, Imm32((unsigned short)lo));
+ Jump loOrAbove = branch32(GreaterThanOrEqual, 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)));
+ failures.append(branch32(LessThan, character, Imm32((unsigned short)lo)));
while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
++*matchIndex;
- matchDest.append(jle32(character, Imm32((unsigned short)hi)));
+ matchDest.append(branch32(LessThanOrEqual, 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.
{
Jump unicodeFail;
if (charClass.numMatchesUnicode || charClass.numRangesUnicode) {
- Jump isAscii = jle32(character, Imm32(0x7f));
+ Jump isAscii = branch32(LessThanOrEqual, 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)));
+ matchDest.append(branch32(Equal, character, Imm32(ch)));
}
}
UChar lo = charClass.rangesUnicode[i].begin;
UChar hi = charClass.rangesUnicode[i].end;
- Jump below = jl32(character, Imm32(lo));
- matchDest.append(jle32(character, Imm32(hi)));
+ Jump below = branch32(LessThan, character, Imm32(lo));
+ matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi)));
below.link(this);
}
}
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++])));
+ matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass.matches[matchIndex++])));
failures.link(this);
} else if (charClass.numMatches) {
if (isASCIIUpper(ch))
continue;
}
- matchDest.append(je32(character, Imm32((unsigned short)ch)));
+ matchDest.append(branch32(Equal, 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])));
+ matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i])));
}
}
JumpList previousIsNewline;
// begin of input == success
- previousIsNewline.append(je32(index, Imm32(0)));
+ previousIsNewline.append(branch32(Equal, index, Imm32(0)));
// now check prev char against newline characters.
load16(BaseIndex(input, index, TimesTwo, -2), character);
previousIsNewline.link(this);
} else
- failures.append(jne32(index, Imm32(0)));
+ failures.append(branch32(NotEqual, index, Imm32(0)));
}
void Generator::generateAssertionEOL(JumpList& failures)
failures.append(jump());
nextIsNewline.link(this);
} else {
- failures.append(jne32(length, index));
+ failures.append(branch32(NotEqual, length, index));
}
}
// (1) Check if the previous value was a word char
// (1.1) check for begin of input
- Jump atBegin = je32(index, Imm32(0));
+ Jump atBegin = branch32(Equal, index, Imm32(0));
// (1.2) load the last char, and chck if is word character
load16(BaseIndex(input, index, TimesTwo, -2), character);
JumpList previousIsWord;
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);
+ Jump endOfBackRef = branch32(Equal, 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);
+ Jump endOfInput = branch32(Equal, length, index);
- je16(character, BaseIndex(input, index, TimesTwo), topOfLoop);
+ branch16(Equal, BaseIndex(input, index, TimesTwo), character, topOfLoop);
endOfInput.link(this);
{
}
+#if PLATFORM(X86)
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 length = X86::ecx;
static const RegisterID output = X86::edi;
+
+ static const RegisterID character = X86::esi;
static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match.
-
+
+ static const RegisterID returnRegister = X86::eax;
+#endif
+#if PLATFORM(X86_64)
+ static const RegisterID input = X86::edi;
+ static const RegisterID index = X86::esi;
+ static const RegisterID length = X86::edx;
+ static const RegisterID output = X86::ecx;
+
+ static const RegisterID character = X86::eax;
+ static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match.
+
+ static const RegisterID returnRegister = X86::eax;
+#endif
+
void generateEnter();
void generateSaveIndex();
void generateIncrementIndex(Jump* failure = 0);
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 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
inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; }
}
+using WTF::isASCII;
+using WTF::isASCIIAlpha;
+using WTF::isASCIIAlphanumeric;
+using WTF::isASCIIDigit;
+using WTF::isASCIIHexDigit;
+using WTF::isASCIILower;
+using WTF::isASCIIOctalDigit;
+using WTF::isASCIIPrintable;
+using WTF::isASCIISpace;
+using WTF::isASCIIUpper;
+using WTF::toASCIIHexValue;
+using WTF::toASCIILower;
+using WTF::toASCIIUpper;
+
#endif
handle h = abs.root;
handle parent = null(), child;
- int cmp, cmp_shortened_sub_with_path;
+ int cmp, cmp_shortened_sub_with_path = 0;
for (;;) {
if (h == null())
#include <CoreFoundation/CFString.h>
-#if COMPILER(MSVC) && !PLATFORM(WIN_CE)
+#if COMPILER(MSVC) && !PLATFORM(WINCE)
#ifndef WINVER
#define WINVER 0x0500
#endif
if (strstr(format, "%@")) {
CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args);
-
+
int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
char* buffer = (char*)malloc(length + 1);
#include "Platform.h"
+#include <stdbool.h>
+
#if COMPILER(MSVC)
#include <stddef.h>
#else
#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
#endif
+/* This macro is needed to prevent the clang static analyzer from generating false-positive reports in ASSERT() macros. */
+#ifdef __clang__
+#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
+#else
+#define CLANG_ANALYZER_NORETURN
+#endif
+
/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
#ifdef __cplusplus
WTFLogChannelState state;
} WTFLogChannel;
-void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
-void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
-void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
-void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion) CLANG_ANALYZER_NORETURN;
+void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(5, 6);
+void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion) CLANG_ANALYZER_NORETURN;
+void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(4, 5);
void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
void WTFLog(WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE) && !PLATFORM(TORCHMOBILE)
/* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
#include <windows.h>
#undef min
/* COMPILE_ASSERT */
#ifndef COMPILE_ASSERT
-#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
+#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1]
#endif
/* FATAL */
private:
ByteArray(size_t size)
- : RefCountedBase(1)
- , m_size(size)
+ : m_size(size)
{
}
size_t m_size;
--- /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 CrossThreadRefCounted_h
+#define CrossThreadRefCounted_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+
+namespace WTF {
+
+ // Used to allowing sharing data across classes and threads (like ThreadedSafeShared).
+ //
+ // Why not just use ThreadSafeShared?
+ // ThreadSafeShared can have a significant perf impact when used in low level classes
+ // (like UString) that get ref/deref'ed a lot. This class has the benefit of doing fast ref
+ // counts like RefPtr whenever possible, but it has the downside that you need to copy it
+ // to use it on another thread.
+ //
+ // Is this class threadsafe?
+ // While each instance of the class is not threadsafe, the copied instance is threadsafe
+ // with respect to the original and any other copies. The underlying m_data is jointly
+ // owned by the original instance and all copies.
+ template<class T>
+ class CrossThreadRefCounted : Noncopyable {
+ public:
+ static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
+ {
+ return adoptRef(new CrossThreadRefCounted<T>(data, 0));
+ }
+
+ // Used to make an instance that can be used on another thread.
+ PassRefPtr<CrossThreadRefCounted<T> > crossThreadCopy();
+
+ void ref();
+ void deref();
+ T* release();
+
+ bool isShared() const
+ {
+ return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef());
+ }
+
+#ifndef NDEBUG
+ bool mayBePassedToAnotherThread() const { ASSERT(!m_threadId); return m_refCounter.hasOneRef(); }
+#endif
+
+ private:
+ CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
+ : m_threadSafeRefCounter(threadedCounter)
+ , m_data(data)
+#ifndef NDEBUG
+ , m_threadId(0)
+#endif
+ {
+ }
+
+ ~CrossThreadRefCounted()
+ {
+ if (!m_threadSafeRefCounter)
+ delete m_data;
+ }
+
+ void threadSafeDeref();
+
+ RefCountedBase m_refCounter;
+ ThreadSafeSharedBase* m_threadSafeRefCounter;
+ T* m_data;
+#ifndef NDEBUG
+ ThreadIdentifier m_threadId;
+#endif
+ };
+
+ template<class T>
+ void CrossThreadRefCounted<T>::ref()
+ {
+
+ // MobileSafari allocates content on the UI thread then
+ // frees it on the Web thread. This is ok. This occurs in a
+ // couple of places. In particular, http://maps.google.com
+ // which uses JS to add an iFrame with an about:blank URL and
+ // then executes some JS. Much of this work happens on the
+ // main (UI) thread.
+ // Ideally we want to have this assert here:
+ // ASSERT(WebThreadIsLockedOrDisabled())
+ // but then we would need to include code from
+ // WebCore. So just don't do any ASSERTs here.
+ m_refCounter.ref();
+#ifndef NDEBUG
+ // Store the threadId as soon as the ref count gets to 2.
+ // The class gets created with a ref count of 1 and then passed
+ // to another thread where to ref count get increased. This
+ // is a heuristic but it seems to always work and has helped
+ // find some bugs.
+ if (!m_threadId && m_refCounter.refCount() == 2)
+ m_threadId = currentThread();
+#endif
+ }
+
+ template<class T>
+ void CrossThreadRefCounted<T>::deref()
+ {
+ // MobileSafari allocates content on the UI thread then
+ // frees it on the Web thread. This is ok. This occurs in a
+ // couple of places. In particular, http://maps.google.com
+ // which uses JS to add an iFrame with an about:blank URL and
+ // then executes some JS. Much of this work happens on the
+ // main (UI) thread.
+ // Ideally we want to have this assert here:
+ // ASSERT(WebThreadIsLockedOrDisabled())
+ // but then we would need to include code from
+ // WebCore. So just don't do any ASSERTs here.
+ if (m_refCounter.derefBase()) {
+ threadSafeDeref();
+ delete this;
+ } else {
+#ifndef NDEBUG
+ // Clear the threadId when the ref goes to 1 because it
+ // is safe to be passed to another thread at this point.
+ if (m_threadId && m_refCounter.refCount() == 1)
+ m_threadId = 0;
+#endif
+ }
+ }
+
+ template<class T>
+ T* CrossThreadRefCounted<T>::release()
+ {
+ ASSERT(!isShared());
+
+ T* data = m_data;
+ m_data = 0;
+ return data;
+ }
+
+ template<class T>
+ PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy()
+ {
+ if (m_threadSafeRefCounter)
+ m_threadSafeRefCounter->ref();
+ else
+ m_threadSafeRefCounter = new ThreadSafeSharedBase(2);
+ return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
+ }
+
+
+ template<class T>
+ void CrossThreadRefCounted<T>::threadSafeDeref()
+ {
+ if (m_threadSafeRefCounter && m_threadSafeRefCounter->derefBase()) {
+ delete m_threadSafeRefCounter;
+ m_threadSafeRefCounter = 0;
+ }
+ }
+} // namespace WTF
+
+using WTF::CrossThreadRefCounted;
+
+#endif // CrossThreadRefCounted_h
#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 PLATFORM(WIN_OS)
+// Windows is first since we want to use hires timers, despite PLATFORM(CF)
+// being defined.
// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <time.h>
+#elif PLATFORM(CF)
+#include <CoreFoundation/CFDate.h>
+#elif PLATFORM(GTK)
+#include <glib.h>
+#elif PLATFORM(WX)
+#include <wx/datetime.h>
#else // Posix systems relying on the gettimeofday()
#include <sys/time.h>
#endif
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)
+#if PLATFORM(WIN_OS)
static LARGE_INTEGER qpcFrequency;
static bool syncedTime;
static double lowResUTCTime()
{
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE)
SYSTEMTIME systemTime;
GetSystemTime(&systemTime);
struct tm tmtime;
tmtime.tm_sec = systemTime.wSecond;
time_t timet = mktime(&tmtime);
return timet * msPerSecond + systemTime.wMilliseconds;
-#else // PLATFORM(WIN_CE)
+#else
struct _timeb timebuffer;
_ftime(&timebuffer);
return timebuffer.time * msPerSecond + timebuffer.millitm;
-#endif // PLATFORM(WIN_CE)
+#endif
}
static bool qpcAvailable()
return utc / 1000.0;
}
+#elif PLATFORM(CF)
+
+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);
+}
+
#else // Other Posix systems rely on the gettimeofday().
double currentTime()
// 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.
+ // than a millisecond.
double currentTime();
} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ * 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 "Assertions.h"
+#include "ASCIICType.h"
+#include "CurrentTime.h"
+#include "MathExtras.h"
+#include "StringExtras.h"
+
+#include <algorithm>
+#include <limits.h>
+#include <limits>
+#include <stdint.h>
+#include <time.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
+
+#define NaN std::numeric_limits<double>::quiet_NaN()
+
+namespace WTF {
+
+/* 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(WINCE)
+ *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()
+{
+ time_t localTime = time(0);
+ tm localt;
+ getLocalTime(&localTime, &localt);
+
+ // Get the difference between this time zone and UTC on the 1st of January of this year.
+ localt.tm_sec = 0;
+ localt.tm_min = 0;
+ localt.tm_hour = 0;
+ localt.tm_mday = 1;
+ localt.tm_mon = 0;
+ // Not setting localt.tm_year!
+ localt.tm_wday = 0;
+ localt.tm_yday = 0;
+ localt.tm_isdst = 0;
+#if PLATFORM(WIN_OS) || PLATFORM(SOLARIS) || COMPILER(RVCT)
+ // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo.
+ localt.tm_year = 109;
+ time_t utcOffset = 1230768000 - mktime(&localt);
+#else
+ localt.tm_zone = 0;
+ localt.tm_gmtoff = 0;
+ time_t utcOffset = timegm(&localt) - mktime(&localt);
+#endif
+
+ 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 = outputIsUTC ? 0 : static_cast<long>((dstOff + utcOff) / msPerSecond);
+ tm.timeZone = NULL;
+}
+
+void initializeDates()
+{
+#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 parseDateFromNullTerminatedCharacters(const char* dateString)
+{
+ // 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.
+
+ // 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);
+}
+
+
+} // namespace WTF
--- /dev/null
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 WTF {
+
+struct GregorianDateTime;
+
+void initializeDates();
+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 parseDateFromNullTerminatedCharacters(const char*);
+double timeClip(double);
+
+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 WTF
+
+#endif // DateMath_h
/*
* 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
template<typename T> class DequeConstReverseIterator;
template<typename T>
- class Deque {
+ class Deque : public FastAllocBase {
public:
typedef DequeIterator<T> iterator;
typedef DequeConstIterator<T> const_iterator;
template<typename U> void append(const U&);
template<typename U> void prepend(const U&);
void removeFirst();
+ void remove(iterator&);
+ void remove(const_iterator&);
void clear();
+ template<typename Predicate>
+ iterator findIf(Predicate&);
+
private:
friend class DequeIteratorBase<T>;
typedef VectorTypeOperations<T> TypeOperations;
typedef DequeIteratorBase<T> IteratorBase;
+ void remove(size_t position);
void invalidateIterators();
void destroyAll();
void checkValidity() const;
private:
void addToIteratorsList();
+ void removeFromIteratorsList();
void checkValidity() const;
void checkValidity(const Base&) const;
destroyAll();
}
- template <typename T>
+ template<typename T>
inline void Deque<T>::swap(Deque<T>& other)
{
checkValidity();
other.checkValidity();
}
- template <typename T>
+ template<typename T>
inline void Deque<T>::clear()
{
checkValidity();
checkValidity();
}
+ template<typename T>
+ template<typename Predicate>
+ inline DequeIterator<T> Deque<T>::findIf(Predicate& predicate)
+ {
+ iterator end_iterator = end();
+ for (iterator it = begin(); it != end_iterator; ++it) {
+ if (predicate(*it))
+ return it;
+ }
+ return end_iterator;
+ }
+
template<typename T>
inline void Deque<T>::expandCapacityIfNeeded()
{
checkValidity();
}
+ template<typename T>
+ inline void Deque<T>::remove(iterator& it)
+ {
+ it.checkValidity();
+ remove(it.m_index);
+ }
+
+ template<typename T>
+ inline void Deque<T>::remove(const_iterator& it)
+ {
+ it.checkValidity();
+ remove(it.m_index);
+ }
+
+ template<typename T>
+ inline void Deque<T>::remove(size_t position)
+ {
+ if (position == m_end)
+ return;
+
+ checkValidity();
+ invalidateIterators();
+
+ T* buffer = m_buffer.buffer();
+ TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
+
+ // Find which segment of the circular buffer contained the remove element, and only move elements in that part.
+ if (position >= m_start) {
+ TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1);
+ m_start = (m_start + 1) % m_buffer.capacity();
+ } else {
+ TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position);
+ m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
+ }
+ checkValidity();
+ }
+
#ifdef NDEBUG
template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { }
template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { }
template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { }
+ template<typename T> inline void DequeIteratorBase<T>::removeFromIteratorsList() { }
#else
template<typename T>
void DequeIteratorBase<T>::checkValidity() const
}
m_previous = 0;
}
+
+ template<typename T>
+ void DequeIteratorBase<T>::removeFromIteratorsList()
+ {
+ if (!m_deque) {
+ ASSERT(!m_next);
+ ASSERT(!m_previous);
+ } else {
+ if (m_next) {
+ ASSERT(m_next->m_previous == this);
+ m_next->m_previous = m_previous;
+ }
+ if (m_previous) {
+ ASSERT(m_deque->m_iterators != this);
+ ASSERT(m_previous->m_next == this);
+ m_previous->m_next = m_next;
+ } else {
+ ASSERT(m_deque->m_iterators == this);
+ m_deque->m_iterators = m_next;
+ }
+ }
+ m_next = 0;
+ m_previous = 0;
+ }
#endif
template<typename T>
checkValidity();
}
+ template<typename T>
+ inline DequeIteratorBase<T>& DequeIteratorBase<T>::operator=(const Base& other)
+ {
+ checkValidity();
+ other.checkValidity();
+ removeFromIteratorsList();
+
+ m_deque = other.m_deque;
+ m_index = other.m_index;
+ addToIteratorsList();
+ checkValidity();
+ return *this;
+ }
+
template<typename T>
inline DequeIteratorBase<T>::~DequeIteratorBase()
{
#ifndef NDEBUG
- // Delete iterator from doubly-linked list of iterators.
- if (!m_deque) {
- ASSERT(!m_next);
- ASSERT(!m_previous);
- } else {
- if (m_next) {
- ASSERT(m_next->m_previous == this);
- m_next->m_previous = m_previous;
- }
- if (m_previous) {
- ASSERT(m_deque->m_iterators != this);
- ASSERT(m_previous->m_next == this);
- m_previous->m_next = m_next;
- } else {
- ASSERT(m_deque->m_iterators == this);
- m_deque->m_iterators = m_next;
- }
- }
+ removeFromIteratorsList();
m_deque = 0;
- m_next = 0;
- m_previous = 0;
#endif
}
#ifndef WTF_DisallowCType_h
#define WTF_DisallowCType_h
+#include "Platform.h"
+
+#define _DONT_USE_CTYPE_INLINE_
+
// The behavior of many of the functions in the <ctype.h> header is dependent
// on the current locale. But almost all uses of these functions are for
// locale-independent, ASCII-specific purposes. In WebKit code we use our own
--- /dev/null
+/*
+ * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. 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 FastAllocBase_h
+#define FastAllocBase_h
+
+// Provides customizable overrides of fastMalloc/fastFree and operator new/delete
+//
+// Provided functionality:
+// namespace WTF {
+// class FastAllocBase;
+//
+// T* fastNew<T>();
+// T* fastNew<T>(arg);
+// T* fastNew<T>(arg, arg);
+// T* fastNewArray<T>(count);
+// void fastDelete(T* p);
+// void fastDeleteArray(T* p);
+// void fastNonNullDelete(T* p);
+// void fastNonNullDeleteArray(T* p);
+// }
+//
+// FastDelete assumes that the underlying
+//
+// Example usage:
+// class Widget : public FastAllocBase { ... };
+//
+// char* charPtr = fastNew<char>();
+// fastDelete(charPtr);
+//
+// char* charArrayPtr = fastNewArray<char>(37);
+// fastDeleteArray(charArrayPtr);
+//
+// void** voidPtrPtr = fastNew<void*>();
+// fastDelete(voidPtrPtr);
+//
+// void** voidPtrArrayPtr = fastNewArray<void*>(37);
+// fastDeleteArray(voidPtrArrayPtr);
+//
+// POD* podPtr = fastNew<POD>();
+// fastDelete(podPtr);
+//
+// POD* podArrayPtr = fastNewArray<POD>(37);
+// fastDeleteArray(podArrayPtr);
+//
+// Object* objectPtr = fastNew<Object>();
+// fastDelete(objectPtr);
+//
+// Object* objectArrayPtr = fastNewArray<Object>(37);
+// fastDeleteArray(objectArrayPtr);
+//
+
+#include <new>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "Assertions.h"
+#include "FastMalloc.h"
+#include "TypeTraits.h"
+
+namespace WTF {
+
+ class FastAllocBase {
+ public:
+ // Placement operator new.
+ void* operator new(size_t, void* p) { return p; }
+ void* operator new[](size_t, void* p) { return p; }
+
+ void* operator new(size_t size)
+ {
+ void* p = fastMalloc(size);
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew);
+ return p;
+ }
+
+ void operator delete(void* p)
+ {
+ fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew);
+ fastFree(p);
+ }
+
+ void* operator new[](size_t size)
+ {
+ void* p = fastMalloc(size);
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray);
+ return p;
+ }
+
+ void operator delete[](void* p)
+ {
+ fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray);
+ fastFree(p);
+ }
+ };
+
+ // fastNew / fastDelete
+
+ template <typename T>
+ inline T* fastNew()
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T;
+ }
+
+ template <typename T, typename Arg1>
+ inline T* fastNew(Arg1 arg1)
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T(arg1);
+ }
+
+ template <typename T, typename Arg1, typename Arg2>
+ inline T* fastNew(Arg1 arg1, Arg2 arg2)
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T(arg1, arg2);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T(arg1, arg2, arg3);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T(arg1, arg2, arg3, arg4);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+ inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+ {
+ void* p = fastMalloc(sizeof(T));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
+ return ::new(p) T(arg1, arg2, arg3, arg4, arg5);
+ }
+
+ namespace Internal {
+
+ // We define a union of pointer to an integer and pointer to T.
+ // When non-POD arrays are allocated we add a few leading bytes to tell what
+ // the size of the array is. We return to the user the pointer to T.
+ // The way to think of it is as if we allocate a struct like so:
+ // struct Array {
+ // AllocAlignmentInteger m_size;
+ // T m_T[array count];
+ // };
+
+ template <typename T>
+ union ArraySize {
+ AllocAlignmentInteger* size;
+ T* t;
+ };
+
+ // This is a support template for fastNewArray.
+ // This handles the case wherein T has a trivial ctor and a trivial dtor.
+ template <typename T, bool trivialCtor, bool trivialDtor>
+ struct NewArrayImpl {
+ static T* fastNewArray(size_t count)
+ {
+ T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
+ return p;
+ }
+ };
+
+ // This is a support template for fastNewArray.
+ // This handles the case wherein T has a non-trivial ctor and a trivial dtor.
+ template <typename T>
+ struct NewArrayImpl<T, false, true> {
+ static T* fastNewArray(size_t count)
+ {
+ T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
+
+ for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
+ ::new(pObject) T;
+
+ return p;
+ }
+ };
+
+ // This is a support template for fastNewArray.
+ // This handles the case wherein T has a trivial ctor and a non-trivial dtor.
+ template <typename T>
+ struct NewArrayImpl<T, true, false> {
+ static T* fastNewArray(size_t count)
+ {
+ void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
+ ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
+ *a.size++ = count;
+ // No need to construct the objects in this case.
+
+ return a.t;
+ }
+ };
+
+ // This is a support template for fastNewArray.
+ // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor.
+ template <typename T>
+ struct NewArrayImpl<T, false, false> {
+ static T* fastNewArray(size_t count)
+ {
+ void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
+ ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
+
+ if (!p)
+ return 0;
+
+ fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
+ *a.size++ = count;
+
+ for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
+ ::new(pT) T;
+
+ return a.t;
+ }
+ };
+ } // namespace Internal
+
+ template <typename T>
+ inline T* fastNewArray(size_t count)
+ {
+ return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
+ }
+
+ template <typename T>
+ inline void fastDelete(T* p)
+ {
+ if (!p)
+ return;
+
+ fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
+ p->~T();
+ fastFree(p);
+ }
+
+ namespace Internal {
+ // This is a support template for fastDeleteArray.
+ // This handles the case wherein T has a trivial dtor.
+ template <typename T, bool trivialDtor>
+ struct DeleteArrayImpl {
+ static void fastDeleteArray(void* p)
+ {
+ // No need to destruct the objects in this case.
+ // We expect that fastFree checks for null.
+ fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
+ fastFree(p);
+ }
+ };
+
+ // This is a support template for fastDeleteArray.
+ // This handles the case wherein T has a non-trivial dtor.
+ template <typename T>
+ struct DeleteArrayImpl<T, false> {
+ static void fastDeleteArray(T* p)
+ {
+ if (!p)
+ return;
+
+ ArraySize<T> a;
+ a.t = p;
+ a.size--; // Decrement size pointer
+
+ T* pEnd = p + *a.size;
+ while (pEnd-- != p)
+ pEnd->~T();
+
+ fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
+ fastFree(a.size);
+ }
+ };
+
+ } // namespace Internal
+
+ template <typename T>
+ void fastDeleteArray(T* p)
+ {
+ Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
+ }
+
+
+ template <typename T>
+ inline void fastNonNullDelete(T* p)
+ {
+ fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
+ p->~T();
+ fastFree(p);
+ }
+
+ namespace Internal {
+ // This is a support template for fastDeleteArray.
+ // This handles the case wherein T has a trivial dtor.
+ template <typename T, bool trivialDtor>
+ struct NonNullDeleteArrayImpl {
+ static void fastNonNullDeleteArray(void* p)
+ {
+ fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
+ // No need to destruct the objects in this case.
+ fastFree(p);
+ }
+ };
+
+ // This is a support template for fastDeleteArray.
+ // This handles the case wherein T has a non-trivial dtor.
+ template <typename T>
+ struct NonNullDeleteArrayImpl<T, false> {
+ static void fastNonNullDeleteArray(T* p)
+ {
+ ArraySize<T> a;
+ a.t = p;
+ a.size--;
+
+ T* pEnd = p + *a.size;
+ while (pEnd-- != p)
+ pEnd->~T();
+
+ fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
+ fastFree(a.size);
+ }
+ };
+
+ } // namespace Internal
+
+ template <typename T>
+ void fastNonNullDeleteArray(T* p)
+ {
+ Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
+ }
+
+
+} // namespace WTF
+
+// Using WTF::FastAllocBase to avoid using FastAllocBase's explicit qualification by WTF::.
+using WTF::FastAllocBase;
+
+#endif // FastAllocBase_h
#include "FastMalloc.h"
#include "Assertions.h"
+#include <limits>
#if ENABLE(JSC_MULTIPLE_THREADS)
#include <pthread.h>
#endif
-#include <Availability.h>
-
#ifndef NO_TCMALLOC_SAMPLES
#ifdef WTF_CHANGES
#define NO_TCMALLOC_SAMPLES
#define FORCE_SYSTEM_MALLOC 1
#endif
-#define TCMALLOC_TRACK_DECOMMITED_SPANS (HAVE(VIRTUALALLOC))
+
+// Use a background thread to periodically scavenge memory to release back to the system
+// https://bugs.webkit.org/show_bug.cgi?id=27900: don't turn this on for Tiger until we have figured out why it caused a crash.
+#define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0
#ifndef NDEBUG
namespace WTF {
namespace WTF {
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+
+namespace Internal {
+
+void fastMallocMatchFailed(void*)
+{
+ CRASH();
+}
+
+} // namespace Internal
+
+#endif
+
void* fastZeroedMalloc(size_t n)
{
void* result = fastMalloc(n);
void* tryFastMalloc(size_t n)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur...
+ return 0;
+
+ void* result = malloc(n + sizeof(AllocAlignmentInteger));
+ if (!result)
+ return 0;
+
+ *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
+ result = static_cast<AllocAlignmentInteger*>(result) + 1;
+
+ return result;
+#else
return malloc(n);
+#endif
}
void* fastMalloc(size_t n)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ void* result = tryFastMalloc(n);
+#else
void* result = malloc(n);
+#endif
+
if (!result)
CRASH();
return result;
void* tryFastCalloc(size_t n_elements, size_t element_size)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ size_t totalBytes = n_elements * element_size;
+ if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements || (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes))
+ return 0;
+
+ totalBytes += sizeof(AllocAlignmentInteger);
+ void* result = malloc(totalBytes);
+ if (!result)
+ return 0;
+
+ memset(result, 0, totalBytes);
+ *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
+ result = static_cast<AllocAlignmentInteger*>(result) + 1;
+ return result;
+#else
return calloc(n_elements, element_size);
+#endif
}
void* fastCalloc(size_t n_elements, size_t element_size)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ void* result = tryFastCalloc(n_elements, element_size);
+#else
void* result = calloc(n_elements, element_size);
+#endif
+
if (!result)
CRASH();
return result;
void fastFree(void* p)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (!p)
+ return;
+
+ AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p);
+ if (*header != Internal::AllocTypeMalloc)
+ Internal::fastMallocMatchFailed(p);
+ free(header);
+#else
free(p);
+#endif
}
void* tryFastRealloc(void* p, size_t n)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (p) {
+ if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur...
+ return 0;
+ AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p);
+ if (*header != Internal::AllocTypeMalloc)
+ Internal::fastMallocMatchFailed(p);
+ void* result = realloc(header, n + sizeof(AllocAlignmentInteger));
+ if (!result)
+ return 0;
+
+ // This should not be needed because the value is already there:
+ // *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
+ result = static_cast<AllocAlignmentInteger*>(result) + 1;
+ return result;
+ } else {
+ return fastMalloc(n);
+ }
+#else
return realloc(p, n);
+#endif
}
void* fastRealloc(void* p, size_t n)
{
ASSERT(!isForbidden());
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ void* result = tryFastRealloc(p, n);
+#else
void* result = realloc(p, n);
+#endif
+
if (!result)
CRASH();
return result;
#include "TCSystemAlloc.h"
#include <algorithm>
#include <errno.h>
+#include <limits>
#include <new>
#include <pthread.h>
#include <stdarg.h>
#define CHECK_CONDITION ASSERT
#if PLATFORM(DARWIN)
+class Span;
+class TCMalloc_Central_FreeListPadded;
class TCMalloc_PageHeap;
class TCMalloc_ThreadCache;
-class TCMalloc_Central_FreeListPadded;
+template <typename T> class PageHeapAllocator;
class FastMallocZone {
public:
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*);
+ FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*, PageHeapAllocator<Span>*, PageHeapAllocator<TCMalloc_ThreadCache>*);
static size_t size(malloc_zone_t*, const void*);
static void* zoneMalloc(malloc_zone_t*, size_t);
static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size);
TCMalloc_PageHeap* m_pageHeap;
TCMalloc_ThreadCache** m_threadHeaps;
TCMalloc_Central_FreeListPadded* m_centralCaches;
+ PageHeapAllocator<Span>* m_spanAllocator;
+ PageHeapAllocator<TCMalloc_ThreadCache>* m_pageHeapAllocator;
};
#endif
char* free_area_;
size_t free_avail_;
+ // Linked list of all regions allocated by this allocator
+ void* allocated_regions_;
+
// Free list of already carved objects
void* free_list_;
void Init() {
ASSERT(kAlignedSize <= kAllocIncrement);
inuse_ = 0;
+ allocated_regions_ = 0;
free_area_ = NULL;
free_avail_ = 0;
free_list_ = NULL;
} else {
if (free_avail_ < kAlignedSize) {
// Need more room
- free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
- if (free_area_ == NULL) CRASH();
- free_avail_ = kAllocIncrement;
+ char* new_allocation = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
+ if (!new_allocation)
+ CRASH();
+
+ *(void**)new_allocation = allocated_regions_;
+ allocated_regions_ = new_allocation;
+ free_area_ = new_allocation + kAlignedSize;
+ free_avail_ = kAllocIncrement - kAlignedSize;
}
result = free_area_;
free_area_ += kAlignedSize;
}
int inuse() const { return inuse_; }
+
+#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+ template <class Recorder>
+ void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
+ {
+ vm_address_t adminAllocation = reinterpret_cast<vm_address_t>(allocated_regions_);
+ while (adminAllocation) {
+ recorder.recordRegion(adminAllocation, kAllocIncrement);
+ adminAllocation = *reader(reinterpret_cast<vm_address_t*>(adminAllocation));
+ }
+ }
+#endif
};
// -------------------------------------------------------------------------
#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) {
// contiguous runs of pages (called a "span").
// -------------------------------------------------------------------------
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+// The central page heap collects spans of memory that have been deleted but are still committed until they are released
+// back to the system. We use a background thread to periodically scan the list of free spans and release some back to the
+// system. Every 5 seconds, the background thread wakes up and does the following:
+// - Check if we needed to commit memory in the last 5 seconds. If so, skip this scavenge because it's a sign that we are short
+// of free committed pages and so we should not release them back to the system yet.
+// - Otherwise, go through the list of free spans (from largest to smallest) and release up to a fraction of the free committed pages
+// back to the system.
+// - If the number of free committed pages reaches kMinimumFreeCommittedPageCount, we can stop the scavenging and block the
+// scavenging thread until the number of free committed pages goes above kMinimumFreeCommittedPageCount.
+
+// Background thread wakes up every 5 seconds to scavenge as long as there is memory available to return to the system.
+static const int kScavengeTimerDelayInSeconds = 5;
+
+// Number of free committed pages that we want to keep around.
+static const size_t kMinimumFreeCommittedPageCount = 512;
+
+// During a scavenge, we'll release up to a fraction of the free committed pages.
+#if PLATFORM(WIN)
+// We are slightly less aggressive in releasing memory on Windows due to performance reasons.
+static const int kMaxScavengeAmountFactor = 3;
+#else
+static const int kMaxScavengeAmountFactor = 2;
+#endif
+#endif
+
class TCMalloc_PageHeap {
public:
void init();
// Bytes allocated from system
uint64_t system_bytes_;
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ // Number of pages kept in free lists that are still committed.
+ Length free_committed_pages_;
+
+ // Number of pages that we committed in the last scavenge wait interval.
+ Length pages_committed_since_last_scavenge_;
+#endif
+
bool GrowHeap(Length n);
// REQUIRES span->length >= n
// span of exactly the specified length. Else, returns NULL.
Span* AllocLarge(Length n);
+#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
// Incrementally release some memory to the system.
// IncrementalScavenge(n) is called whenever n pages are freed.
void IncrementalScavenge(Length n);
+#endif
// Number of pages to deallocate before doing more scavenging
int64_t scavenge_counter_;
#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
friend class FastMallocZone;
#endif
+
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ static NO_RETURN void* runScavengerThread(void*);
+
+ NO_RETURN void scavengerThread();
+
+ void scavenge();
+
+ inline bool shouldContinueScavenging() const;
+
+ pthread_mutex_t m_scavengeMutex;
+
+ pthread_cond_t m_scavengeCondition;
+
+ // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or
+ // it's blocked waiting for more pages to be deleted.
+ bool m_scavengeThreadActive;
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
};
void TCMalloc_PageHeap::init()
pagemap_cache_ = PageMapCache(0);
free_pages_ = 0;
system_bytes_ = 0;
+
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ free_committed_pages_ = 0;
+ pages_committed_since_last_scavenge_ = 0;
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+
scavenge_counter_ = 0;
// Start scavenging at kMaxPages list
scavenge_index_ = kMaxPages-1;
DLL_Init(&free_[i].normal);
DLL_Init(&free_[i].returned);
}
+
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ pthread_mutex_init(&m_scavengeMutex, 0);
+ pthread_cond_init(&m_scavengeCondition, 0);
+ m_scavengeThreadActive = true;
+ pthread_t thread;
+ pthread_create(&thread, 0, runScavengerThread, this);
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
}
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+void* TCMalloc_PageHeap::runScavengerThread(void* context)
+{
+ static_cast<TCMalloc_PageHeap*>(context)->scavengerThread();
+#if COMPILER(MSVC)
+ // Without this, Visual Studio will complain that this method does not return a value.
+ return 0;
+#endif
+}
+
+void TCMalloc_PageHeap::scavenge()
+{
+ // If we have to commit memory in the last 5 seconds, it means we don't have enough free committed pages
+ // for the amount of allocations that we do. So hold off on releasing memory back to the system.
+ if (pages_committed_since_last_scavenge_ > 0) {
+ pages_committed_since_last_scavenge_ = 0;
+ return;
+ }
+ Length pagesDecommitted = 0;
+ for (int i = kMaxPages; i >= 0; i--) {
+ SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i];
+ if (!DLL_IsEmpty(&slist->normal)) {
+ // Release the last span on the normal portion of this list
+ Span* s = slist->normal.prev;
+ // Only decommit up to a fraction of the free committed pages if pages_allocated_since_last_scavenge_ > 0.
+ if ((pagesDecommitted + s->length) * kMaxScavengeAmountFactor > free_committed_pages_)
+ continue;
+ DLL_Remove(s);
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
+ static_cast<size_t>(s->length << kPageShift));
+ if (!s->decommitted) {
+ pagesDecommitted += s->length;
+ s->decommitted = true;
+ }
+ DLL_Prepend(&slist->returned, s);
+ // We can stop scavenging if the number of free committed pages left is less than or equal to the minimum number we want to keep around.
+ if (free_committed_pages_ <= kMinimumFreeCommittedPageCount + pagesDecommitted)
+ break;
+ }
+ }
+ pages_committed_since_last_scavenge_ = 0;
+ ASSERT(free_committed_pages_ >= pagesDecommitted);
+ free_committed_pages_ -= pagesDecommitted;
+}
+
+inline bool TCMalloc_PageHeap::shouldContinueScavenging() const
+{
+ return free_committed_pages_ > kMinimumFreeCommittedPageCount;
+}
+
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+
inline Span* TCMalloc_PageHeap::New(Length n) {
ASSERT(Check());
ASSERT(n > 0);
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;
- }
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ pages_committed_since_last_scavenge_ += n;
#endif
+ }
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ else {
+ // The newly allocated memory is from a span that's in the normal span list (already committed). Update the
+ // free committed pages count.
+ ASSERT(free_committed_pages_ >= n);
+ free_committed_pages_ -= n;
+ }
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
ASSERT(Check());
free_pages_ -= n;
return result;
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;
- }
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ pages_committed_since_last_scavenge_ += n;
#endif
+ }
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ else {
+ // The newly allocated memory is from a span that's in the normal span list (already committed). Update the
+ // free committed pages count.
+ ASSERT(free_committed_pages_ >= n);
+ free_committed_pages_ -= n;
+ }
+#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
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);
}
}
-#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)
+ if (destination->decommitted && !other->decommitted) {
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(other->start << kPageShift),
+ static_cast<size_t>(other->length << kPageShift));
+ } else if (other->decommitted && !destination->decommitted) {
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(destination->start << kPageShift),
+ static_cast<size_t>(destination->length << kPageShift));
destination->decommitted = true;
+ }
}
-#endif
inline void TCMalloc_PageHeap::Delete(Span* span) {
ASSERT(Check());
// necessary. We do not bother resetting the stale pagemap
// entries for the pieces we are merging together because we only
// care about the pagemap entries for the boundaries.
- //
- // Note that the spans we merge into "span" may come out of
- // a "returned" list. For simplicity, we move these into the
- // "normal" list of the appropriate size class.
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ // Track the total size of the neighboring free spans that are committed.
+ Length neighboringCommittedSpansLength = 0;
+#endif
const PageID p = span->start;
const Length n = span->length;
Span* prev = GetDescriptor(p-1);
// Merge preceding span into this span
ASSERT(prev->start + prev->length == p);
const Length len = prev->length;
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ if (!prev->decommitted)
+ neighboringCommittedSpansLength += len;
+#endif
mergeDecommittedStates(span, prev);
DLL_Remove(prev);
DeleteSpan(prev);
// Merge next span into this span
ASSERT(next->start == p+n);
const Length len = next->length;
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ if (!next->decommitted)
+ neighboringCommittedSpansLength += len;
+#endif
mergeDecommittedStates(span, next);
DLL_Remove(next);
DeleteSpan(next);
Event(span, 'D', span->length);
span->free = 1;
- if (span->length < kMaxPages) {
- DLL_Prepend(&free_[span->length].normal, span);
+ if (span->decommitted) {
+ if (span->length < kMaxPages)
+ DLL_Prepend(&free_[span->length].returned, span);
+ else
+ DLL_Prepend(&large_.returned, span);
} else {
- DLL_Prepend(&large_.normal, span);
+ if (span->length < kMaxPages)
+ DLL_Prepend(&free_[span->length].normal, span);
+ else
+ DLL_Prepend(&large_.normal, span);
}
free_pages_ += n;
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ if (span->decommitted) {
+ // If the merged span is decommitted, that means we decommitted any neighboring spans that were
+ // committed. Update the free committed pages count.
+ free_committed_pages_ -= neighboringCommittedSpansLength;
+ } else {
+ // If the merged span remains committed, add the deleted span's size to the free committed pages count.
+ free_committed_pages_ += n;
+ }
+
+ // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system.
+ if (!m_scavengeThreadActive && shouldContinueScavenging())
+ pthread_cond_signal(&m_scavengeCondition);
+#else
IncrementalScavenge(n);
+#endif
+
ASSERT(Check());
}
+#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
// Fast path; not yet time to release memory
scavenge_counter_ -= n;
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)));
// Nothing to scavenge, delay for a while
scavenge_counter_ = kDefaultReleaseDelay;
}
+#endif
void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) {
// Associate span object with all interior pages as well
}
ask = actual_size >> kPageShift;
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+ pages_committed_since_last_scavenge_ += ask;
+#endif
+
uint64_t old_system_bytes = system_bytes_;
system_bytes_ += (ask << kPageShift);
const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
#define pageheap getPageHeap()
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+#if PLATFORM(WIN)
+static void sleep(unsigned seconds)
+{
+ ::Sleep(seconds * 1000);
+}
+#endif
+
+void TCMalloc_PageHeap::scavengerThread()
+{
+#if HAVE(PTHREAD_SETNAME_NP)
+ pthread_setname_np("JavaScriptCore: FastMalloc scavenger");
+#endif
+
+ while (1) {
+ if (!shouldContinueScavenging()) {
+ pthread_mutex_lock(&m_scavengeMutex);
+ m_scavengeThreadActive = false;
+ // Block until there are enough freed pages to release back to the system.
+ pthread_cond_wait(&m_scavengeCondition, &m_scavengeMutex);
+ m_scavengeThreadActive = true;
+ pthread_mutex_unlock(&m_scavengeMutex);
+ }
+ sleep(kScavengeTimerDelayInSeconds);
+ {
+ SpinLockHolder h(&pageheap_lock);
+ pageheap->scavenge();
+ }
+ }
+}
+#endif
+
// If TLS is available, we also store a copy
// of the per-thread object in a __thread variable
// since __thread variables are faster to read
ALWAYS_INLINE
#endif
void* malloc(size_t size) {
- void* result = do_malloc(size);
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= size) // If overflow would occur...
+ return 0;
+ size += sizeof(AllocAlignmentInteger);
+ void* result = do_malloc(size);
+ if (!result)
+ return 0;
+
+ *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
+ result = static_cast<AllocAlignmentInteger*>(result) + 1;
+#else
+ void* result = do_malloc(size);
+#endif
+
#ifndef WTF_CHANGES
MallocHook::InvokeNewHook(result, size);
#endif
#ifndef WTF_CHANGES
MallocHook::InvokeDeleteHook(ptr);
#endif
- do_free(ptr);
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (!ptr)
+ return;
+
+ AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(ptr);
+ if (*header != Internal::AllocTypeMalloc)
+ Internal::fastMallocMatchFailed(ptr);
+ do_free(header);
+#else
+ do_free(ptr);
+#endif
}
#ifndef WTF_CHANGES
ALWAYS_INLINE
#endif
void* calloc(size_t n, size_t elem_size) {
- const size_t totalBytes = n * elem_size;
+ size_t totalBytes = n * elem_size;
// Protect against overflow
if (n > 1 && elem_size && (totalBytes / elem_size) != n)
return 0;
-
- void* result = do_malloc(totalBytes);
- if (result != NULL) {
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes) // If overflow would occur...
+ return 0;
+
+ totalBytes += sizeof(AllocAlignmentInteger);
+ void* result = do_malloc(totalBytes);
+ if (!result)
+ return 0;
+
memset(result, 0, totalBytes);
- }
+ *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
+ result = static_cast<AllocAlignmentInteger*>(result) + 1;
+#else
+ void* result = do_malloc(totalBytes);
+ if (result != NULL) {
+ memset(result, 0, totalBytes);
+ }
+#endif
+
#ifndef WTF_CHANGES
MallocHook::InvokeNewHook(result, totalBytes);
#endif
#endif
void* realloc(void* old_ptr, size_t new_size) {
if (old_ptr == NULL) {
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ void* result = malloc(new_size);
+#else
void* result = do_malloc(new_size);
#ifndef WTF_CHANGES
MallocHook::InvokeNewHook(result, new_size);
+#endif
#endif
return result;
}
return NULL;
}
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= new_size) // If overflow would occur...
+ return 0;
+ new_size += sizeof(AllocAlignmentInteger);
+ AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(old_ptr);
+ if (*header != Internal::AllocTypeMalloc)
+ Internal::fastMallocMatchFailed(old_ptr);
+ old_ptr = header;
+#endif
+
// Get the size of the old entry
const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift;
size_t cl = pageheap->GetSizeClassIfCached(p);
// that we already know the sizeclass of old_ptr. The benefit
// would be small, so don't bother.
do_free(old_ptr);
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ new_ptr = static_cast<AllocAlignmentInteger*>(new_ptr) + 1;
+#endif
return new_ptr;
} else {
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+ old_ptr = pByte + sizeof(AllocAlignmentInteger); // Set old_ptr back to the user pointer.
+#endif
return old_ptr;
}
}
#if defined(__GLIBC__)
extern "C" {
-# if defined(__GNUC__) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__)
+#if COMPILER(GCC) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__)
// Potentially faster variants that use the gcc alias extension.
// Mach-O (Darwin) does not support weak aliases, hence the __MACH__ check.
# define ALIAS(x) __attribute__ ((weak, alias (x)))
void visit(void* ptr) { m_freeObjects.add(ptr); }
bool isFreeObject(void* ptr) const { return m_freeObjects.contains(ptr); }
+ bool isFreeObject(vm_address_t ptr) const { return isFreeObject(reinterpret_cast<void*>(ptr)); }
size_t freeObjectCount() const { return m_freeObjects.size(); }
void findFreeObjects(TCMalloc_ThreadCache* threadCache)
vm_range_recorder_t* m_recorder;
const RemoteMemoryReader& m_reader;
const FreeObjectFinder& m_freeObjectFinder;
- mutable HashSet<void*> m_seenPointers;
+
+ HashSet<void*> m_seenPointers;
+ Vector<Span*> m_coalescedSpans;
public:
PageMapMemoryUsageRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader, const FreeObjectFinder& freeObjectFinder)
, m_freeObjectFinder(freeObjectFinder)
{ }
- int visit(void* ptr) const
+ ~PageMapMemoryUsageRecorder()
+ {
+ ASSERT(!m_coalescedSpans.size());
+ }
+
+ void recordPendingRegions()
+ {
+ Span* lastSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
+ vm_range_t ptrRange = { m_coalescedSpans[0]->start << kPageShift, 0 };
+ ptrRange.size = (lastSpan->start << kPageShift) - ptrRange.address + (lastSpan->length * kPageSize);
+
+ // Mark the memory region the spans represent as a candidate for containing pointers
+ if (m_typeMask & MALLOC_PTR_REGION_RANGE_TYPE)
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+
+ if (!(m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
+ m_coalescedSpans.clear();
+ return;
+ }
+
+ Vector<vm_range_t, 1024> allocatedPointers;
+ for (size_t i = 0; i < m_coalescedSpans.size(); ++i) {
+ Span *theSpan = m_coalescedSpans[i];
+ if (theSpan->free)
+ continue;
+
+ vm_address_t spanStartAddress = theSpan->start << kPageShift;
+ vm_size_t spanSizeInBytes = theSpan->length * kPageSize;
+
+ if (!theSpan->sizeclass) {
+ // If it's an allocated large object span, mark it as in use
+ if (!m_freeObjectFinder.isFreeObject(spanStartAddress))
+ allocatedPointers.append((vm_range_t){spanStartAddress, spanSizeInBytes});
+ } else {
+ const size_t objectSize = ByteSizeForClass(theSpan->sizeclass);
+
+ // Mark each allocated small object within the span as in use
+ const vm_address_t endOfSpan = spanStartAddress + spanSizeInBytes;
+ for (vm_address_t object = spanStartAddress; object + objectSize <= endOfSpan; object += objectSize) {
+ if (!m_freeObjectFinder.isFreeObject(object))
+ allocatedPointers.append((vm_range_t){object, objectSize});
+ }
+ }
+ }
+
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, allocatedPointers.data(), allocatedPointers.size());
+
+ m_coalescedSpans.clear();
+ }
+
+ int visit(void* ptr)
{
if (!ptr)
return 1;
Span* span = m_reader(reinterpret_cast<Span*>(ptr));
+ if (!span->start)
+ return 1;
+
if (m_seenPointers.contains(ptr))
return span->length;
m_seenPointers.add(ptr);
- // Mark the memory used for the Span itself as an administrative region
- vm_range_t ptrRange = { reinterpret_cast<vm_address_t>(ptr), sizeof(Span) };
- if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
- (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, &ptrRange, 1);
+ if (!m_coalescedSpans.size()) {
+ m_coalescedSpans.append(span);
+ return span->length;
+ }
- ptrRange.address = span->start << kPageShift;
- ptrRange.size = span->length * kPageSize;
+ Span* previousSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
+ vm_address_t previousSpanStartAddress = previousSpan->start << kPageShift;
+ vm_size_t previousSpanSizeInBytes = previousSpan->length * kPageSize;
- // Mark the memory region the span represents as candidates for containing pointers
- if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
- (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+ // If the new span is adjacent to the previous span, do nothing for now.
+ vm_address_t spanStartAddress = span->start << kPageShift;
+ if (spanStartAddress == previousSpanStartAddress + previousSpanSizeInBytes) {
+ m_coalescedSpans.append(span);
+ return span->length;
+ }
- if (!span->free && (m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
- // If it's an allocated large object span, mark it as in use
- if (span->sizeclass == 0 && !m_freeObjectFinder.isFreeObject(reinterpret_cast<void*>(ptrRange.address)))
- (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1);
- else if (span->sizeclass) {
- const size_t byteSize = ByteSizeForClass(span->sizeclass);
- unsigned totalObjects = (span->length << kPageShift) / byteSize;
- ASSERT(span->refcount <= totalObjects);
- char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
+ // New span is not adjacent to previous span, so record the spans coalesced so far.
+ recordPendingRegions();
+ m_coalescedSpans.append(span);
- // Mark each allocated small object within the span as in use
- for (unsigned i = 0; i < totalObjects; i++) {
- char* thisObject = ptr + (i * byteSize);
- if (m_freeObjectFinder.isFreeObject(thisObject))
- continue;
+ return span->length;
+ }
+};
- vm_range_t objectRange = { reinterpret_cast<vm_address_t>(thisObject), byteSize };
- (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &objectRange, 1);
- }
- }
+class AdminRegionRecorder {
+ task_t m_task;
+ void* m_context;
+ unsigned m_typeMask;
+ vm_range_recorder_t* m_recorder;
+ const RemoteMemoryReader& m_reader;
+
+ Vector<vm_range_t, 1024> m_pendingRegions;
+
+public:
+ AdminRegionRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader)
+ : m_task(task)
+ , m_context(context)
+ , m_typeMask(typeMask)
+ , m_recorder(recorder)
+ , m_reader(reader)
+ { }
+
+ void recordRegion(vm_address_t ptr, size_t size)
+ {
+ if (m_typeMask & MALLOC_ADMIN_REGION_RANGE_TYPE)
+ m_pendingRegions.append((vm_range_t){ ptr, size });
+ }
+
+ void visit(void *ptr, size_t size)
+ {
+ recordRegion(reinterpret_cast<vm_address_t>(ptr), size);
+ }
+
+ void recordPendingRegions()
+ {
+ if (m_pendingRegions.size()) {
+ (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, m_pendingRegions.data(), m_pendingRegions.size());
+ m_pendingRegions.clear();
}
+ }
- return span->length;
+ ~AdminRegionRecorder()
+ {
+ ASSERT(!m_pendingRegions.size());
}
};
TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
- pageMap->visit(pageMapFinder, memoryReader);
+ pageMap->visitValues(pageMapFinder, memoryReader);
PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder);
- pageMap->visit(usageRecorder, memoryReader);
+ pageMap->visitValues(usageRecorder, memoryReader);
+ usageRecorder.recordPendingRegions();
+
+ AdminRegionRecorder adminRegionRecorder(task, context, typeMask, recorder, memoryReader);
+ pageMap->visitAllocations(adminRegionRecorder, memoryReader);
+
+ PageHeapAllocator<Span>* spanAllocator = memoryReader(mzone->m_spanAllocator);
+ PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator = memoryReader(mzone->m_pageHeapAllocator);
+
+ spanAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
+ pageHeapAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
+
+ adminRegionRecorder.recordPendingRegions();
return 0;
}
extern "C" {
malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print,
&FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
+
+#if !PLATFORM(IPHONE_SIMULATOR)
+ , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
+#endif
+
};
}
-FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches)
+FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches, PageHeapAllocator<Span>* spanAllocator, PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator)
: m_pageHeap(pageHeap)
, m_threadHeaps(threadHeaps)
, m_centralCaches(centralCaches)
+ , m_spanAllocator(spanAllocator)
+ , m_pageHeapAllocator(pageHeapAllocator)
{
memset(&m_zone, 0, sizeof(m_zone));
m_zone.version = 4;
void FastMallocZone::init()
{
- static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache));
+ static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator);
}
#endif
};
FastMallocStatistics fastMallocStatistics();
+ // This defines a type which holds an unsigned integer and is the same
+ // size as the minimally aligned memory allocation.
+ typedef unsigned long long AllocAlignmentInteger;
+
+ namespace Internal {
+ enum AllocType { // Start with an unusual number instead of zero, because zero is common.
+ AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc.
+ AllocTypeClassNew, // Encompasses class operator new from FastAllocBase.
+ AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase.
+ AllocTypeFastNew, // Encompasses fastNew.
+ AllocTypeFastNewArray, // Encompasses fastNewArray.
+ AllocTypeNew, // Encompasses global operator new.
+ AllocTypeNewArray // Encompasses global operator new[].
+ };
+ }
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+
+ // Malloc validation is a scheme whereby a tag is attached to an
+ // allocation which identifies how it was originally allocated.
+ // This allows us to verify that the freeing operation matches the
+ // allocation operation. If memory is allocated with operator new[]
+ // but freed with free or delete, this system would detect that.
+ // In the implementation here, the tag is an integer prepended to
+ // the allocation memory which is assigned one of the AllocType
+ // enumeration values. An alternative implementation of this
+ // scheme could store the tag somewhere else or ignore it.
+ // Users of FastMalloc don't need to know or care how this tagging
+ // is implemented.
+
+ namespace Internal {
+
+ // Return the AllocType tag associated with the allocated block p.
+ inline AllocType fastMallocMatchValidationType(const void* p)
+ {
+ const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1;
+ return static_cast<AllocType>(*type);
+ }
+
+ // Return the address of the AllocType tag associated with the allocated block p.
+ inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p)
+ {
+ return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger));
+ }
+
+ // Set the AllocType tag to be associaged with the allocated block p.
+ inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
+ {
+ AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1;
+ *type = static_cast<AllocAlignmentInteger>(allocType);
+ }
+
+ // Handle a detected alloc/free mismatch. By default this calls CRASH().
+ void fastMallocMatchFailed(void* p);
+
+ } // namespace Internal
+
+ // This is a higher level function which is used by FastMalloc-using code.
+ inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType)
+ {
+ if (!p)
+ return;
+
+ Internal::setFastMallocMatchValidationType(p, allocType);
+ }
+
+ // This is a higher level function which is used by FastMalloc-using code.
+ inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType)
+ {
+ if (!p)
+ return;
+
+ if (Internal::fastMallocMatchValidationType(p) != allocType)
+ Internal::fastMallocMatchFailed(p);
+ Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK.
+ }
+
+#else
+
+ inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
+ {
+ }
+
+ inline void fastMallocMatchValidateFree(void*, Internal::AllocType)
+ {
+ }
+
+#endif
+
} // namespace WTF
using WTF::fastMalloc;
WTF_PRIVATE_INLINE void operator delete(void* p) { fastFree(p); }
WTF_PRIVATE_INLINE void* operator new[](size_t s) { return fastMalloc(s); }
WTF_PRIVATE_INLINE void operator delete[](void* p) { fastFree(p); }
+
+#if PLATFORM(WINCE)
+WTF_PRIVATE_INLINE void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
+WTF_PRIVATE_INLINE void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
+#endif
#endif
#endif // _CRTDBG_MAP_ALLOC
g_dir_close(ptr);
}
+template <> void freeOwnedGPtr<GHashTable>(GHashTable* ptr)
+{
+ if (ptr)
+ g_hash_table_unref(ptr);
+}
+
} // namespace WTF
template<> void freeOwnedGPtr<GMutex>(GMutex*);
template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
template<> void freeOwnedGPtr<GDir>(GDir*);
+ template<> void freeOwnedGPtr<GHashTable>(GHashTable*);
template <typename T> class GOwnPtr : Noncopyable {
public:
#define WTF_HashCountedSet_h
#include "Assertions.h"
+#include "FastAllocBase.h"
#include "HashMap.h"
#include "Vector.h"
namespace WTF {
template<typename Value, typename HashFunctions = typename DefaultHash<Value>::Hash,
- typename Traits = HashTraits<Value> > class HashCountedSet {
+ typename Traits = HashTraits<Value> > class HashCountedSet : public FastAllocBase {
private:
typedef HashMap<Value, unsigned, HashFunctions, Traits> ImplType;
public:
template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> >
- class HashMap {
+ class HashMap : public FastAllocBase {
private:
typedef KeyTraitsArg KeyTraits;
typedef MappedTraitsArg MappedTraits;
#ifndef WTF_HashSet_h
#define WTF_HashSet_h
+#include "FastAllocBase.h"
#include "HashTable.h"
namespace WTF {
template<typename T> struct IdentityExtractor;
template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
- typename TraitsArg = HashTraits<ValueArg> > class HashSet {
+ typename TraitsArg = HashTraits<ValueArg> > class HashSet : public FastAllocBase {
private:
typedef HashArg HashFunctions;
typedef TraitsArg ValueTraits;
#ifndef WTF_HashTraits_h
#define WTF_HashTraits_h
-#include "Assertions.h"
#include "HashFunctions.h"
+#include "TypeTraits.h"
#include <utility>
#include <limits>
using std::pair;
using std::make_pair;
- template<typename T> struct IsInteger { static const bool value = false; };
- template<> struct IsInteger<bool> { static const bool value = true; };
- template<> struct IsInteger<char> { static const bool value = true; };
- template<> struct IsInteger<signed char> { static const bool value = true; };
- template<> struct IsInteger<unsigned char> { static const bool value = true; };
- template<> struct IsInteger<short> { static const bool value = true; };
- template<> struct IsInteger<unsigned short> { static const bool value = true; };
- template<> struct IsInteger<int> { static const bool value = true; };
- template<> struct IsInteger<unsigned int> { static const bool value = true; };
- template<> struct IsInteger<long> { static const bool value = true; };
- template<> struct IsInteger<unsigned long> { static const bool value = true; };
- 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<unsigned char>::value, WTF_IsInteger_unsigned_char_true);
- COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true);
- COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true);
- COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true);
- COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true);
- COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true);
- COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_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);
- COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false);
- COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false);
-
template<typename T> struct HashTraits;
template<bool isInteger, typename T> struct GenericHashTraitsBase;
#include "MainThread.h"
#include "StdLibExtras.h"
+#include "CurrentTime.h"
+#include "Deque.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)
+ FunctionWithContext(MainThreadFunction* function = 0, void* context = 0)
: function(function)
, context(context)
- , syncFlag(syncFlag)
{
}
};
-typedef Vector<FunctionWithContext> FunctionQueue;
+typedef Deque<FunctionWithContext> FunctionQueue;
static bool callbacksPaused; // This global variable is only accessed from main thread.
return staticFunctionQueue;
}
-#if !PLATFORM(WIN)
void initializeMainThread()
{
mainThreadFunctionQueueMutex();
+ initializeMainThreadPlatform();
}
-#endif
+
+// 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that.
+static const double maxRunLoopSuspensionTime = 0.05;
void dispatchFunctionsFromMainThread()
{
if (callbacksPaused)
return;
- FunctionQueue queueCopy;
- {
- MutexLocker locker(mainThreadFunctionQueueMutex());
- queueCopy.swap(functionQueue());
- }
+ double startTime = currentTime();
+
+ FunctionWithContext invocation;
+ while (true) {
+ {
+ MutexLocker locker(mainThreadFunctionQueueMutex());
+ if (!functionQueue().size())
+ break;
+ invocation = functionQueue().first();
+ functionQueue().removeFirst();
+ }
- for (unsigned i = 0; i < queueCopy.size(); ++i) {
- FunctionWithContext& invocation = queueCopy[i];
invocation.function(invocation.context);
- if (invocation.syncFlag)
- invocation.syncFlag->signal();
+
+ // If we are running accumulated functions for too long so UI may become unresponsive, we need to
+ // yield so the user input can be processed. Otherwise user may not be able to even close the window.
+ // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that
+ // allows input events to be processed before we are back here.
+ if (currentTime() - startTime > maxRunLoopSuspensionTime) {
+ scheduleDispatchFunctionsOnMainThread();
+ break;
+ }
}
}
void callOnMainThread(MainThreadFunction* function, void* context)
{
ASSERT(function);
-
+ bool needToSchedule = false;
{
MutexLocker locker(mainThreadFunctionQueueMutex());
+ needToSchedule = functionQueue().size() == 0;
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);
+ if (needToSchedule)
+ scheduleDispatchFunctionsOnMainThread();
}
void setMainThreadCallbacksPaused(bool paused)
typedef void MainThreadFunction(void*);
void callOnMainThread(MainThreadFunction*, void* context);
-void callOnMainThreadAndWait(MainThreadFunction*, void* context);
void setMainThreadCallbacksPaused(bool paused);
void initializeMainThread();
// These functions are internal to the callOnMainThread implementation.
-void dispatchFunctionsFromMainThread();
+void initializeMainThreadPlatform();
void scheduleDispatchFunctionsOnMainThread();
Mutex& mainThreadFunctionQueueMutex();
+void dispatchFunctionsFromMainThread();
} // namespace WTF
#endif
#if COMPILER(MSVC)
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE)
#include <stdlib.h>
-#else
-#include <xmath.h>
#endif
#include <limits>
/*
* Copyright (C) 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
#ifndef MessageQueue_h
#define MessageQueue_h
+#include <limits>
#include <wtf/Assertions.h>
#include <wtf/Deque.h>
#include <wtf/Noncopyable.h>
template<typename DataType>
class MessageQueue : Noncopyable {
public:
- MessageQueue() : m_killed(false) {}
+ MessageQueue() : m_killed(false) { }
void append(const DataType&);
+ bool appendAndCheckEmpty(const DataType&);
void prepend(const DataType&);
bool waitForMessage(DataType&);
- MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
+ template<typename Predicate>
+ MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime);
void kill();
bool tryGetMessage(DataType&);
// The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
bool isEmpty();
+ static double infiniteTime() { return std::numeric_limits<double>::max(); }
+
private:
+ static bool alwaysTruePredicate(DataType&) { return true; }
+
mutable Mutex m_mutex;
ThreadCondition m_condition;
Deque<DataType> m_queue;
m_condition.signal();
}
+ // Returns true if the queue was empty before the item was added.
+ template<typename DataType>
+ inline bool MessageQueue<DataType>::appendAndCheckEmpty(const DataType& message)
+ {
+ MutexLocker lock(m_mutex);
+ bool wasEmpty = m_queue.isEmpty();
+ m_queue.append(message);
+ m_condition.signal();
+ return wasEmpty;
+ }
+
template<typename DataType>
inline void MessageQueue<DataType>::prepend(const DataType& message)
{
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;
+ MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
+ ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
+ return exitReason == MessageQueueMessageReceived;
}
template<typename DataType>
- inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
+ template<typename Predicate>
+ inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime)
{
MutexLocker lock(m_mutex);
bool timedOut = false;
- while (!m_killed && !timedOut && m_queue.isEmpty())
+ DequeConstIterator<DataType> found = m_queue.end();
+ while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
+ ASSERT(!timedOut || absoluteTime != infiniteTime());
+
if (m_killed)
return MessageQueueTerminated;
if (timedOut)
return MessageQueueTimeout;
- ASSERT(!m_queue.isEmpty());
- result = m_queue.first();
- m_queue.removeFirst();
+ ASSERT(found != m_queue.end());
+ result = *found;
+ m_queue.remove(found);
return MessageQueueMessageReceived;
}
MutexLocker lock(m_mutex);
return m_killed;
}
-}
+} // namespace WTF
using WTF::MessageQueue;
// MessageQueueWaitResult enum and all its values.
} // namespace WTF
+using WTF::notFound;
+
#endif // NotFound_h
--- /dev/null
+/*
+ * Copyright (C) 2006, 2007 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 OwnFastMallocPtr_h
+#define OwnFastMallocPtr_h
+
+#include "FastMalloc.h"
+#include "Noncopyable.h"
+
+namespace WTF {
+
+ template<class T> class OwnFastMallocPtr : Noncopyable {
+ public:
+ explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr)
+ {
+ }
+
+ ~OwnFastMallocPtr()
+ {
+ fastFree(m_ptr);
+ }
+
+ T* get() const { return m_ptr; }
+ T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
+
+ private:
+ T* m_ptr;
+ };
+
+} // namespace WTF
+
+using WTF::OwnFastMallocPtr;
+
+#endif // OwnFastMallocPtr_h
/*
- * Copyright (C) 2006, 2007 Apple 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 WTF_OwnPtr_h
#define WTF_OwnPtr_h
+#include "Assertions.h"
+#include "Noncopyable.h"
+#include "OwnPtrCommon.h"
+#include "TypeTraits.h"
#include <algorithm>
#include <memory>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
-
-#if PLATFORM(WIN)
-
-typedef struct HBITMAP__* HBITMAP;
-typedef struct HBRUSH__* HBRUSH;
-typedef struct HFONT__* HFONT;
-typedef struct HPALETTE__* HPALETTE;
-typedef struct HPEN__* HPEN;
-typedef struct HRGN__* HRGN;
-
-#endif
namespace WTF {
// Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type.
- // FIXME: Share a single RemovePointer class template with RetainPtr.
- template <typename T> struct OwnPtrRemovePointer { typedef T type; };
- template <typename T> struct OwnPtrRemovePointer<T*> { typedef T type; };
-
- template <typename T> inline void deleteOwnedPtr(T* ptr)
- {
- typedef char known[sizeof(T) ? 1 : -1];
- if (sizeof(known))
- delete ptr;
- }
-
-#if PLATFORM(WIN)
- void deleteOwnedPtr(HBITMAP);
- void deleteOwnedPtr(HBRUSH);
- void deleteOwnedPtr(HFONT);
- void deleteOwnedPtr(HPALETTE);
- void deleteOwnedPtr(HPEN);
- void deleteOwnedPtr(HRGN);
-#endif
+ template <typename T> class PassOwnPtr;
template <typename T> class OwnPtr : Noncopyable {
public:
- typedef typename OwnPtrRemovePointer<T>::type ValueType;
+ typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { }
+ // See comment in PassOwnPtr.h for why this takes a const reference.
+ template <typename U> OwnPtr(const PassOwnPtr<U>& o);
+
+ // This copy constructor is used implicitly by gcc when it generates
+ // transients for assigning a PassOwnPtr<T> object to a stack-allocated
+ // OwnPtr<T> object. It should never be called explicitly and gcc
+ // should optimize away the constructor when generating code.
+ OwnPtr(const OwnPtr<ValueType>& o);
+
~OwnPtr() { deleteOwnedPtr(m_ptr); }
PtrType get() const { return m_ptr; }
typedef PtrType OwnPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
+ OwnPtr& operator=(const PassOwnPtr<T>&);
+ template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
+
void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
private:
PtrType m_ptr;
};
-
- template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) { a.swap(b); }
+
+ template <typename T> template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
+ : m_ptr(o.release())
+ {
+ }
+
+ template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
+ {
+ T* ptr = m_ptr;
+ m_ptr = o.release();
+ ASSERT(!ptr || m_ptr != ptr);
+ if (ptr)
+ deleteOwnedPtr(ptr);
+ return *this;
+ }
+
+ template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
+ {
+ T* ptr = m_ptr;
+ m_ptr = o.release();
+ ASSERT(!ptr || m_ptr != ptr);
+ if (ptr)
+ deleteOwnedPtr(ptr);
+ return *this;
+ }
+
+ template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
+ {
+ a.swap(b);
+ }
template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
- {
+ {
return a.get() == b;
}
-
+
template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b)
{
return a == b.get();
}
template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
- {
+ {
return a != b.get();
}
-
+
template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
{
return p.get();
--- /dev/null
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
+ *
+ * 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_OwnPtrCommon_h
+#define WTF_OwnPtrCommon_h
+
+#if PLATFORM(WIN)
+typedef struct HBITMAP__* HBITMAP;
+typedef struct HBRUSH__* HBRUSH;
+typedef struct HDC__* HDC;
+typedef struct HFONT__* HFONT;
+typedef struct HPALETTE__* HPALETTE;
+typedef struct HPEN__* HPEN;
+typedef struct HRGN__* HRGN;
+#endif
+
+namespace WTF {
+
+ template <typename T> inline void deleteOwnedPtr(T* ptr)
+ {
+ typedef char known[sizeof(T) ? 1 : -1];
+ if (sizeof(known))
+ delete ptr;
+ }
+
+#if PLATFORM(WIN)
+ void deleteOwnedPtr(HBITMAP);
+ void deleteOwnedPtr(HBRUSH);
+ void deleteOwnedPtr(HDC);
+ void deleteOwnedPtr(HFONT);
+ void deleteOwnedPtr(HPALETTE);
+ void deleteOwnedPtr(HPEN);
+ void deleteOwnedPtr(HRGN);
+#endif
+
+} // namespace WTF
+
+#endif // WTF_OwnPtrCommon_h
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
DeleteObject(ptr);
}
+void deleteOwnedPtr(HDC ptr)
+{
+ if (ptr)
+ DeleteDC(ptr);
+}
+
void deleteOwnedPtr(HFONT ptr)
{
if (ptr)
--- /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 WTF_PassOwnPtr_h
+#define WTF_PassOwnPtr_h
+
+#include "Assertions.h"
+#include "OwnPtrCommon.h"
+#include "TypeTraits.h"
+
+namespace WTF {
+
+ // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type.
+
+ template <typename T> class OwnPtr;
+
+ template <typename T> class PassOwnPtr {
+ public:
+ typedef typename RemovePointer<T>::Type ValueType;
+ typedef ValueType* PtrType;
+
+ PassOwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+ // It somewhat breaks the type system to allow transfer of ownership out of
+ // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
+ // temporaries, and we don't really have a need to use real const PassOwnPtrs
+ // anyway.
+ PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.release()) { }
+ template <typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.release()) { }
+
+ ~PassOwnPtr() { deleteOwnedPtr(m_ptr); }
+
+ PtrType get() const { return m_ptr; }
+
+ void clear() { m_ptr = 0; }
+ PtrType release() const { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
+
+ ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+ PtrType 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 PtrType PassOwnPtr::*UnspecifiedBoolType;
+ operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
+
+ PassOwnPtr& operator=(T*);
+ PassOwnPtr& operator=(const PassOwnPtr<T>&);
+ template <typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
+
+ private:
+ mutable PtrType m_ptr;
+ };
+
+ template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(T* optr)
+ {
+ T* ptr = m_ptr;
+ m_ptr = optr;
+ ASSERT(!ptr || m_ptr != ptr);
+ if (ptr)
+ deleteOwnedPtr(ptr);
+ return *this;
+ }
+
+ template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
+ {
+ T* ptr = m_ptr;
+ m_ptr = optr.release();
+ ASSERT(!ptr || m_ptr != ptr);
+ if (ptr)
+ deleteOwnedPtr(ptr);
+ return *this;
+ }
+
+ template <typename T> template <typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
+ {
+ T* ptr = m_ptr;
+ m_ptr = optr.release();
+ ASSERT(!ptr || m_ptr != ptr);
+ if (ptr)
+ deleteOwnedPtr(ptr);
+ return *this;
+ }
+
+ template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
+ {
+ return a.get() == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
+ {
+ return a.get() == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
+ {
+ return a.get() == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
+ {
+ return a.get() == b;
+ }
+
+ template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
+ {
+ return a == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
+ {
+ return a.get() != b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
+ {
+ return a.get() != b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
+ {
+ return a.get() != b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
+ {
+ return a.get() != b;
+ }
+
+ template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
+ {
+ return a != b.get();
+ }
+
+ template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
+ {
+ return PassOwnPtr<T>(static_cast<T*>(p.release()));
+ }
+
+ template <typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p)
+ {
+ return PassOwnPtr<T>(const_cast<T*>(p.release()));
+ }
+
+ template <typename T> inline T* getPtr(const PassOwnPtr<T>& p)
+ {
+ return p.get();
+ }
+
+} // namespace WTF
+
+using WTF::PassOwnPtr;
+using WTF::const_pointer_cast;
+using WTF::static_pointer_cast;
+
+#endif // WTF_PassOwnPtr_h
PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
- ALWAYS_INLINE ~PassRefPtr() { if (T* ptr = m_ptr) ptr->deref(); }
+ ALWAYS_INLINE ~PassRefPtr() { if (UNLIKELY(m_ptr != 0)) m_ptr->deref(); }
template <class U>
PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
/* be used regardless of operating environment */
#ifdef __APPLE__
#define WTF_PLATFORM_DARWIN 1
+#include <AvailabilityMacros.h>
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+#define BUILDING_ON_TIGER 1
+#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+#define BUILDING_ON_LEOPARD 1
+#endif
+#include <Availability.h>
#include <TargetConditionals.h>
#endif
#define WTF_PLATFORM_WIN_OS 1
#endif
-/* PLATFORM(WIN_CE) */
+/* PLATFORM(WINCE) */
/* 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
+#define WTF_PLATFORM_WINCE 1
+#endif
+
+/* PLATFORM(LINUX) */
+/* Operating system level dependencies for Linux-like systems that */
+/* should be used regardless of operating environment */
+#ifdef __linux__
+#define WTF_PLATFORM_LINUX 1
#endif
/* PLATFORM(FREEBSD) */
#endif
/* PLATFORM(IPHONE) */
-#if TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
#define WTF_PLATFORM_IPHONE 1
#endif
/* PLATFORM(IPHONE_SIMULATOR) */
-#if TARGET_IPHONE_SIMULATOR
+#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
#define WTF_PLATFORM_IPHONE 1
#define WTF_PLATFORM_IPHONE_SIMULATOR 1
#else
#if !defined(__ARM_EABI__)
#define WTF_PLATFORM_FORCE_PACK 1
#endif
+#define ARM_ARCH_VERSION 3
+#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
+#undef ARM_ARCH_VERSION
+#define ARM_ARCH_VERSION 4
+#endif
+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
+#undef ARM_ARCH_VERSION
+#define ARM_ARCH_VERSION 5
#endif
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__)
+#undef ARM_ARCH_VERSION
+#define ARM_ARCH_VERSION 6
+#endif
+#if defined(__ARM_ARCH_7A__)
+#undef ARM_ARCH_VERSION
+#define ARM_ARCH_VERSION 7
+#endif
+#endif /* ARM */
+#define PLATFORM_ARM_ARCH(N) (PLATFORM(ARM) && ARM_ARCH_VERSION >= N)
/* PLATFORM(X86) */
#if defined(__i386__) \
/* PLATFORM(X86_64) */
#if defined(__x86_64__) \
- || defined(__ia64__) \
|| defined(_M_X64)
#define WTF_PLATFORM_X86_64 1
#endif
+/* PLATFORM(SH4) */
+#if defined(__SH4__)
+#define WTF_PLATFORM_SH4 1
+#endif
+
/* PLATFORM(SPARC64) */
#if defined(__sparc64__)
#define WTF_PLATFORM_SPARC64 1
#define WTF_PLATFORM_BIG_ENDIAN 1
#endif
-/* PLATFORM(WIN_CE) && PLATFORM(QT)
+/* PLATFORM(WINCE) && 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)
+#if PLATFORM(WINCE) && PLATFORM(QT)
# include <QtGlobal>
# undef WTF_PLATFORM_BIG_ENDIAN
# undef WTF_PLATFORM_MIDDLE_ENDIAN
#endif
#endif
+/* COMPILER(RVCT) */
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define WTF_COMPILER_RVCT 1
+#endif
+
/* COMPILER(GCC) */
-#if defined(__GNUC__)
+/* --gnu option of the RVCT compiler also defines __GNUC__ */
+#if defined(__GNUC__) && !COMPILER(RVCT)
#define WTF_COMPILER_GCC 1
#endif
#define WTF_COMPILER_CYGWIN 1
#endif
-/* COMPILER(RVCT) */
-#if defined(__CC_ARM) || defined(__ARMCC__)
-#define WTF_COMPILER_RVCT 1
-#endif
-
/* COMPILER(WINSCW) */
#if defined(__WINSCW__)
#define WTF_COMPILER_WINSCW 1
#define WTF_USE_PTHREADS 1
#endif
-#define WTF_PLATFORM_CF 1
-#define WTF_USE_PTHREADS 1
+#define DONT_FINALIZE_ON_MAIN_THREAD 1
+#define ENABLE_CONTEXT_MENUS 0
+#define ENABLE_DRAG_SUPPORT 0
#define ENABLE_FTPDIR 1
+#define ENABLE_GEOLOCATION 1
+#define ENABLE_ICONDATABASE 0
+#define ENABLE_INSPECTOR 0
#define ENABLE_JIT 0
#define ENABLE_MAC_JAVA_BRIDGE 0
-#define ENABLE_ICONDATABASE 0
-#define ENABLE_TOUCH_EVENTS 1
-#define ENABLE_IPHONE_PPT 1
-#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_ORIENTATION_EVENTS 1
#define ENABLE_REPAINT_THROTTLING 1
#define ENABLE_RESPECT_EXIF_ORIENTATION 1
+#define HAVE_READLINE 1
+#define HAVE_RUNLOOP_TIMER 0
+#define WTF_PLATFORM_CF 1
+#define WTF_USE_PTHREADS 1
#if PLATFORM(WIN)
#define WTF_USE_WININET 1
#endif
#if PLATFORM(WX)
+#define ENABLE_ASSEMBLER 1
#define WTF_USE_CURL 1
#define WTF_USE_PTHREADS 1
#endif
#define HAVE_ACCESSIBILITY 1
#endif /* !defined(HAVE_ACCESSIBILITY) */
-#if COMPILER(GCC)
-#define HAVE_COMPUTED_GOTO 1
+#if PLATFORM(UNIX) && !PLATFORM(SYMBIAN)
+#define HAVE_SIGNAL_H 1
#endif
#if PLATFORM(DARWIN)
#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 1
#define HAVE_MMAP 1
#define HAVE_MERGESORT 1
#define HAVE_SBRK 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TIMEB_H 1
+
+#define HAVE_MADV_FREE 1
+
#elif PLATFORM(WIN_OS)
#define HAVE_FLOAT_H 1
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE)
#define HAVE_ERRNO_H 0
#else
#define HAVE_SYS_TIMEB_H 1
/* FIXME: is this actually used or do other platforms generate their own config.h? */
#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 1
#define HAVE_MMAP 1
#define HAVE_SBRK 1
#define HAVE_STRINGS_H 1
/* ENABLE macro defaults */
+/* fastMalloc match validation allows for runtime verification that
+ new is matched by delete, fastMalloc is matched by fastFree, etc. */
+#if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION)
+#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0
+#endif
+
#if !defined(ENABLE_ICONDATABASE)
#define ENABLE_ICONDATABASE 1
#endif
#define ENABLE_DASHBOARD_SUPPORT 0
#endif
+#if !defined(ENABLE_CONTEXT_MENUS)
+#define ENABLE_CONTEXT_MENUS 1
+#endif
+
+#if !defined(ENABLE_DRAG_SUPPORT)
+#define ENABLE_DRAG_SUPPORT 1
+#endif
+
+#if !defined(ENABLE_INSPECTOR)
+#define ENABLE_INSPECTOR 1
+#endif
+
#if !defined(ENABLE_MAC_JAVA_BRIDGE)
#define ENABLE_MAC_JAVA_BRIDGE 0
#endif
#define ENABLE_NETSCAPE_PLUGIN_API 1
#endif
-#if !defined(ENABLE_RESPECT_EXIF_ORIENTATION)
-#define ENABLE_RESPECT_EXIF_ORIENTATION 0
+#if !defined(WTF_USE_PLUGIN_HOST_PROCESS)
+#define WTF_USE_PLUGIN_HOST_PROCESS 0
#endif
-#if !defined(ENABLE_TOUCH_EVENTS)
-#define ENABLE_TOUCH_EVENTS 0
+#if !defined(ENABLE_ORIENTATION_EVENTS)
+#define ENABLE_ORIENTATION_EVENTS 0
#endif
-#if !defined(ENABLE_IPHONE_PPT)
-#define ENABLE_IPHONE_PPT 0
+#if !defined(ENABLE_RESPECT_EXIF_ORIENTATION)
+#define ENABLE_RESPECT_EXIF_ORIENTATION 0
#endif
#if !defined(ENABLE_OPCODE_STATS)
#define ENABLE_OPCODE_STATS 0
#endif
-#if !defined(ENABLE_CODEBLOCK_SAMPLING)
+#define ENABLE_SAMPLING_COUNTERS 0
+#define ENABLE_SAMPLING_FLAGS 0
+#define ENABLE_OPCODE_SAMPLING 0
#define ENABLE_CODEBLOCK_SAMPLING 0
+#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING)
+#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING"
#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
+#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS)
+#define ENABLE_SAMPLING_THREAD 1
#endif
#if !defined(ENABLE_GEOLOCATION)
#define ENABLE_TEXT_CARET 1
#endif
-#if !defined(WTF_USE_ALTERNATE_JSIMMEDIATE) && PLATFORM(X86_64) && PLATFORM(MAC)
-#define WTF_USE_ALTERNATE_JSIMMEDIATE 1
+#if !defined(ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL)
+#define ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL 0
+#endif
+
+#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
+#if PLATFORM(X86_64) && PLATFORM(MAC)
+#define WTF_USE_JSVALUE64 1
+#elif PLATFORM(PPC64) || PLATFORM(QT) || (PLATFORM(IPHONE) && PLATFORM_ARM_ARCH(6) && !defined(__llvm__))
+// FIXME: <rdar://problem/7478149> gcc-4.2 compiler bug with USE(JSVALUE32_64) and armv6 target
+#define WTF_USE_JSVALUE32 1
+#else
+#define WTF_USE_JSVALUE32_64 1
#endif
+#endif // !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
#if !defined(ENABLE_REPAINT_THROTTLING)
#define ENABLE_REPAINT_THROTTLING 0
#endif
#if !defined(ENABLE_JIT)
-/* x86-64 support is under development. */
+/* The JIT is tested & working on x86_64 Mac */
#if PLATFORM(X86_64) && PLATFORM(MAC)
- #define ENABLE_JIT 0
- #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+ #define ENABLE_JIT 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
+#elif PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
+ /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */
+ #define ENABLE_JIT 0
+ #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0
/* 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.
+#ifndef ENABLE_JIT_OPTIMIZE_CALL
+#define ENABLE_JIT_OPTIMIZE_CALL 1
+#endif
+#ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL
+#define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1
+#endif
+#ifndef ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS
+#define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
+#endif
+#ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS
+#define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1
+#endif
+#endif
+
+#if PLATFORM(X86) && COMPILER(MSVC)
+#define JSC_HOST_CALL __fastcall
+#elif PLATFORM(X86) && COMPILER(GCC)
+#define JSC_HOST_CALL __attribute__ ((fastcall))
+#else
+#define JSC_HOST_CALL
+#endif
+
+#if COMPILER(GCC) && !ENABLE(JIT)
+#define HAVE_COMPUTED_GOTO 1
#endif
+
+#if ENABLE(JIT) && defined(COVERAGE)
+ #define WTF_USE_INTERPRETER 0
+#else
+ #define WTF_USE_INTERPRETER 1
#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
+/* Yet Another Regex Runtime. */
+/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
+#if (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(MAC)) \
+ || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86_64) && PLATFORM(MAC)) \
+ /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \
+ || (!defined(ENABLE_YARR_JIT) && PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE) && 0) \
+ || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(WIN))
+#define ENABLE_YARR 1
+#define ENABLE_YARR_JIT 1
+#endif
+/* Sanity Check */
+#if ENABLE(YARR_JIT) && !ENABLE(YARR)
+#error "YARR_JIT requires YARR"
#endif
-#if ENABLE(JIT) || ENABLE(WREC)
+#if ENABLE(JIT) || ENABLE(YARR_JIT)
#define ENABLE_ASSEMBLER 1
#endif
+/* Setting this flag prevents the assembler from using RWX memory; this may improve
+ security but currectly comes at a significant performance cost. */
+#if PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
+#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1
+#else
+#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0
+#endif
#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS)
#define ENABLE_PAN_SCROLLING 1
#define WTF_USE_FONT_FAST_PATH 1
#endif
+/* Accelerated compositing */
+#if PLATFORM(MAC)
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#define WTF_USE_ACCELERATED_COMPOSITING 1
+#endif
+#endif
+
+#define WTF_USE_ACCELERATED_COMPOSITING 1
+
#endif /* WTF_Platform_h */
/*
- * Copyright (c) 2009, Google 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
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);}
+ void set(T* ptr)
+ {
+ ASSERT(!(reinterpret_cast<intptr_t>(ptr) & 3));
+ m_ptrAndFlags = reinterpret_cast<intptr_t>(ptr) | (m_ptrAndFlags & 3);
+#ifndef NDEBUG
+ m_leaksPtr = ptr;
+#endif
+ }
+
private:
intptr_t m_ptrAndFlags;
+#ifndef NDEBUG
+ void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.
+#endif
};
} // namespace WTF
}
protected:
- RefCountedBase(int initialRefCount)
- : m_refCount(initialRefCount)
+ RefCountedBase()
+ : m_refCount(1)
#ifndef NDEBUG
, m_deletionHasBegun(false)
#endif
{
}
- ~RefCountedBase() {}
+ ~RefCountedBase()
+ {
+ }
// Returns whether the pointer should be freed or not.
bool derefBase()
return false;
}
-protected:
+ // Helper for generating JIT code. Please do not use for non-JIT purposes.
+ int* addressOfCount()
+ {
+ return &m_refCount;
+ }
+
+#ifndef NDEBUG
+ bool deletionHasBegun() const
+ {
+ return m_deletionHasBegun;
+ }
+#endif
+
+private:
+ template<class T>
+ friend class CrossThreadRefCounted;
+
int m_refCount;
#ifndef NDEBUG
bool m_deletionHasBegun;
template<class T> class RefCounted : public RefCountedBase {
public:
- RefCounted(int initialRefCount = 1)
- : RefCountedBase(initialRefCount)
- {
- }
-
void deref()
{
if (derefBase())
}
protected:
- ~RefCounted() {}
+ ~RefCounted()
+ {
+ }
};
} // namespace WTF
#include <algorithm>
#include "AlwaysInline.h"
+#include "FastAllocBase.h"
namespace WTF {
enum HashTableDeletedValueType { HashTableDeletedValue };
- template <typename T> class RefPtr {
+ template <typename T> class RefPtr : public FastAllocBase {
public:
RefPtr() : m_ptr(0) { }
RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); }
#ifndef RetainPtr_h
#define RetainPtr_h
+#include "TypeTraits.h"
#include <algorithm>
#include <CoreFoundation/CoreFoundation.h>
namespace WTF {
- template <typename T> struct RemovePointer {
- typedef T type;
- };
-
- template <typename T> struct RemovePointer<T*> {
- typedef T type;
- };
-
// Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
// so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
template <typename T> class RetainPtr {
public:
- typedef typename RemovePointer<T>::type ValueType;
+ typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
RetainPtr() : m_ptr(0) {}
--- /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 WTF {
+
+ // An iterator for SegmentedVector. It supports only the pre ++ operator
+ template <typename T, size_t SegmentSize> class SegmentedVector;
+ template <typename T, size_t SegmentSize> class SegmentedVectorIterator {
+ private:
+ friend class SegmentedVector<T, SegmentSize>;
+ public:
+ typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
+
+ ~SegmentedVectorIterator() { }
+
+ T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); }
+ T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); }
+
+ // Only prefix ++ operator supported
+ Iterator& operator++()
+ {
+ ASSERT(m_index != SegmentSize);
+ ++m_index;
+ if (m_index >= m_vector.m_segments.at(m_segment)->size()) {
+ if (m_segment + 1 < m_vector.m_segments.size()) {
+ ASSERT(m_vector.m_segments.at(m_segment)->size() > 0);
+ ++m_segment;
+ m_index = 0;
+ } else {
+ // Points to the "end" symbol
+ m_segment = 0;
+ m_index = SegmentSize;
+ }
+ }
+ return *this;
+ }
+
+ bool operator==(const Iterator& other) const
+ {
+ return (m_index == other.m_index && m_segment = other.m_segment && &m_vector == &other.m_vector);
+ }
+
+ bool operator!=(const Iterator& other) const
+ {
+ return (m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector);
+ }
+
+ SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other)
+ {
+ m_vector = other.m_vector;
+ m_segment = other.m_segment;
+ m_index = other.m_index;
+ return *this;
+ }
+
+ private:
+ SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index)
+ : m_vector(vector)
+ , m_segment(segment)
+ , m_index(index)
+ {
+ }
+
+ SegmentedVector<T, SegmentSize>& m_vector;
+ size_t m_segment;
+ size_t m_index;
+ };
+
+ // 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 {
+ friend class SegmentedVectorIterator<T, SegmentSize>;
+ public:
+ typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
+
+ 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);
+ }
+
+ T& alloc()
+ {
+ append<T>(T());
+ return last();
+ }
+
+ 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;
+ }
+
+ Iterator begin()
+ {
+ return Iterator(*this, 0, m_size ? 0 : SegmentSize);
+ }
+
+ Iterator end()
+ {
+ return Iterator(*this, 0, SegmentSize);
+ }
+
+ 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 WTF
+
+#endif // SegmentedVector_h
static type& name = *new type arguments
#endif
+// OBJECT_OFFSETOF: 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 OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
+
namespace WTF {
/*
* C++'s idea of a reinterpret_cast lacks sufficient cojones.
*/
template<typename TO, typename FROM>
- TO bitwise_cast(FROM in)
+ TO bitwise_cast(FROM from)
{
- COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal);
+ COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal);
union {
FROM from;
TO to;
} u;
- u.from = in;
+ u.from = from;
return u.to;
}
#include <stdarg.h>
#include <stdio.h>
+#if HAVE(STRINGS_H)
+#include <strings.h>
+#endif
+
#if COMPILER(MSVC)
inline int snprintf(char* buffer, size_t count, const char* format, ...)
return result;
}
-#if COMPILER(MSVC7) || PLATFORM(WIN_CE)
+#if COMPILER(MSVC7) || PLATFORM(WINCE)
inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
{
#endif
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE)
inline int strnicmp(const char* string1, const char* string2, size_t count)
{
#endif
#include <string.h>
-
#include "Assertions.h"
// Single-level array
#ifdef WTF_CHANGES
template<class Visitor, class MemoryReader>
- void visit(const Visitor& visitor, const MemoryReader& reader)
+ void visitValues(Visitor& visitor, const MemoryReader& reader)
{
for (int i = 0; i < ROOT_LENGTH; i++) {
if (!root_[i])
;
}
}
+
+ template<class Visitor, class MemoryReader>
+ void visitAllocations(Visitor& visitor, const MemoryReader&) {
+ for (int i = 0; i < ROOT_LENGTH; i++) {
+ if (root_[i])
+ visitor.visit(root_[i], sizeof(Leaf));
+ }
+ }
#endif
};
#ifdef WTF_CHANGES
template<class Visitor, class MemoryReader>
- void visit(const Visitor& visitor, const MemoryReader& reader) {
+ void visitValues(Visitor& visitor, const MemoryReader& reader) {
Node* root = reader(root_);
for (int i = 0; i < INTERIOR_LENGTH; i++) {
if (!root->ptrs[i])
}
}
}
+
+ template<class Visitor, class MemoryReader>
+ void visitAllocations(Visitor& visitor, const MemoryReader& reader) {
+ visitor.visit(root_, sizeof(Node));
+
+ Node* root = reader(root_);
+ for (int i = 0; i < INTERIOR_LENGTH; i++) {
+ if (!root->ptrs[i])
+ continue;
+
+ visitor.visit(root->ptrs[i], sizeof(Node));
+ Node* n = reader(root->ptrs[i]);
+ for (int j = 0; j < INTERIOR_LENGTH; j++) {
+ if (!n->ptrs[j])
+ continue;
+
+ visitor.visit(n->ptrs[j], sizeof(Leaf));
+ }
+ }
+ }
#endif
};
// Author: Sanjay Ghemawat
#include "config.h"
+#include "TCSystemAlloc.h"
+
+#include <algorithm>
+#include <fcntl.h>
+#include "Assertions.h"
+#include "TCSpinLock.h"
+#include "UnusedParam.h"
+
#if HAVE(STDINT_H)
#include <stdint.h>
#elif HAVE(INTTYPES_H)
#else
#include <sys/types.h>
#endif
+
#if PLATFORM(WIN_OS)
#include "windows.h"
#else
#include <unistd.h>
#include <sys/mman.h>
#endif
-#include <fcntl.h>
-#include "Assertions.h"
-#include "TCSystemAlloc.h"
-#include "TCSpinLock.h"
-#include "UnusedParam.h"
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
+using namespace std;
+
// Structure for discovering alignment
union MemoryAligner {
void* p;
return NULL;
}
+#if HAVE(MADV_FREE_REUSE)
+
+void TCMalloc_SystemRelease(void* start, size_t length)
+{
+ while (madvise(start, length, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+}
+
+#elif HAVE(MADV_FREE) || HAVE(MADV_DONTNEED)
+
void TCMalloc_SystemRelease(void* start, size_t length)
{
-#if HAVE(MADV_FREE) || HAVE(MADV_DONTNEED)
+ // MADV_FREE clears the modified bit on pages, which allows
+ // them to be discarded immediately.
#if HAVE(MADV_FREE)
- const int advice = MADV_FREE;
+ const int advice = MADV_FREE;
#else
- const int advice = MADV_DONTNEED;
+ const int advice = MADV_DONTNEED;
#endif
if (FLAGS_malloc_devmem_start) {
// It's not safe to use MADV_DONTNEED if we've been mapping
errno == EAGAIN) {
// NOP
}
- return;
}
-#endif
+}
-#if HAVE(MMAP)
+#elif HAVE(MMAP)
+
+void TCMalloc_SystemRelease(void* start, size_t length)
+{
void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
// If the mmap failed then that's ok, we just won't return the memory to the system.
ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
- return;
-#endif
+}
+
+#elif HAVE(VIRTUALALLOC)
+
+void TCMalloc_SystemRelease(void* start, size_t length)
+{
+ if (VirtualFree(start, length, MEM_DECOMMIT))
+ return;
+
+ // The decommit may fail if the memory region consists of allocations
+ // from more than one call to VirtualAlloc. In this case, fall back to
+ // using VirtualQuery to retrieve the allocation boundaries and decommit
+ // them each individually.
+
+ char* ptr = static_cast<char*>(start);
+ char* end = ptr + length;
+ MEMORY_BASIC_INFORMATION info;
+ while (ptr < end) {
+ size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
+ ASSERT_UNUSED(resultSize, resultSize == sizeof(info));
+
+ size_t decommitSize = min<size_t>(info.RegionSize, end - ptr);
+ BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
+ ASSERT_UNUSED(success, success);
+ ptr += decommitSize;
+ }
+}
+
+#else
+
+// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease
+// declared in TCSystemAlloc.h
-#if !HAVE(MADV_DONTNEED) && !HAVE(MMAP)
- UNUSED_PARAM(start);
- UNUSED_PARAM(length);
#endif
+
+#if HAVE(MADV_FREE_REUSE)
+
+void TCMalloc_SystemCommit(void* start, size_t length)
+{
+ while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
}
-#if HAVE(VIRTUALALLOC)
-void TCMalloc_SystemCommit(void*, size_t)
+#elif HAVE(VIRTUALALLOC)
+
+void TCMalloc_SystemCommit(void* start, size_t length)
{
+ if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
+ return;
+
+ // The commit may fail if the memory region consists of allocations
+ // from more than one call to VirtualAlloc. In this case, fall back to
+ // using VirtualQuery to retrieve the allocation boundaries and commit them
+ // each individually.
+
+ char* ptr = static_cast<char*>(start);
+ char* end = ptr + length;
+ MEMORY_BASIC_INFORMATION info;
+ while (ptr < end) {
+ size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
+ ASSERT_UNUSED(resultSize, resultSize == sizeof(info));
+
+ size_t commitSize = min<size_t>(info.RegionSize, end - ptr);
+ void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, PAGE_READWRITE);
+ ASSERT_UNUSED(newAddress, newAddress == ptr);
+ ptr += commitSize;
+ }
}
+
+#else
+
+// Platforms that don't need to explicitly commit memory use an empty inline version of TCMalloc_SystemCommit
+// declared in TCSystemAlloc.h
+
#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
+
+#if !HAVE(MADV_FREE_REUSE) && !HAVE(MADV_DONTNEED) && !HAVE(MMAP) && !HAVE(VIRTUALALLOC)
+inline void TCMalloc_SystemRelease(void*, size_t) { }
+#endif
+
+#if !HAVE(VIRTUALALLOC) && !HAVE(MADV_FREE_REUSE)
inline void TCMalloc_SystemCommit(void*, size_t) { }
#endif
#if USE(PTHREADS)
#include <pthread.h>
+#elif PLATFORM(QT)
+#include <QThreadStorage>
#elif PLATFORM(WIN_OS)
#include <windows.h>
#endif
namespace WTF {
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && 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();
~ThreadSpecific();
private:
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS)
friend void ThreadSpecificThreadExit();
#endif
void set(T*);
void static destroy(void* ptr);
-#if USE(PTHREADS) || PLATFORM(WIN_OS)
+#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(WIN_OS)
struct Data : Noncopyable {
Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
#if USE(PTHREADS)
pthread_key_t m_key;
+#elif PLATFORM(QT)
+ QThreadStorage<Data*> m_key;
#elif PLATFORM(WIN_OS)
int m_index;
#endif
pthread_setspecific(m_key, new Data(ptr, this));
}
+#elif PLATFORM(QT)
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+{
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+ Data* data = static_cast<Data*>(m_key.localData());
+ if (data)
+ data->destructor(data);
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+ Data* data = static_cast<Data*>(m_key.localData());
+ 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;
+ m_key.setLocalData(data);
+}
+
#elif PLATFORM(WIN_OS)
// The maximum number of TLS keys that can be created. For simplification, we assume that:
// 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];
+long& tlsKeyCount();
+DWORD* tlsKeys();
template<typename T>
inline ThreadSpecific<T>::ThreadSpecific()
if (tls_key == TLS_OUT_OF_INDEXES)
CRASH();
- m_index = InterlockedIncrement(&g_tls_key_count) - 1;
+ m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
if (m_index >= kMaxTlsKeySize)
CRASH();
- g_tls_keys[m_index] = tls_key;
+ tlsKeys()[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]);
+ TlsFree(tlsKeys()[m_index]);
}
template<typename T>
inline T* ThreadSpecific<T>::get()
{
- Data* data = static_cast<Data*>(TlsGetValue(g_tls_keys[m_index]));
+ Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
return data ? data->value : 0;
}
ASSERT(!get());
Data* data = new Data(ptr, this);
data->destructor = &ThreadSpecific<T>::destroy;
- TlsSetValue(g_tls_keys[m_index], data);
+ TlsSetValue(tlsKeys()[m_index], data);
}
#else
#if USE(PTHREADS)
pthread_setspecific(data->owner->m_key, 0);
+#elif PLATFORM(QT)
+ data->owner->m_key.setLocalData(0);
#elif PLATFORM(WIN_OS)
- TlsSetValue(g_tls_keys[data->owner->m_index], 0);
+ TlsSetValue(tlsKeys()[data->owner->m_index], 0);
#else
#error ThreadSpecific is not implemented for this platform.
#endif
namespace WTF {
-long g_tls_key_count = 0;
-DWORD g_tls_keys[kMaxTlsKeySize];
+long& tlsKeyCount()
+{
+ static long count;
+ return count;
+}
+
+DWORD* tlsKeys()
+{
+ static DWORD keys[kMaxTlsKeySize];
+ return keys;
+}
void ThreadSpecificThreadExit()
{
- for (long i = 0; i < g_tls_key_count; i++) {
+ for (long i = 0; i < tlsKeyCount(); 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]));
+ ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i]));
if (data)
data->destructor(data);
}
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
#include "config.h"
#include "Threading.h"
+#include <string.h>
+
namespace WTF {
struct NewThreadContext {
- NewThreadContext(ThreadFunction entryPoint, void* data)
+ NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
: entryPoint(entryPoint)
, data(data)
- { }
+ , name(name)
+ {
+ }
ThreadFunction entryPoint;
void* data;
+ const char* name;
Mutex creationMutex;
};
{
NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
+ setThreadNameInternal(context->name);
+
// Block until our creating thread has completed any extra setup work
{
MutexLocker locker(context->creationMutex);
ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
{
- NewThreadContext* context = new NewThreadContext(entryPoint, data);
+ // 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.
+#if !LOG_DISABLED
+ if (strlen(name) > 31)
+ LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name);
+#endif
+
+ NewThreadContext* context = new NewThreadContext(entryPoint, data, name);
// Prevent the thread body from executing until we've established the thread identifier
MutexLocker locker(context->creationMutex);
#ifndef Threading_h
#define Threading_h
-#include <wtf/Platform.h>
-
-#if PLATFORM(WIN_CE)
+#if PLATFORM(WINCE)
#include <windows.h>
#endif
#include <wtf/Locker.h>
#include <wtf/Noncopyable.h>
-#if PLATFORM(WIN_OS) && !PLATFORM(WIN_CE)
+#if PLATFORM(WIN_OS) && !PLATFORM(WINCE)
#include <windows.h>
#elif PLATFORM(DARWIN)
#include <libkern/OSAtomic.h>
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
typedef uint32_t ThreadIdentifier;
typedef void* (*ThreadFunction)(void* argument);
-// Returns 0 if thread creation failed
+// Returns 0 if thread creation failed.
+// The thread name must be a literal since on some platforms it's passed in to the thread.
ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
+
+// Internal platform-specific createThread implementation.
ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
+// Called in the thread during initialization.
+// Helpful for platforms where the thread name must be set from within the thread.
+void setThreadNameInternal(const char* threadName);
+
ThreadIdentifier currentThread();
bool isMainThread();
int waitForThreadCompletion(ThreadIdentifier, void**);
#if USE(PTHREADS)
typedef pthread_mutex_t PlatformMutex;
+typedef pthread_rwlock_t PlatformReadWriteLock;
typedef pthread_cond_t PlatformCondition;
#elif PLATFORM(GTK)
typedef GOwnPtr<GMutex> PlatformMutex;
+typedef void* PlatformReadWriteLock; // FIXME: Implement.
typedef GOwnPtr<GCond> PlatformCondition;
#elif PLATFORM(QT)
typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
+typedef void* PlatformReadWriteLock; // FIXME: Implement.
typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
#elif PLATFORM(WIN_OS)
struct PlatformMutex {
CRITICAL_SECTION m_internalMutex;
size_t m_recursionCount;
};
+typedef void* PlatformReadWriteLock; // FIXME: Implement.
struct PlatformCondition {
size_t m_waitersGone;
size_t m_waitersBlocked;
};
#else
typedef void* PlatformMutex;
+typedef void* PlatformReadWriteLock;
typedef void* PlatformCondition;
#endif
typedef Locker<Mutex> MutexLocker;
+class ReadWriteLock : Noncopyable {
+public:
+ ReadWriteLock();
+ ~ReadWriteLock();
+
+ void readLock();
+ bool tryReadLock();
+
+ void writeLock();
+ bool tryWriteLock();
+
+ void unlock();
+
+private:
+ PlatformReadWriteLock m_readWriteLock;
+};
+
class ThreadCondition : Noncopyable {
public:
ThreadCondition();
#if PLATFORM(WIN_OS)
#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
-#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WIN_CE)
+#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WINCE)
inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); }
inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
#else
#endif
-template<class T> class ThreadSafeShared : Noncopyable {
+class ThreadSafeSharedBase : Noncopyable {
public:
- ThreadSafeShared(int initialRefCount = 1)
+ ThreadSafeSharedBase(int initialRefCount = 1)
: m_refCount(initialRefCount)
{
}
#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;
return static_cast<int const volatile &>(m_refCount);
}
+protected:
+ // Returns whether the pointer should be freed or not.
+ bool derefBase()
+ {
+#if USE(LOCKFREE_THREADSAFESHARED)
+ if (atomicDecrement(&m_refCount) <= 0)
+ return true;
+#else
+ int refCount;
+ {
+ MutexLocker locker(m_mutex);
+ --m_refCount;
+ refCount = m_refCount;
+ }
+ if (refCount <= 0)
+ return true;
+#endif
+ return false;
+ }
+
private:
+ template<class T>
+ friend class CrossThreadRefCounted;
+
int m_refCount;
#if !USE(LOCKFREE_THREADSAFESHARED)
mutable Mutex m_mutex;
#endif
};
+template<class T> class ThreadSafeShared : public ThreadSafeSharedBase {
+public:
+ ThreadSafeShared(int initialRefCount = 1)
+ : ThreadSafeSharedBase(initialRefCount)
+ {
+ }
+
+ void deref()
+ {
+ if (derefBase())
+ delete static_cast<T*>(this);
+ }
+};
+
// 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();
+++ /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)
namespace WTF {
void initializeThreading() { }
-ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; }
+ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); }
+void setThreadNameInternal(const char*) { }
int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
void detachThread(ThreadIdentifier) { }
-ThreadIdentifier currentThread() { return 0; }
+ThreadIdentifier currentThread() { return ThreadIdentifier(); }
bool isMainThread() { return true; }
Mutex::Mutex() { }
ThreadCondition::ThreadCondition() { }
ThreadCondition::~ThreadCondition() { }
-void ThreadCondition::wait(Mutex& mutex) { }
-bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) { return false; }
+void ThreadCondition::wait(Mutex&) { }
+bool ThreadCondition::timedWait(Mutex&, double) { return false; }
void ThreadCondition::signal() { }
void ThreadCondition::broadcast() { }
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
*
* Redistribution and use in source and binary forms, with or without
* (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 "StdLibExtras.h"
+#include "UnusedParam.h"
#include <errno.h>
#include <limits.h>
#include <sys/time.h>
+#if PLATFORM(ANDROID)
+#include "jni_utility.h"
+#endif
+
namespace WTF {
typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
threadMapMutex();
initializeRandomNumberGenerator();
mainThreadIdentifier = currentThread();
- initializeMainNSThread();
initializeMainThread();
}
}
static ThreadIdentifier identifierCount = 1;
threadMap().add(identifierCount, pthreadHandle);
-
+
return identifierCount++;
}
static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
{
MutexLocker locker(threadMapMutex());
-
+
return threadMap().get(id);
}
MutexLocker locker(threadMapMutex());
ASSERT(threadMap().contains(id));
-
+
threadMap().remove(id);
}
+#if PLATFORM(ANDROID)
+// On the Android platform, threads must be registered with the VM before they run.
+struct ThreadData {
+ ThreadFunction entryPoint;
+ void* arg;
+};
+
+static void* runThreadWithRegistration(void* arg)
+{
+ ThreadData* data = static_cast<ThreadData*>(arg);
+ JavaVM* vm = JSC::Bindings::getJavaVM();
+ JNIEnv* env;
+ void* ret = 0;
+ if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
+ ret = data->entryPoint(data->arg);
+ vm->DetachCurrentThread();
+ }
+ delete data;
+ return ret;
+}
+
+ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
+{
+ pthread_t threadHandle;
+ ThreadData* threadData = new ThreadData();
+ threadData->entryPoint = entryPoint;
+ threadData->arg = data;
+
+ if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
+ LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
+ return 0;
+ }
+ return establishIdentifierForPthreadHandle(threadHandle);
+}
+#else
ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
{
pthread_t threadHandle;
- if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
+ if (pthread_create(&threadHandle, 0, entryPoint, data)) {
LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
return 0;
}
return establishIdentifierForPthreadHandle(threadHandle);
}
+#endif
+
+void setThreadNameInternal(const char* threadName)
+{
+#if HAVE(PTHREAD_SETNAME_NP)
+ pthread_setname_np(threadName);
+#else
+ UNUSED_PARAM(threadName);
+#endif
+}
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);
}
void Mutex::lock()
{
- if (pthread_mutex_lock(&m_mutex) != 0)
- ASSERT(false);
+ int result = pthread_mutex_lock(&m_mutex);
+ ASSERT_UNUSED(result, !result);
}
-
+
bool Mutex::tryLock()
{
int result = pthread_mutex_trylock(&m_mutex);
-
+
if (result == 0)
return true;
- else if (result == EBUSY)
+ if (result == EBUSY)
return false;
- ASSERT(false);
+ ASSERT_NOT_REACHED();
return false;
}
void Mutex::unlock()
{
- if (pthread_mutex_unlock(&m_mutex) != 0)
- ASSERT(false);
+ int result = pthread_mutex_unlock(&m_mutex);
+ ASSERT_UNUSED(result, !result);
+}
+
+
+ReadWriteLock::ReadWriteLock()
+{
+ pthread_rwlock_init(&m_readWriteLock, NULL);
+}
+
+ReadWriteLock::~ReadWriteLock()
+{
+ pthread_rwlock_destroy(&m_readWriteLock);
+}
+
+void ReadWriteLock::readLock()
+{
+ int result = pthread_rwlock_rdlock(&m_readWriteLock);
+ ASSERT_UNUSED(result, !result);
+}
+
+bool ReadWriteLock::tryReadLock()
+{
+ int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
+
+ if (result == 0)
+ return true;
+ if (result == EBUSY || result == EAGAIN)
+ return false;
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void ReadWriteLock::writeLock()
+{
+ int result = pthread_rwlock_wrlock(&m_readWriteLock);
+ ASSERT_UNUSED(result, !result);
+}
+
+bool ReadWriteLock::tryWriteLock()
+{
+ int result = pthread_rwlock_trywrlock(&m_readWriteLock);
+
+ if (result == 0)
+ return true;
+ if (result == EBUSY || result == EAGAIN)
+ return false;
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void ReadWriteLock::unlock()
+{
+ int result = pthread_rwlock_unlock(&m_readWriteLock);
+ ASSERT_UNUSED(result, !result);
}
ThreadCondition::ThreadCondition()
void ThreadCondition::wait(Mutex& mutex)
{
- if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
- ASSERT(false);
+ int result = pthread_cond_wait(&m_condition, &mutex.impl());
+ ASSERT_UNUSED(result, !result);
}
bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
void ThreadCondition::signal()
{
- if (pthread_cond_signal(&m_condition) != 0)
- ASSERT(false);
+ int result = pthread_cond_signal(&m_condition);
+ ASSERT_UNUSED(result, !result);
}
void ThreadCondition::broadcast()
{
- if (pthread_cond_broadcast(&m_condition) != 0)
- ASSERT(false);
+ int result = pthread_cond_broadcast(&m_condition);
+ ASSERT_UNUSED(result, !result);
}
-
+
} // 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
namespace WTF {
-// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadName all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
+// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
} THREADNAME_INFO;
#pragma pack(pop)
-static void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+void setThreadNameInternal(const char* 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.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try {
initializeRandomNumberGenerator();
initializeMainThread();
mainThreadIdentifier = currentThread();
- setThreadName(mainThreadIdentifier, "Main Thread");
+ setThreadNameInternal("Main Thread");
}
}
return 0;
}
- if (threadName)
- setThreadName(threadIdentifier, threadName);
-
threadID = static_cast<ThreadIdentifier>(threadIdentifier);
storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
void detachThread(ThreadIdentifier threadID)
{
ASSERT(threadID);
-
+
HANDLE threadHandle = threadHandleForIdentifier(threadID);
if (threadHandle)
CloseHandle(threadHandle);
if (absoluteTime < currentTime)
return false;
- double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
- if (intervalMilliseconds >= INT_MAX)
- intervalMilliseconds = INT_MAX;
+ // Time is too far in the future (and would overflow unsigned long) - wait forever.
+ if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
+ wait(mutex);
+ return true;
+ }
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
}
--- /dev/null
+ /*
+ * Copyright (C) 2006, 2007, 2008 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.
+ *
+ */
+
+#include "config.h"
+#include "TypeTraits.h"
+
+#include "Assertions.h"
+
+namespace WTF {
+
+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<unsigned char>::value, WTF_IsInteger_unsigned_char_true);
+COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true);
+COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true);
+COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true);
+COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true);
+COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true);
+COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_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);
+COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false);
+COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false);
+
+COMPILE_ASSERT(IsPod<bool>::value, WTF_IsPod_bool_true);
+COMPILE_ASSERT(IsPod<char>::value, WTF_IsPod_char_true);
+COMPILE_ASSERT(IsPod<signed char>::value, WTF_IsPod_signed_char_true);
+COMPILE_ASSERT(IsPod<unsigned char>::value, WTF_IsPod_unsigned_char_true);
+COMPILE_ASSERT(IsPod<short>::value, WTF_IsPod_short_true);
+COMPILE_ASSERT(IsPod<unsigned short>::value, WTF_IsPod_unsigned_short_true);
+COMPILE_ASSERT(IsPod<int>::value, WTF_IsPod_int_true);
+COMPILE_ASSERT(IsPod<unsigned int>::value, WTF_IsPod_unsigned_int_true);
+COMPILE_ASSERT(IsPod<long>::value, WTF_IsPod_long_true);
+COMPILE_ASSERT(IsPod<unsigned long>::value, WTF_IsPod_unsigned_long_true);
+COMPILE_ASSERT(IsPod<long long>::value, WTF_IsPod_long_long_true);
+COMPILE_ASSERT(IsPod<unsigned long long>::value, WTF_IsPod_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+COMPILE_ASSERT(IsPod<wchar_t>::value, WTF_IsPod_wchar_t_true);
+#endif
+COMPILE_ASSERT(IsPod<char*>::value, WTF_IsPod_char_pointer_true);
+COMPILE_ASSERT(IsPod<const char*>::value, WTF_IsPod_const_char_pointer_true);
+COMPILE_ASSERT(IsPod<volatile char*>::value, WTF_IsPod_volatile_char_pointer_true);
+COMPILE_ASSERT(IsPod<double>::value, WTF_IsPod_double_true);
+COMPILE_ASSERT(IsPod<long double>::value, WTF_IsPod_long_double_true);
+COMPILE_ASSERT(IsPod<float>::value, WTF_IsPod_float_true);
+COMPILE_ASSERT(!IsPod<IsPod<bool> >::value, WTF_IsPod_struct_false);
+
+enum IsConvertibleToIntegerCheck { };
+COMPILE_ASSERT(IsConvertibleToInteger<IsConvertibleToIntegerCheck>::value, WTF_IsConvertibleToInteger_enum_true);
+COMPILE_ASSERT(IsConvertibleToInteger<bool>::value, WTF_IsConvertibleToInteger_bool_true);
+COMPILE_ASSERT(IsConvertibleToInteger<char>::value, WTF_IsConvertibleToInteger_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<signed char>::value, WTF_IsConvertibleToInteger_signed_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned char>::value, WTF_IsConvertibleToInteger_unsigned_char_true);
+COMPILE_ASSERT(IsConvertibleToInteger<short>::value, WTF_IsConvertibleToInteger_short_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned short>::value, WTF_IsConvertibleToInteger_unsigned_short_true);
+COMPILE_ASSERT(IsConvertibleToInteger<int>::value, WTF_IsConvertibleToInteger_int_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned int>::value, WTF_IsConvertibleToInteger_unsigned_int_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long>::value, WTF_IsConvertibleToInteger_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned long>::value, WTF_IsConvertibleToInteger_unsigned_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long long>::value, WTF_IsConvertibleToInteger_long_long_true);
+COMPILE_ASSERT(IsConvertibleToInteger<unsigned long long>::value, WTF_IsConvertibleToInteger_unsigned_long_long_true);
+#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
+COMPILE_ASSERT(IsConvertibleToInteger<wchar_t>::value, WTF_IsConvertibleToInteger_wchar_t_true);
+#endif
+COMPILE_ASSERT(IsConvertibleToInteger<double>::value, WTF_IsConvertibleToInteger_double_true);
+COMPILE_ASSERT(IsConvertibleToInteger<long double>::value, WTF_IsConvertibleToInteger_long_double_true);
+COMPILE_ASSERT(IsConvertibleToInteger<float>::value, WTF_IsConvertibleToInteger_float_true);
+COMPILE_ASSERT(!IsConvertibleToInteger<char*>::value, WTF_IsConvertibleToInteger_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<const char*>::value, WTF_IsConvertibleToInteger_const_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<volatile char*>::value, WTF_IsConvertibleToInteger_volatile_char_pointer_false);
+COMPILE_ASSERT(!IsConvertibleToInteger<IsConvertibleToInteger<bool> >::value, WTF_IsConvertibleToInteger_struct_false);
+
+COMPILE_ASSERT((IsSameType<bool, bool>::value), WTF_IsSameType_bool_true);
+COMPILE_ASSERT((IsSameType<int*, int*>::value), WTF_IsSameType_int_pointer_true);
+COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_false);
+COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false);
+COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool);
+COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<bool>::Type>::value), WTF_test_RemoveVolatile_bool);
+COMPILE_ASSERT((!IsSameType<bool, RemoveVolatile<const bool>::Type>::value), WTF_test_RemoveVolatile_const_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<volatile bool>::Type>::value), WTF_test_RemoveVolatile_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<bool>::Type>::value), WTF_test_RemoveConstVolatile_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const bool>::Type>::value), WTF_test_RemoveConstVolatile_const_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_volatile_bool);
+COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_const_volatile_bool);
+
+COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_RemovePointer_int);
+COMPILE_ASSERT((IsSameType<int, RemovePointer<int*>::Type>::value), WTF_Test_RemovePointer_int_pointer);
+COMPILE_ASSERT((!IsSameType<int, RemovePointer<int**>::Type>::value), WTF_Test_RemovePointer_int_pointer_pointer);
+
+} // namespace WTF
--- /dev/null
+ /*
+ * Copyright (C) 2006, 2007, 2008 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 TypeTraits_h
+#define TypeTraits_h
+
+#include "Platform.h"
+
+#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
+#include <type_traits>
+#endif
+
+namespace WTF {
+
+ // The following are provided in this file:
+ //
+ // IsInteger<T>::value
+ // IsPod<T>::value, see the definition for a note about its limitations
+ // IsConvertibleToInteger<T>::value
+ //
+ // IsSameType<T, U>::value
+ //
+ // RemovePointer<T>::Type
+ // RemoveConst<T>::Type
+ // RemoveVolatile<T>::Type
+ // RemoveConstVolatile<T>::Type
+ //
+ // COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do.
+
+ template<typename T> struct IsInteger { static const bool value = false; };
+ template<> struct IsInteger<bool> { static const bool value = true; };
+ template<> struct IsInteger<char> { static const bool value = true; };
+ template<> struct IsInteger<signed char> { static const bool value = true; };
+ template<> struct IsInteger<unsigned char> { static const bool value = true; };
+ template<> struct IsInteger<short> { static const bool value = true; };
+ template<> struct IsInteger<unsigned short> { static const bool value = true; };
+ template<> struct IsInteger<int> { static const bool value = true; };
+ template<> struct IsInteger<unsigned int> { static const bool value = true; };
+ template<> struct IsInteger<long> { static const bool value = true; };
+ template<> struct IsInteger<unsigned long> { static const bool value = true; };
+ 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
+
+ // IsPod is misnamed as it doesn't cover all plain old data (pod) types.
+ // Specifically, it doesn't allow for enums or for structs.
+ template <typename T> struct IsPod { static const bool value = IsInteger<T>::value; };
+ template <> struct IsPod<float> { static const bool value = true; };
+ template <> struct IsPod<double> { static const bool value = true; };
+ template <> struct IsPod<long double> { static const bool value = true; };
+ template <typename P> struct IsPod<P*> { static const bool value = true; };
+
+ template<typename T> class IsConvertibleToInteger {
+ // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
+ // by not converting int's to doubles.
+ template<bool performCheck, typename U> class IsConvertibleToDouble;
+ template<typename U> class IsConvertibleToDouble<false, U> {
+ public:
+ static const bool value = false;
+ };
+
+ template<typename U> class IsConvertibleToDouble<true, U> {
+ typedef char YesType;
+ struct NoType {
+ char padding[8];
+ };
+
+ static YesType floatCheck(long double);
+ static NoType floatCheck(...);
+ static T& t;
+ public:
+ static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
+ };
+
+ public:
+ static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
+ };
+
+ template <typename T, typename U> struct IsSameType {
+ static const bool value = false;
+ };
+
+ template <typename T> struct IsSameType<T, T> {
+ static const bool value = true;
+ };
+
+ template <typename T> struct RemoveConst {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveConst<const T> {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveVolatile {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveVolatile<volatile T> {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemoveConstVolatile {
+ typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
+ };
+
+ template <typename T> struct RemovePointer {
+ typedef T Type;
+ };
+
+ template <typename T> struct RemovePointer<T*> {
+ typedef T Type;
+ };
+
+#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
+
+ // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace.
+ // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace.
+ template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { };
+ template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { };
+
+#else
+
+ // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor
+ // and HasTrivialDestructor definitions. The definitions here include most built-in
+ // scalar types but do not include POD structs and classes. For the intended purposes of
+ // type_traits this results correct but potentially less efficient code.
+ template <typename T, T v>
+ struct IntegralConstant {
+ static const T value = v;
+ typedef T value_type;
+ typedef IntegralConstant<T, v> type;
+ };
+
+ typedef IntegralConstant<bool, true> true_type;
+ typedef IntegralConstant<bool, false> false_type;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+ // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor,
+ // but for some unexplained reason it doesn't work on built-in types.
+ template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ };
+ template <typename T> struct HasTrivialDestructor : public IntegralConstant<bool, __has_trivial_destructor(T)>{ };
+#else
+ template <typename T> struct HasTrivialConstructor : public false_type{ };
+ template <typename T> struct HasTrivialDestructor : public false_type{ };
+#endif
+
+ template <typename T> struct HasTrivialConstructor<T*> : public true_type{ };
+ template <typename T> struct HasTrivialDestructor<T*> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<float> : public true_type{ };
+ template <> struct HasTrivialConstructor<const float> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile float> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile float> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<double> : public true_type{ };
+ template <> struct HasTrivialConstructor<const double> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile double> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile double> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<long double> : public true_type{ };
+ template <> struct HasTrivialConstructor<const long double> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile long double> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile long double> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<unsigned char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const unsigned char> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile unsigned char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile unsigned char> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<unsigned short> : public true_type{ };
+ template <> struct HasTrivialConstructor<const unsigned short> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile unsigned short> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile unsigned short> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<unsigned int> : public true_type{ };
+ template <> struct HasTrivialConstructor<const unsigned int> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile unsigned int> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile unsigned int> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<unsigned long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const unsigned long> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile unsigned long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile unsigned long> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<unsigned long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const unsigned long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile unsigned long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile unsigned long long> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<signed char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const signed char> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile signed char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile signed char> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<signed short> : public true_type{ };
+ template <> struct HasTrivialConstructor<const signed short> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile signed short> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile signed short> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<signed int> : public true_type{ };
+ template <> struct HasTrivialConstructor<const signed int> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile signed int> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile signed int> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<signed long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const signed long> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile signed long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile signed long> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<signed long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const signed long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile signed long long> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile signed long long> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<bool> : public true_type{ };
+ template <> struct HasTrivialConstructor<const bool> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile bool> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile bool> : public true_type{ };
+
+ template <> struct HasTrivialConstructor<char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const char> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile char> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile char> : public true_type{ };
+
+ #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template <> struct HasTrivialConstructor<wchar_t> : public true_type{ };
+ template <> struct HasTrivialConstructor<const wchar_t> : public true_type{ };
+ template <> struct HasTrivialConstructor<volatile wchar_t> : public true_type{ };
+ template <> struct HasTrivialConstructor<const volatile wchar_t> : public true_type{ };
+ #endif
+
+ template <> struct HasTrivialDestructor<float> : public true_type{ };
+ template <> struct HasTrivialDestructor<const float> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile float> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile float> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<double> : public true_type{ };
+ template <> struct HasTrivialDestructor<const double> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile double> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile double> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<long double> : public true_type{ };
+ template <> struct HasTrivialDestructor<const long double> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile long double> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile long double> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<unsigned char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const unsigned char> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile unsigned char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile unsigned char> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<unsigned short> : public true_type{ };
+ template <> struct HasTrivialDestructor<const unsigned short> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile unsigned short> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile unsigned short> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<unsigned int> : public true_type{ };
+ template <> struct HasTrivialDestructor<const unsigned int> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile unsigned int> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile unsigned int> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<unsigned long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const unsigned long> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile unsigned long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile unsigned long> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<unsigned long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const unsigned long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile unsigned long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile unsigned long long> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<signed char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const signed char> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile signed char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile signed char> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<signed short> : public true_type{ };
+ template <> struct HasTrivialDestructor<const signed short> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile signed short> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile signed short> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<signed int> : public true_type{ };
+ template <> struct HasTrivialDestructor<const signed int> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile signed int> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile signed int> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<signed long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const signed long> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile signed long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile signed long> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<signed long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const signed long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile signed long long> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile signed long long> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<bool> : public true_type{ };
+ template <> struct HasTrivialDestructor<const bool> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile bool> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile bool> : public true_type{ };
+
+ template <> struct HasTrivialDestructor<char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const char> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile char> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile char> : public true_type{ };
+
+ #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template <> struct HasTrivialDestructor<wchar_t> : public true_type{ };
+ template <> struct HasTrivialDestructor<const wchar_t> : public true_type{ };
+ template <> struct HasTrivialDestructor<volatile wchar_t> : public true_type{ };
+ template <> struct HasTrivialDestructor<const volatile wchar_t> : public true_type{ };
+ #endif
+
+#endif // __GLIBCXX__, etc.
+
+} // namespace WTF
+
+#endif // TypeTraits_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.
+ */
+
+#ifndef VMTags_h
+#define VMTags_h
+
+#include <wtf/Platform.h>
+
+// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map
+// in order to aid tools that inspect system memory use.
+#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+
+#include <mach/vm_statistics.h>
+
+#if defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
+#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
+#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
+#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
+#else
+#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63)
+#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64)
+#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
+#endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
+
+#else // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+
+#define VM_TAG_FOR_COLLECTOR_MEMORY -1
+#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
+#define VM_TAG_FOR_REGISTERFILE_MEMORY -1
+
+#endif // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+
+#endif // VMTags_h
#ifndef WTF_Vector_h
#define WTF_Vector_h
-#include "Assertions.h"
-#include "FastMalloc.h"
+#include "FastAllocBase.h"
#include "Noncopyable.h"
#include "NotFound.h"
#include "VectorTraits.h"
#include <limits>
-#include <stdlib.h>
-#include <string.h>
#include <utility>
+#if PLATFORM(QT)
+#include <QDataStream>
+#endif
+
namespace WTF {
using std::min;
VectorBuffer(size_t capacity)
: Base(inlineBuffer(), inlineCapacity)
{
- allocateBuffer(capacity);
+ if (capacity > inlineCapacity)
+ Base::allocateBuffer(capacity);
}
~VectorBuffer()
{
if (newCapacity > inlineCapacity)
Base::allocateBuffer(newCapacity);
+ else {
+ m_buffer = inlineBuffer();
+ m_capacity = inlineCapacity;
+ }
}
void deallocateBuffer(T* bufferToDeallocate)
};
template<typename T, size_t inlineCapacity = 0>
- class Vector {
+ class Vector : public FastAllocBase {
private:
typedef VectorBuffer<T, inlineCapacity> Buffer;
typedef VectorTypeOperations<T> TypeOperations;
Buffer m_buffer;
};
+#if PLATFORM(QT)
+ template<typename T>
+ QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
+ {
+ stream << qint64(data.size());
+ foreach (const T& i, data)
+ stream << i;
+ return stream;
+ }
+
+ template<typename T>
+ QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
+ {
+ data.clear();
+ qint64 count;
+ T item;
+ stream >> count;
+ data.reserveCapacity(count);
+ for (qint64 i = 0; i < count; ++i) {
+ stream >> item;
+ data.append(item);
+ }
+ return stream;
+ }
+#endif
+
template<typename T, size_t inlineCapacity>
Vector<T, inlineCapacity>::Vector(const Vector& other)
: m_size(other.size())
}
template<typename T, size_t inlineCapacity>
- void Vector<T, inlineCapacity>::resize(size_t size)
+ inline void Vector<T, inlineCapacity>::resize(size_t size)
{
if (size <= m_size)
TypeOperations::destruct(begin() + size, end());
}
template<typename T, size_t inlineCapacity> template<typename U>
- inline void Vector<T, inlineCapacity>::append(const U& val)
+ ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
{
const U* ptr = &val;
if (size() == capacity()) {
#define WTF_VectorTraits_h
#include "RefPtr.h"
+#include "TypeTraits.h"
#include <utility>
#include <memory>
namespace WTF {
- template <typename T> struct IsPod { static const bool value = false; };
- template <> struct IsPod<bool> { static const bool value = true; };
- template <> struct IsPod<char> { static const bool value = true; };
- template <> struct IsPod<signed char> { static const bool value = true; };
- template <> struct IsPod<unsigned char> { static const bool value = true; };
- template <> struct IsPod<short> { static const bool value = true; };
- template <> struct IsPod<unsigned short> { static const bool value = true; };
- template <> struct IsPod<int> { static const bool value = true; };
- template <> struct IsPod<unsigned int> { static const bool value = true; };
- template <> struct IsPod<long> { static const bool value = true; };
- template <> struct IsPod<unsigned long> { static const bool value = true; };
- template <> struct IsPod<long long> { static const bool value = true; };
- template <> struct IsPod<unsigned long long> { static const bool value = true; };
- template <> struct IsPod<float> { static const bool value = true; };
- template <> struct IsPod<double> { static const bool value = true; };
- template <> struct IsPod<long double> { static const bool value = true; };
- template <typename P> struct IsPod<P *> { static const bool value = true; };
-
template<bool isPod, typename T>
class VectorTraitsBase;
--- /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 ChromiumThreading_h
+#define ChromiumThreading_h
+
+namespace WTF {
+
+ // An interface to the embedding layer, which provides threading support.
+ class ChromiumThreading {
+ public:
+ static void initializeMainThread();
+ static void scheduleDispatchFunctionsOnMainThread();
+ };
+
+} // namespace WTF
+
+#endif // ChromiumThreading_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.
+*/
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "ChromiumThreading.h"
+
+namespace WTF {
+
+void initializeMainThreadPlatform()
+{
+ ChromiumThreading::initializeMainThread();
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+ ChromiumThreading::scheduleDispatchFunctionsOnMainThread();
+}
+
+} // namespace WTF
+
#include <wtf/AlwaysInline.h>
#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>
+#include <wtf/Vector.h>
#include <wtf/Threading.h>
+#include <stdio.h>
+
#if COMPILER(MSVC)
#pragma warning(disable: 4244)
#pragma warning(disable: 4245)
#endif
#else
#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
-#define dval(x) ((U*)&x)->d
+#define dval(x) (x)->d
#endif
/* The following definition of Storeinc is appropriate for MIPS processors.
#define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
#define Big1 0xffffffff
+
+// FIXME: we should remove non-Pack_32 mode since it is unused and unmaintained
#ifndef Pack_32
#define Pack_32
#endif
#define Kmax 15
-struct Bigint {
- struct Bigint* next;
- int k, maxwds, sign, wds;
- uint32_t x[1];
-};
+struct BigInt {
+ BigInt() : sign(0) { }
+ int sign;
-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;
-}
+ void clear()
+ {
+ sign = 0;
+ m_words.clear();
+ }
+
+ size_t size() const
+ {
+ return m_words.size();
+ }
-static void Bfree(Bigint* v)
-{
- fastFree(v);
-}
+ void resize(size_t s)
+ {
+ m_words.resize(s);
+ }
+
+ uint32_t* words()
+ {
+ return m_words.data();
+ }
-#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int))
+ const uint32_t* words() const
+ {
+ return m_words.data();
+ }
+
+ void append(uint32_t w)
+ {
+ m_words.append(w);
+ }
+
+ Vector<uint32_t, 16> m_words;
+};
-static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */
+static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */
{
#ifdef USE_LONG_LONG
unsigned long long carry;
uint32_t carry;
#endif
- int wds = b->wds;
- uint32_t* x = b->x;
+ int wds = b.size();
+ uint32_t* x = b.words();
int i = 0;
carry = a;
do {
#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;
+ if (carry)
+ b.append((uint32_t)carry);
}
-static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9)
+static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9)
{
int k;
int32_t y;
for (k = 0, y = 1; x > y; y <<= 1, k++) { }
#ifdef Pack_32
- Bigint* b = Balloc(k);
- b->x[0] = y9;
- b->wds = 1;
+ b.sign = 0;
+ b.resize(1);
+ b.words()[0] = y9;
#else
- Bigint* b = Balloc(k + 1);
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+ b.sign = 0;
+ b.resize((b->x[1] = y9 >> 16) ? 2 : 1);
+ b.words()[0] = y9 & 0xffff;
#endif
int i = 9;
if (9 < nd0) {
s += 9;
do {
- b = multadd(b, 10, *s++ - '0');
+ multadd(b, 10, *s++ - '0');
} while (++i < nd0);
s++;
} else
s += 10;
for (; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
+ multadd(b, 10, *s++ - '0');
}
static int hi0bits(uint32_t x)
return k;
}
-static Bigint* i2b(int i)
+static void i2b(BigInt& b, int i)
{
- Bigint* b;
-
- b = Balloc(1);
- b->x[0] = i;
- b->wds = 1;
- return b;
+ b.sign = 0;
+ b.resize(1);
+ b.words()[0] = i;
}
-static Bigint* mult(Bigint* a, Bigint* b)
+static void mult(BigInt& aRef, const BigInt& bRef)
{
- Bigint* c;
- int k, wa, wb, wc;
- uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ const BigInt* a = &aRef;
+ const BigInt* b = &bRef;
+ BigInt c;
+ int wa, wb, wc;
+ const uint32_t *x = 0, *xa, *xb, *xae, *xbe;
+ uint32_t *xc, *xc0;
uint32_t y;
#ifdef USE_LONG_LONG
unsigned long long carry, z;
uint32_t carry, z;
#endif
- if (a->wds < b->wds) {
- c = a;
+ if (a->size() < b->size()) {
+ const BigInt* tmp = a;
a = b;
- b = c;
+ b = tmp;
}
- k = a->k;
- wa = a->wds;
- wb = b->wds;
+
+ wa = a->size();
+ wb = b->size();
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;
+ c.resize(wc);
+
+ for (xc = c.words(), xa = xc + wc; xc < xa; xc++)
+ *xc = 0;
+ xa = a->words();
xae = xa + wa;
- xb = b->x;
+ xb = b->words();
xbe = xb + wb;
- xc0 = c->x;
+ xc0 = c.words();
#ifdef USE_LONG_LONG
for (; xb < xbe; xc0++) {
if ((y = *xb++)) {
}
#endif
#endif
- for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
- c->wds = wc;
- return c;
+ for (xc0 = c.words(), xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
+ c.resize(wc);
+ aRef = c;
}
-static Bigint* p5s;
+struct P5Node {
+ BigInt val;
+ P5Node* next;
+};
+
+static P5Node* p5s;
static int p5s_count;
-static Bigint* pow5mult(Bigint* b, int k)
+static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
{
static int p05[3] = { 5, 25, 125 };
if (int i = k & 3)
- b = multadd(b, p05[i - 1], 0);
+ multadd(b, p05[i - 1], 0);
if (!(k >>= 2))
- return b;
+ return;
#if ENABLE(JSC_MULTIPLE_THREADS)
s_dtoaP5Mutex->lock();
#endif
- Bigint* p5 = p5s;
+ P5Node* p5 = p5s;
+
if (!p5) {
/* first time */
- p5 = p5s = i2b(625);
+ p5 = new P5Node;
+ i2b(p5->val, 625);
+ p5->next = 0;
+ p5s = p5;
p5s_count = 1;
}
+
int p5s_count_local = p5s_count;
#if ENABLE(JSC_MULTIPLE_THREADS)
s_dtoaP5Mutex->unlock();
int p5s_used = 0;
for (;;) {
- if (k & 1) {
- Bigint* b1 = mult(b, p5);
- Bfree(b);
- b = b1;
- }
+ if (k & 1)
+ mult(b, p5->val);
+
if (!(k >>= 1))
break;
#endif
if (p5s_used == p5s_count) {
ASSERT(!p5->next);
- p5->next = mult(p5, p5);
+ p5->next = new P5Node;
+ p5->next->next = 0;
+ p5->next->val = p5->val;
+ mult(p5->next->val, p5->next->val);
++p5s_count;
}
}
p5 = p5->next;
}
-
- return b;
}
-static Bigint* lshift(Bigint* b, int k)
+static ALWAYS_INLINE void 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);
+ int origSize = b.size();
+ int n1 = n + origSize + 1;
- const uint32_t* srcStart = b->x;
- uint32_t* dstStart = result->x;
- const uint32_t* src = srcStart + b->wds - 1;
+ if (k &= 0x1f)
+ b.resize(b.size() + n + 1);
+ else
+ b.resize(b.size() + n);
+
+ const uint32_t* srcStart = b.words();
+ uint32_t* dstStart = b.words();
+ const uint32_t* src = srcStart + origSize - 1;
uint32_t* dst = dstStart + n1 - 1;
#ifdef Pack_32
- if (k &= 0x1f) {
+ if (k) {
uint32_t hiSubword = 0;
int s = 32 - k;
for (; src >= srcStart; --src) {
}
*dst = hiSubword;
ASSERT(dst == dstStart + n);
- result->wds = b->wds + n + (result->x[n1 - 1] != 0);
+
+ b.resize(origSize + n + (b.words()[n1 - 1] != 0));
}
#else
if (k &= 0xf) {
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;
+ ASSERT(b.size() <= 1 || b.words()[b.size() - 1]);
}
-static int cmp(Bigint* a, Bigint* b)
+static int cmp(const BigInt& a, const BigInt& b)
{
- uint32_t *xa, *xa0, *xb, *xb0;
+ const 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]);
+ i = a.size();
+ j = b.size();
+ ASSERT(i <= 1 || a.words()[i - 1]);
+ ASSERT(j <= 1 || b.words()[j - 1]);
if (i -= j)
return i;
- xa0 = a->x;
+ xa0 = a.words();
xa = xa0 + j;
- xb0 = b->x;
+ xb0 = b.words();
xb = xb0 + j;
for (;;) {
if (*--xa != *--xb)
return 0;
}
-static Bigint* diff(Bigint* a, Bigint* b)
+static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef)
{
- Bigint* c;
+ const BigInt* a = &aRef;
+ const BigInt* b = &bRef;
int i, wa, wb;
- uint32_t *xa, *xae, *xb, *xbe, *xc;
+ uint32_t *xc;
- i = cmp(a,b);
+ i = cmp(*a, *b);
if (!i) {
- c = Balloc(0);
- c->wds = 1;
- c->x[0] = 0;
- return c;
+ c.sign = 0;
+ c.resize(1);
+ c.words()[0] = 0;
+ return;
}
if (i < 0) {
- c = a;
+ const BigInt* tmp = a;
a = b;
- b = c;
+ b = tmp;
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;
+
+ wa = a->size();
+ const uint32_t* xa = a->words();
+ const uint32_t* xae = xa + wa;
+ wb = b->size();
+ const uint32_t* xb = b->words();
+ const uint32_t* xbe = xb + wb;
+
+ c.resize(wa);
+ c.sign = i;
+ xc = c.words();
#ifdef USE_LONG_LONG
unsigned long long borrow = 0;
do {
#endif
while (!*--xc)
wa--;
- c->wds = wa;
- return c;
+ c.resize(wa);
}
-static double ulp(double x)
+static double ulp(U *x)
{
register int32_t L;
- double a;
+ U u;
L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
#ifndef Avoid_Underflow
if (L > 0) {
#endif
#endif
- word0(a) = L;
- word1(a) = 0;
+ word0(&u) = L;
+ word1(&u) = 0;
#ifndef Avoid_Underflow
#ifndef Sudden_Underflow
} else {
L = -L >> Exp_shift;
if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
+ word0(&u) = 0x80000 >> L;
+ word1(&u) = 0;
} else {
- word0(a) = 0;
+ word0(&u) = 0;
L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ word1(&u) = L >= 31 ? 1 : 1 << 31 - L;
}
}
#endif
#endif
- return dval(a);
+ return dval(&u);
}
-static double b2d(Bigint* a, int* e)
+static double b2d(const BigInt& a, int* e)
{
- uint32_t* xa;
- uint32_t* xa0;
+ const uint32_t* xa;
+ const uint32_t* xa0;
uint32_t w;
uint32_t y;
uint32_t z;
int k;
- double d;
+ U d;
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
- xa0 = a->x;
- xa = xa0 + a->wds;
+ xa0 = a.words();
+ xa = xa0 + a.size();
y = *--xa;
ASSERT(y);
k = hi0bits(y);
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | (y >> (Ebits - k));
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32 - Ebits) + k | w >> Ebits - k;
+ 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;
+ d0 = Exp_1 | (y << k) | (z >> (32 - k));
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = (z << k) | (y >> (32 - k));
} else {
d0 = Exp_1 | y;
d1 = z;
ret_d:
#undef d0
#undef d1
- return dval(d);
+ return dval(&d);
}
-static Bigint* d2b(double d, int* e, int* bits)
+static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits)
{
- Bigint* b;
int de, k;
uint32_t *x, y, z;
#ifndef Sudden_Underflow
#define d0 word0(d)
#define d1 word1(d)
+ b.sign = 0;
#ifdef Pack_32
- b = Balloc(1);
+ b.resize(1);
#else
- b = Balloc(2);
+ b.resize(2);
#endif
- x = b->x;
+ x = b.words();
z = d0 & Frac_mask;
d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
#ifdef Pack_32
if ((y = d1)) {
if ((k = lo0bits(&y))) {
- x[0] = y | z << 32 - k;
+ x[0] = y | (z << (32 - k));
z >>= k;
} else
x[0] = y;
+ if (z) {
+ b.resize(2);
+ x[1] = z;
+ }
+
#ifndef Sudden_Underflow
- i =
+ i = b.size();
#endif
- b->wds = (x[1] = z) ? 2 : 1;
} else {
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
- i =
+ i = 1;
#endif
- b->wds = 1;
+ b.resize(1);
k += 32;
}
#else
k += 32;
} while (!x[i])
--i;
- b->wds = i + 1;
+ b->resize(i + 1);
#endif
#ifndef Sudden_Underflow
if (de) {
#endif
}
#endif
- return b;
}
#undef d0
#undef d1
-static double ratio(Bigint* a, Bigint* b)
+static double ratio(const BigInt& a, const BigInt& b)
{
- double da, db;
+ U da, db;
int k, ka, kb;
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
+ dval(&da) = b2d(a, &ka);
+ dval(&db) = b2d(b, &kb);
#ifdef Pack_32
- k = ka - kb + 32 * (a->wds - b->wds);
+ k = ka - kb + 32 * (a.size() - b.size());
#else
- k = ka - kb + 16 * (a->wds - b->wds);
+ k = ka - kb + 16 * (a.size() - b.size());
#endif
if (k > 0)
- word0(da) += k * Exp_msk1;
+ word0(&da) += k * Exp_msk1;
else {
k = -k;
- word0(db) += k * Exp_msk1;
+ word0(&db) += k * Exp_msk1;
}
- return dval(da) / dval(db);
+ return dval(&da) / dval(&db);
}
static const double tens[] = {
}
#ifndef No_Hex_NaN
-static void hexnan(double* rvp, const char** sp)
+static void hexnan(U* rvp, const char** sp)
{
uint32_t c, x[2];
const char* s;
x[1] = (x[1] << 4) | c;
}
if ((x[0] &= 0xfffff) || x[1]) {
- word0(*rvp) = Exp_mask | x[0];
- word1(*rvp) = x[1];
+ word0(rvp) = Exp_mask | x[0];
+ word1(rvp) = x[1];
}
}
#endif /*No_Hex_NaN*/
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;
+ double aadj, aadj1;
+ U aadj2, adj, rv, rv0;
int32_t L;
uint32_t y, z;
- Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
+ BigInt bb, bb1, bd, bd0, bs, delta;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
sign = nz0 = nz = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0;
for (s = s00; ; s++)
switch (*s) {
case '-':
--s;
if (!match(&s,"inity"))
++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
+ 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;
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
#ifndef No_Hex_NaN
if (*s == '(') /*)*/
hexnan(&rv, &s);
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ 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;
+ 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]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret;
}
i = DBL_DIG - nd;
* this for larger i values.
*/
e -= i;
- dval(rv) *= tens[i];
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ 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]);
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret;
}
#endif
if (e1 > 0) {
if ((i = e1 & 15))
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
errno = ERANGE;
#endif
/* Can't trust HUGE_VAL */
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
#ifdef SET_INEXACT
/* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
+ 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];
+ 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))
+ 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;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
} else
- word0(rv) += P * Exp_msk1;
+ word0(&rv) += P * Exp_msk1;
}
} else if (e1 < 0) {
e1 = -e1;
if ((i = e1 & 15))
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
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) {
+ 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;
+ word1(&rv) = 0;
if (j >= 53)
- word0(rv) = (P + 2) * Exp_msk1;
+ word0(&rv) = (P + 2) * Exp_msk1;
else
- word0(rv) &= 0xffffffff << j - 32;
+ word0(&rv) &= 0xffffffff << (j - 32);
} else
- word1(rv) &= 0xffffffff << j;
+ word1(&rv) &= 0xffffffff << j;
}
#else
for (j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ 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];
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2. * dval(&rv0);
+ dval(&rv) *= tinytens[j];
#endif
- if (!dval(rv)) {
+ if (!dval(&rv)) {
undfl:
- dval(rv) = 0.;
+ dval(&rv) = 0.;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
- if (bd0)
- goto retfree;
goto ret;
}
#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
/* The refinement below will clean
* this approximation up.
*/
/* Put digits into bd: true value = bd * 10^e */
- bd0 = s2b(s0, nd0, nd, y);
+ s2b(bd0, 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);
+ bd = bd0;
+ d2b(bb, &rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
+ i2b(bs, 1);
if (e >= 0) {
bb2 = bb5 = 0;
bs2 -= i;
}
if (bb5 > 0) {
- bs = pow5mult(bs, bb5);
- bb1 = mult(bs, bb);
- Bfree(bb);
- bb = bb1;
+ pow5mult(bs, bb5);
+ mult(bb, bs);
}
if (bb2 > 0)
- bb = lshift(bb, bb2);
+ lshift(bb, bb2);
if (bd5 > 0)
- bd = pow5mult(bd, bd5);
+ pow5mult(bd, bd5);
if (bd2 > 0)
- bd = lshift(bd, bd2);
+ lshift(bd, bd2);
if (bs2 > 0)
- bs = lshift(bs, bs2);
- delta = diff(bb, bd);
- dsign = delta->sign;
- delta->sign = 0;
+ lshift(bs, bs2);
+ diff(delta, 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
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
+ || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
#endif
) {
#ifdef SET_INEXACT
- if (!delta->x[0] && delta->wds <= 1)
+ if (!delta->words()[0] && delta->size() <= 1)
inexact = 0;
#endif
break;
}
- if (!delta->x[0] && delta->wds <= 1) {
+ if (!delta.words()[0] && delta.size() <= 1) {
/* exact result */
#ifdef SET_INEXACT
inexact = 0;
#endif
break;
}
- delta = lshift(delta,Log2P);
+ 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) == (
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1)
+ (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;
+ 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)) {
+ } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
#ifdef Avoid_Underflow
if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1))
#else
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
if (scale) {
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
if (L <= (2 * P + 1) * Exp_msk1) {
if (L > (P + 2) * Exp_msk1)
/* round even ==> */
}
}
#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
break;
}
- if (!(word1(rv) & LSB))
+ if (!(word1(&rv) & LSB))
break;
if (dsign)
- dval(rv) += ulp(dval(rv));
+ dval(&rv) += ulp(&rv);
else {
- dval(rv) -= ulp(dval(rv));
+ dval(&rv) -= ulp(&rv);
#ifndef Sudden_Underflow
- if (!dval(rv))
+ if (!dval(&rv))
goto undfl;
#endif
}
if ((aadj = ratio(delta, bs)) <= 2.) {
if (dsign)
aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
+ if (word1(&rv) == Tiny1 && !word0(&rv))
goto undfl;
#endif
aadj = 1.;
aadj1 += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
- y = word0(rv) & Exp_mask;
+ 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)
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P * Exp_msk1;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
+ 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;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
goto cont;
} else
- word0(rv) += P * Exp_msk1;
+ word0(&rv) += P * Exp_msk1;
} else {
#ifdef Avoid_Underflow
if (scale && y <= 2 * P * Exp_msk1) {
aadj = z;
aadj1 = dsign ? aadj : -aadj;
}
- word0(aadj1) += (2 * P + 1) * Exp_msk1 - y;
+ dval(&aadj2) = aadj1;
+ word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y;
+ aadj1 = dval(&aadj2);
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
#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(&rv) & Exp_mask) <= P * Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P * Exp_msk1;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
+ if ((word0(&rv) & Exp_mask) <= P * Exp_msk1)
{
- if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
+ if (word0(&rv0) == Tiny0 && word1(&rv0) == Tiny1)
goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
goto cont;
}
else
- word0(rv) -= P * Exp_msk1;
+ word0(&rv) -= P * Exp_msk1;
} else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
}
#else /*Sudden_Underflow*/
/* Compute adj so that the IEEE rounding rules will
if (!dsign)
aadj1 = -aadj1;
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ adj.d = aadj1 * ulp(&rv);
+ dval(&rv) += adj.d;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
- z = word0(rv) & Exp_mask;
+ z = word0(&rv) & Exp_mask;
#ifndef SET_INEXACT
#ifdef Avoid_Underflow
if (!scale)
L = (int32_t)aadj;
aadj -= L;
/* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
} else if (aadj < .4999999 / FLT_RADIX)
}
#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.;
+ 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);
+ 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)
+ if (word0(&rv) == 0 && word1(&rv) == 0)
errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
+ if (inexact && !(word0(&rv) & Exp_mask)) {
/* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
+ 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);
+ return sign ? -dval(&rv) : dval(&rv);
}
-static int quorem(Bigint* b, Bigint* S)
+static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
{
- int n;
+ size_t n;
uint32_t *bx, *bxe, q, *sx, *sxe;
#ifdef USE_LONG_LONG
unsigned long long borrow, carry, y, ys;
uint32_t si, z, zs;
#endif
#endif
+ ASSERT(b.size() <= 1 || b.words()[b.size() - 1]);
+ ASSERT(S.size() <= 1 || S.words()[S.size() - 1]);
- n = S->wds;
- ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem");
- if (b->wds < n)
+ n = S.size();
+ ASSERT_WITH_MESSAGE(b.size() <= n, "oversize b in quorem");
+ if (b.size() < n)
return 0;
- sx = S->x;
+ sx = S.words();
sxe = sx + --n;
- bx = b->x;
+ bx = b.words();
bxe = bx + n;
q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem");
#endif
} while (sx <= sxe);
if (!*bxe) {
- bx = b->x;
+ bx = b.words();
while (--bxe > bx && !*bxe)
--n;
- b->wds = n;
+ b.resize(n);
}
}
if (cmp(b, S) >= 0) {
q++;
borrow = 0;
carry = 0;
- bx = b->x;
- sx = S->x;
+ bx = b.words();
+ sx = S.words();
do {
#ifdef USE_LONG_LONG
ys = *sx++ + carry;
#endif
#endif
} while (sx <= sxe);
- bx = b->x;
+ bx = b.words();
bxe = bx + n;
if (!*bxe) {
while (--bxe > bx && !*bxe)
--n;
- b->wds = n;
+ b.resize(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
* calculation.
*/
-char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve)
+void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rve)
{
/*
Arguments ndigits, decpt, sign are similar to those
int denorm;
uint32_t x;
#endif
- Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S;
- double d2, ds, eps;
+ BigInt b, b1, delta, mlo, mhi, S;
+ U d2, eps, u;
+ double ds;
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) {
+ u.d = dd;
+ if (word0(&u) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
+ word0(&u) &= ~Sign_bit; /* clear sign bit */
} else
*sign = 0;
- if ((word0(d) & Exp_mask) == Exp_mask)
+ if ((word0(&u) & 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 (!word1(&u) && !(word0(&u) & 0xfffff))
+ strcpy(result, "Infinity");
+ else
+ strcpy(result, "NaN");
+ return;
}
- if (!dval(d)) {
+ if (!dval(&u)) {
*decpt = 1;
- return nrv_alloc("0", rve, 1);
+ result[0] = '0';
+ result[1] = '\0';
+ return;
}
#ifdef SET_INEXACT
inexact = 1;
#endif
- b = d2b(dval(d), &be, &bbits);
+ d2b(b, &u, &be, &bbits);
#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
+ i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
+ if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
+ dval(&d2) = dval(&u);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10)
/* 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 */
+ x = (i > 32) ? (word0(&u) << (64 - i)) | (word1(&u) >> (i - 32))
+ : word1(&u) << (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);
+ 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])
+ if (dval(&u) < tens[k])
k--;
k_check = 0;
}
ilim = ilim1 = -1;
i = 18;
ndigits = 0;
- s = s0 = rv_alloc(i);
+ s = s0 = result;
if (ilim >= 0 && ilim <= Quick_max && try_quick) {
/* Try to get by with floating-point arithmetic. */
i = 0;
- dval(d2) = dval(d);
+ dval(&d2) = dval(&u);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens - 1];
+ dval(&u) /= bigtens[n_bigtens - 1];
ieps++;
}
for (; j; j >>= 1, i++) {
ds *= bigtens[i];
}
}
- dval(d) /= ds;
+ dval(&u) /= ds;
} else if ((j1 = -k)) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&u) *= tens[j1 & 0xf];
for (j = j1 >> 4; j; j >>= 1, i++) {
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&u) *= bigtens[i];
}
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&u) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&u) *= 10.;
ieps++;
}
- dval(eps) = (ieps * dval(d)) + 7.;
- word0(eps) -= (P - 1) * Exp_msk1;
+ dval(&eps) = (ieps * dval(&u)) + 7.;
+ word0(&eps) -= (P - 1) * Exp_msk1;
if (ilim == 0) {
- S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
+ S.clear();
+ mhi.clear();
+ dval(&u) -= 5.;
+ if (dval(&u) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&u) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps);
+ dval(&eps) = (0.5 / tens[ilim - 1]) - dval(&eps);
for (i = 0;;) {
- L = (long int)dval(d);
- dval(d) -= L;
+ L = (long int)dval(&u);
+ dval(&u) -= L;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
- goto ret1;
- if (1. - dval(d) < dval(eps))
+ if (dval(&u) < dval(&eps))
+ goto ret;
+ if (1. - dval(&u) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ dval(&eps) *= 10.;
+ dval(&u) *= 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))
+ dval(&eps) *= tens[ilim - 1];
+ for (i = 1;; i++, dval(&u) *= 10.) {
+ L = (int32_t)(dval(&u));
+ if (!(dval(&u) -= L))
ilim = i;
*s++ = '0' + (int)L;
if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
+ if (dval(&u) > 0.5 + dval(&eps))
goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
+ else if (dval(&u) < 0.5 - dval(&eps)) {
while (*--s == '0') { }
s++;
- goto ret1;
+ goto ret;
}
break;
}
#endif
fast_failed:
s = s0;
- dval(d) = dval(d2);
+ dval(&u) = dval(&d2);
k = k0;
ilim = ilim0;
}
/* Yes. */
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
- S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5 * ds)
+ S.clear();
+ mhi.clear();
+ if (ilim < 0 || dval(&u) <= 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;
+ for (i = 1;; i++, dval(&u) *= 10.) {
+ L = (int32_t)(dval(&u) / ds);
+ dval(&u) -= L * ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
+ if (dval(&u) < 0) {
L--;
- dval(d) += ds;
+ dval(&u) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (!dval(d)) {
+ if (!dval(&u)) {
#ifdef SET_INEXACT
inexact = 0;
#endif
break;
}
if (i == ilim) {
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ dval(&u) += dval(&u);
+ if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) {
bump_up:
while (*--s == '9')
if (s == s0) {
break;
}
}
- goto ret1;
+ goto ret;
}
m2 = b2;
m5 = b5;
- mhi = mlo = 0;
+ mhi.clear();
+ mlo.clear();
if (leftright) {
i =
#ifndef Sudden_Underflow
1 + P - bbits;
b2 += i;
s2 += i;
- mhi = i2b(1);
+ i2b(mhi, 1);
}
if (m2 > 0 && s2 > 0) {
i = m2 < s2 ? m2 : s2;
if (b5 > 0) {
if (leftright) {
if (m5 > 0) {
- mhi = pow5mult(mhi, m5);
- b1 = mult(mhi, b);
- Bfree(b);
- b = b1;
+ pow5mult(mhi, m5);
+ mult(b, mhi);
}
if ((j = b5 - m5))
- b = pow5mult(b, j);
+ pow5mult(b, j);
} else
- b = pow5mult(b, b5);
+ pow5mult(b, b5);
}
- S = i2b(1);
+ i2b(S, 1);
if (s5 > 0)
- S = pow5mult(S, s5);
+ 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)
+ if (!word1(&u) && !(word0(&u) & Bndry_mask)
#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
+ && word0(&u) & (Exp_mask & ~Exp_msk1)
#endif
) {
/* The special case */
* 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))
+ if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0x1f))
i = 32 - i;
#else
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf))
+ if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0xf))
i = 16 - i;
#endif
if (i > 4) {
s2 += i;
}
if (b2 > 0)
- b = lshift(b, b2);
+ lshift(b, b2);
if (s2 > 0)
- S = lshift(S, s2);
+ lshift(S, s2);
if (k_check) {
if (cmp(b,S) < 0) {
k--;
- b = multadd(b, 10, 0); /* we botched the k estimate */
+ multadd(b, 10, 0); /* we botched the k estimate */
if (leftright)
- mhi = multadd(mhi, 10, 0);
+ multadd(mhi, 10, 0);
ilim = ilim1;
}
}
if (leftright) {
if (m2 > 0)
- mhi = lshift(mhi, m2);
+ 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);
+ mhi = mlo;
+ lshift(mhi, Log2P);
}
for (i = 1;;i++) {
* 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)) {
+ diff(delta, S, mhi);
+ j1 = delta.sign ? 1 : cmp(b, delta);
+ if (j1 == 0 && !(word1(&u) & 1)) {
if (dig == '9')
goto round_9_up;
if (j > 0)
*s++ = dig;
goto ret;
}
- if (j < 0 || j == 0 && !(word1(d) & 1)) {
- if (!b->x[0] && b->wds <= 1) {
+ if (j < 0 || (j == 0 && !(word1(&u) & 1))) {
+ if (!b.words()[0] && b.size() <= 1) {
#ifdef SET_INEXACT
inexact = 0;
#endif
goto accept_dig;
}
if (j1 > 0) {
- b = lshift(b, 1);
+ lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9')
+ if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
goto round_9_up;
}
accept_dig:
*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);
- }
+ multadd(b, 10, 0);
+ multadd(mlo, 10, 0);
+ multadd(mhi, 10, 0);
}
} else
for (i = 1;; i++) {
*s++ = dig = quorem(b,S) + '0';
- if (!b->x[0] && b->wds <= 1) {
+ if (!b.words()[0] && b.size() <= 1) {
#ifdef SET_INEXACT
inexact = 0;
#endif
}
if (i >= ilim)
break;
- b = multadd(b, 10, 0);
+ multadd(b, 10, 0);
}
/* Round off last digit */
- b = lshift(b, 1);
+ lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && (dig & 1))) {
roundoff:
while (*--s == '9')
if (s == s0) {
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.;
+ word0(&u) = Exp_1 + (70 << Exp_shift);
+ word1(&u) = 0;
+ dval(&u) += 1.;
}
} else if (!oldinexact)
clear_inexact();
#endif
- Bfree(b);
*s = 0;
*decpt = k + 1;
if (rve)
*rve = s;
- return s0;
}
} // 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);
+ void dtoa(char* result, double d, int ndigits, int* decpt, int* sign, char** rve);
} // namespace WTF
namespace WTF {
+void initializeMainThreadPlatform()
+{
+}
+
static gboolean timeoutFired(gpointer)
{
dispatchFunctionsFromMainThread();
g_timeout_add(0, timeoutFired, 0);
}
-
-}
+} // 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 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;
+}
+
+void setThreadNameInternal(const char*)
+{
+}
+
+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)
#import "config.h"
#import "MainThread.h"
-#import "Threading.h"
#import <Foundation/NSThread.h>
+#import <wtf/Assertions.h>
@interface WTFMainThreadCaller : NSObject {
}
namespace WTF {
+static NSThread* staticMainNSThread = nil;
+static WTFMainThreadCaller* staticMainThreadCaller = nil;
+
+void initializeMainThreadPlatform()
+{
+ ASSERT(!staticMainThreadCaller);
+ staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+ ASSERT(!staticMainNSThread);
+ staticMainNSThread = [[NSThread currentThread] retain];
+}
+
void scheduleDispatchFunctionsOnMainThread()
{
- WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
- [caller performSelector:@selector(call) onThread:mainNSThread() withObject:nil waitUntilDone:NO];
- [caller release];
+ ASSERT(staticMainNSThread);
+ ASSERT(staticMainThreadCaller);
+ [staticMainThreadCaller performSelector:@selector(call) onThread:staticMainNSThread withObject:nil waitUntilDone:NO];
}
} // 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
#import "MainThread.h"
#import <Foundation/NSThread.h>
+#import <wtf/Assertions.h>
@interface WTFMainThreadCaller : NSObject {
}
namespace WTF {
+static WTFMainThreadCaller* staticMainThreadCaller = nil;
+
+void initializeMainThreadPlatform()
+{
+ ASSERT(!staticMainThreadCaller);
+ staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+}
+
void scheduleDispatchFunctionsOnMainThread()
{
- WTFMainThreadCaller *caller = [[WTFMainThreadCaller alloc] init];
- [caller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
- [caller release];
+ ASSERT(staticMainThreadCaller);
+ [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
}
} // namespace WTF
Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker)
+void initializeMainThreadPlatform()
+{
+}
void scheduleDispatchFunctionsOnMainThread()
{
QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection);
}
-}
+} // namespace WTF
#include "MainThreadQt.moc"
--- /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);
+}
+
+void setThreadNameInternal(const char*)
+{
+}
+
+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 QThread::currentThread() == QCoreApplication::instance()->thread();
+}
+
+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;
+
+ // Time is too far in the future (and would overflow unsigned long) - wait forever.
+ if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
+ wait(mutex);
+ return true;
+ }
+
+ double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
+ 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
#include "qt4/UnicodeQt4.h"
#elif USE(ICU_UNICODE)
#include <wtf/unicode/icu/UnicodeIcu.h>
+#elif USE(GLIB_UNICODE)
+#include <wtf/unicode/glib/UnicodeGLib.h>
#else
#error "Unknown Unicode implementation"
#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
+ * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.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 "UnicodeGLib.h"
+
+namespace WTF {
+namespace Unicode {
+
+UChar32 foldCase(UChar32 ch)
+{
+ GOwnPtr<GError> gerror;
+
+ GOwnPtr<char> utf8char;
+ utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr()));
+ if (gerror)
+ return ch;
+
+ GOwnPtr<char> utf8caseFolded;
+ utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1));
+
+ GOwnPtr<gunichar> ucs4Result;
+ ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0));
+
+ return *ucs4Result;
+}
+
+int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ GOwnPtr<GError> gerror;
+
+ GOwnPtr<char> utf8src;
+ utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ GOwnPtr<char> utf8result;
+ utf8result.set(g_utf8_casefold(utf8src.get(), -1));
+
+ long utf16resultLength = -1;
+ GOwnPtr<UChar> utf16result;
+ utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ if (utf16resultLength > resultLength) {
+ *error = true;
+ return utf16resultLength;
+ }
+ memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
+
+ return utf16resultLength;
+}
+
+int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ GOwnPtr<GError> gerror;
+
+ GOwnPtr<char> utf8src;
+ utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ GOwnPtr<char> utf8result;
+ utf8result.set(g_utf8_strdown(utf8src.get(), -1));
+
+ long utf16resultLength = -1;
+ GOwnPtr<UChar> utf16result;
+ utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ if (utf16resultLength > resultLength) {
+ *error = true;
+ return utf16resultLength;
+ }
+ memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
+
+ return utf16resultLength;
+}
+
+int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+ *error = false;
+ GOwnPtr<GError> gerror;
+
+ GOwnPtr<char> utf8src;
+ utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ GOwnPtr<char> utf8result;
+ utf8result.set(g_utf8_strup(utf8src.get(), -1));
+
+ long utf16resultLength = -1;
+ GOwnPtr<UChar> utf16result;
+ utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
+ if (gerror) {
+ *error = true;
+ return -1;
+ }
+
+ if (utf16resultLength > resultLength) {
+ *error = true;
+ return utf16resultLength;
+ }
+ memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
+
+ return utf16resultLength;
+}
+
+Direction direction(UChar32 c)
+{
+ PangoBidiType type = pango_bidi_type_for_unichar(c);
+ switch (type) {
+ case PANGO_BIDI_TYPE_L:
+ return LeftToRight;
+ case PANGO_BIDI_TYPE_R:
+ return RightToLeft;
+ case PANGO_BIDI_TYPE_AL:
+ return RightToLeftArabic;
+ case PANGO_BIDI_TYPE_LRE:
+ return LeftToRightEmbedding;
+ case PANGO_BIDI_TYPE_RLE:
+ return RightToLeftEmbedding;
+ case PANGO_BIDI_TYPE_LRO:
+ return LeftToRightOverride;
+ case PANGO_BIDI_TYPE_RLO:
+ return RightToLeftOverride;
+ case PANGO_BIDI_TYPE_PDF:
+ return PopDirectionalFormat;
+ case PANGO_BIDI_TYPE_EN:
+ return EuropeanNumber;
+ case PANGO_BIDI_TYPE_AN:
+ return ArabicNumber;
+ case PANGO_BIDI_TYPE_ES:
+ return EuropeanNumberSeparator;
+ case PANGO_BIDI_TYPE_ET:
+ return EuropeanNumberTerminator;
+ case PANGO_BIDI_TYPE_CS:
+ return CommonNumberSeparator;
+ case PANGO_BIDI_TYPE_NSM:
+ return NonSpacingMark;
+ case PANGO_BIDI_TYPE_BN:
+ return BoundaryNeutral;
+ case PANGO_BIDI_TYPE_B:
+ return BlockSeparator;
+ case PANGO_BIDI_TYPE_S:
+ return SegmentSeparator;
+ case PANGO_BIDI_TYPE_WS:
+ return WhiteSpaceNeutral;
+ default:
+ return OtherNeutral;
+ }
+}
+
+int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+ GOwnPtr<char> utf8a;
+ GOwnPtr<char> utf8b;
+
+ utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0));
+ utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0));
+
+ GOwnPtr<char> foldedA;
+ GOwnPtr<char> foldedB;
+
+ foldedA.set(g_utf8_casefold(utf8a.get(), -1));
+ foldedB.set(g_utf8_casefold(utf8b.get(), -1));
+
+ // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu
+ // from the ICU docs:
+ // "Compare two strings case-insensitively using full case folding.
+ // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))."
+ //
+ // So it looks like we don't need the full g_utf8_collate here,
+ // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes).
+ // As there is no direct equivalent to this icu function in GLib, for now
+ // we'll use g_utf8_collate():
+
+ return g_utf8_collate(foldedA.get(), foldedB.get());
+}
+
+}
+}
--- /dev/null
+/*
+ * 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) 2008 Jürg Billeter <j@bitron.ch>
+ * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.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.
+ *
+ */
+
+#ifndef UnicodeGLib_h
+#define UnicodeGLib_h
+
+#include "UnicodeMacrosFromICU.h"
+#include <wtf/GOwnPtr.h>
+
+#include <glib.h>
+#include <pango/pango.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef uint16_t UChar;
+typedef int32_t UChar32;
+
+namespace WTF {
+namespace Unicode {
+
+enum Direction {
+ LeftToRight,
+ RightToLeft,
+ EuropeanNumber,
+ EuropeanNumberSeparator,
+ EuropeanNumberTerminator,
+ ArabicNumber,
+ CommonNumberSeparator,
+ BlockSeparator,
+ SegmentSeparator,
+ WhiteSpaceNeutral,
+ OtherNeutral,
+ LeftToRightEmbedding,
+ LeftToRightOverride,
+ RightToLeftArabic,
+ RightToLeftEmbedding,
+ RightToLeftOverride,
+ PopDirectionalFormat,
+ NonSpacingMark,
+ BoundaryNeutral
+};
+
+enum DecompositionType {
+ DecompositionNone,
+ DecompositionCanonical,
+ DecompositionCompat,
+ DecompositionCircle,
+ DecompositionFinal,
+ DecompositionFont,
+ DecompositionFraction,
+ DecompositionInitial,
+ DecompositionIsolated,
+ DecompositionMedial,
+ DecompositionNarrow,
+ DecompositionNoBreak,
+ DecompositionSmall,
+ DecompositionSquare,
+ DecompositionSub,
+ DecompositionSuper,
+ DecompositionVertical,
+ DecompositionWide,
+};
+
+enum CharCategory {
+ NoCategory = 0,
+ Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED),
+ Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER),
+ Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER),
+ Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER),
+ Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER),
+ Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER),
+
+ Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK),
+ Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK),
+ Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK),
+
+ Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER),
+ Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER),
+ Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER),
+
+ Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR),
+ Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR),
+ Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR),
+
+ Other_Control = U_MASK(G_UNICODE_CONTROL),
+ Other_Format = U_MASK(G_UNICODE_FORMAT),
+ Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE),
+ Other_Surrogate = U_MASK(G_UNICODE_SURROGATE),
+
+ Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION),
+ Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION),
+ Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION),
+ Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION),
+ Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION),
+
+ Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL),
+ Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL),
+ Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL),
+ Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL),
+
+ Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION),
+ Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION)
+};
+
+UChar32 foldCase(UChar32);
+
+int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
+
+int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
+
+inline UChar32 toLower(UChar32 c)
+{
+ return g_unichar_tolower(c);
+}
+
+inline UChar32 toUpper(UChar32 c)
+{
+ return g_unichar_toupper(c);
+}
+
+int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
+
+inline UChar32 toTitleCase(UChar32 c)
+{
+ return g_unichar_totitle(c);
+}
+
+inline bool isArabicChar(UChar32 c)
+{
+ return c >= 0x0600 && c <= 0x06FF;
+}
+
+inline bool isFormatChar(UChar32 c)
+{
+ return g_unichar_type(c) == G_UNICODE_FORMAT;
+}
+
+inline bool isSeparatorSpace(UChar32 c)
+{
+ return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR;
+}
+
+inline bool isPrintableChar(UChar32 c)
+{
+ return g_unichar_isprint(c);
+}
+
+inline bool isDigit(UChar32 c)
+{
+ return g_unichar_isdigit(c);
+}
+
+inline bool isPunct(UChar32 c)
+{
+ return g_unichar_ispunct(c);
+}
+
+inline bool hasLineBreakingPropertyComplexContext(UChar32 c)
+{
+ // FIXME
+ return false;
+}
+
+inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c)
+{
+ // FIXME
+ return false;
+}
+
+inline UChar32 mirroredChar(UChar32 c)
+{
+ gunichar mirror = 0;
+ g_unichar_get_mirror_char(c, &mirror);
+ return mirror;
+}
+
+inline CharCategory category(UChar32 c)
+{
+ if (c > 0xffff)
+ return NoCategory;
+
+ return (CharCategory) U_MASK(g_unichar_type(c));
+}
+
+Direction direction(UChar32);
+
+inline bool isLower(UChar32 c)
+{
+ return g_unichar_islower(c);
+}
+
+inline int digitValue(UChar32 c)
+{
+ return g_unichar_digit_value(c);
+}
+
+inline uint8_t combiningClass(UChar32 c)
+{
+ // FIXME
+ // return g_unichar_combining_class(c);
+ return 0;
+}
+
+inline DecompositionType decompositionType(UChar32 c)
+{
+ // FIXME
+ return DecompositionNone;
+}
+
+int umemcasecmp(const UChar*, const UChar*, int len);
+
+}
+}
+
+#endif
+
--- /dev/null
+/*
+ * 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) 2008 Jürg Billeter <j@bitron.ch>
+ * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.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.
+ *
+ */
+
+#ifndef UnicodeMacrosFromICU_h
+#define UnicodeMacrosFromICU_h
+
+// some defines from ICU
+
+#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
+#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
+#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
+#define U16_GET_SUPPLEMENTARY(lead, trail) \
+ (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET)
+
+#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
+#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
+
+#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
+#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
+#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
+#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
+
+#define U16_PREV(s, start, i, c) { \
+ (c)=(s)[--(i)]; \
+ if(U16_IS_TRAIL(c)) { \
+ uint16_t __c2; \
+ if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
+ --(i); \
+ (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
+ } \
+ } \
+}
+
+#define U16_NEXT(s, i, length, c) { \
+ (c)=(s)[(i)++]; \
+ if(U16_IS_LEAD(c)) { \
+ uint16_t __c2; \
+ if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
+ ++(i); \
+ (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
+ } \
+ } \
+}
+
+#define U_MASK(x) ((uint32_t)1<<(x))
+
+#endif
+
} \
}
+#define U16_PREV(s, start, i, c) { \
+ (c)=(s)[--(i)]; \
+ if(U16_IS_TRAIL(c)) { \
+ uint16_t __c2; \
+ if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
+ --(i); \
+ (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
+ } \
+ } \
+}
+
#define U_MASK(x) ((uint32_t)1<<(x))
namespace WTF {
#include "Assertions.h"
#include "Threading.h"
-#if !PLATFORM(WIN_CE)
+#if !PLATFORM(WINCE)
#include <windows.h>
#endif
return 0;
}
-void initializeMainThread()
+void initializeMainThreadPlatform()
{
if (threadingWindowHandle)
return;
- mainThreadFunctionQueueMutex();
-
WNDCLASSEX wcex;
memset(&wcex, 0, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
}
-} // namespace WebCore
+} // namespace WTF
namespace WTF {
-void scheduleDispatchFunctionsOnMainThread()
+void initializeMainThreadPlatform()
{
}
+void scheduleDispatchFunctionsOnMainThread()
+{
}
+
+} // namespace WTF
--- /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 "RegexCompiler.h"
+
+#include "RegexInterpreter.h"
+#include "RegexPattern.h"
+#include <wtf/Vector.h>
+
+#if ENABLE(YARR)
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+class CharacterClassConstructor {
+public:
+ CharacterClassConstructor(bool isCaseInsensitive = false)
+ : m_isCaseInsensitive(isCaseInsensitive)
+ {
+ }
+
+ void reset()
+ {
+ m_matches.clear();
+ m_ranges.clear();
+ m_matchesUnicode.clear();
+ m_rangesUnicode.clear();
+ }
+
+ void append(const CharacterClass* other)
+ {
+ for (size_t i = 0; i < other->m_matches.size(); ++i)
+ addSorted(m_matches, other->m_matches[i]);
+ for (size_t i = 0; i < other->m_ranges.size(); ++i)
+ addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end);
+ for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
+ addSorted(m_matchesUnicode, other->m_matchesUnicode[i]);
+ for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
+ addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end);
+ }
+
+ void putChar(UChar ch)
+ {
+ if (ch <= 0x7f) {
+ if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
+ addSorted(m_matches, toASCIIUpper(ch));
+ addSorted(m_matches, toASCIILower(ch));
+ } else
+ addSorted(m_matches, ch);
+ } else {
+ UChar upper, lower;
+ if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != (lower = Unicode::toLower(ch)))) {
+ addSorted(m_matchesUnicode, upper);
+ addSorted(m_matchesUnicode, lower);
+ } else
+ addSorted(m_matchesUnicode, ch);
+ }
+ }
+
+ // returns true if this character has another case, and 'ch' is the upper case form.
+ static inline bool isUnicodeUpper(UChar ch)
+ {
+ return ch != Unicode::toLower(ch);
+ }
+
+ // returns true if this character has another case, and 'ch' is the lower case form.
+ static inline bool isUnicodeLower(UChar ch)
+ {
+ return ch != Unicode::toUpper(ch);
+ }
+
+ void putRange(UChar lo, UChar hi)
+ {
+ 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) {
+ uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
+ addSortedRange(m_rangesUnicode, unicodeCurr, hi);
+
+ if (m_isCaseInsensitive) {
+ while (unicodeCurr <= hi) {
+ // If the upper bound of the range (hi) is 0xffff, the increments to
+ // unicodeCurr in this loop may take it to 0x10000. This is fine
+ // (if so we won't re-enter the loop, since the loop condition above
+ // will definitely fail) - but this does mean we cannot use a UChar
+ // to represent unicodeCurr, we must use a 32-bit value instead.
+ ASSERT(unicodeCurr <= 0xffff);
+
+ if (isUnicodeUpper(unicodeCurr)) {
+ UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
+ UChar lowerCaseRangeEnd = lowerCaseRangeBegin;
+ while ((++unicodeCurr <= hi) && isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == (lowerCaseRangeEnd + 1)))
+ lowerCaseRangeEnd++;
+ addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, lowerCaseRangeEnd);
+ } else if (isUnicodeLower(unicodeCurr)) {
+ UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr);
+ UChar upperCaseRangeEnd = upperCaseRangeBegin;
+ while ((++unicodeCurr <= hi) && isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == (upperCaseRangeEnd + 1)))
+ upperCaseRangeEnd++;
+ addSortedRange(m_rangesUnicode, upperCaseRangeBegin, upperCaseRangeEnd);
+ } else
+ ++unicodeCurr;
+ }
+ }
+ }
+ }
+
+ CharacterClass* charClass()
+ {
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_matches.append(m_matches);
+ characterClass->m_ranges.append(m_ranges);
+ characterClass->m_matchesUnicode.append(m_matchesUnicode);
+ characterClass->m_rangesUnicode.append(m_rangesUnicode);
+
+ reset();
+
+ return characterClass;
+ }
+
+private:
+ void 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 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;
+ }
+ ranges.insert(i, CharacterRange(lo, hi));
+ 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.
+ ranges.append(CharacterRange(lo, hi));
+ }
+
+ bool m_isCaseInsensitive;
+
+ Vector<UChar> m_matches;
+ Vector<CharacterRange> m_ranges;
+ Vector<UChar> m_matchesUnicode;
+ Vector<CharacterRange> m_rangesUnicode;
+};
+
+
+CharacterClass* newlineCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_matches.append('\n');
+ characterClass->m_matches.append('\r');
+ characterClass->m_matchesUnicode.append(0x2028);
+ characterClass->m_matchesUnicode.append(0x2029);
+
+ return characterClass;
+}
+
+CharacterClass* digitsCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_ranges.append(CharacterRange('0', '9'));
+
+ return characterClass;
+}
+
+CharacterClass* spacesCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_matches.append(' ');
+ characterClass->m_ranges.append(CharacterRange('\t', '\r'));
+ characterClass->m_matchesUnicode.append(0x00a0);
+ characterClass->m_matchesUnicode.append(0x1680);
+ characterClass->m_matchesUnicode.append(0x180e);
+ characterClass->m_matchesUnicode.append(0x2028);
+ characterClass->m_matchesUnicode.append(0x2029);
+ characterClass->m_matchesUnicode.append(0x202f);
+ characterClass->m_matchesUnicode.append(0x205f);
+ characterClass->m_matchesUnicode.append(0x3000);
+ characterClass->m_rangesUnicode.append(CharacterRange(0x2000, 0x200a));
+
+ return characterClass;
+}
+
+CharacterClass* wordcharCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_matches.append('_');
+ characterClass->m_ranges.append(CharacterRange('0', '9'));
+ characterClass->m_ranges.append(CharacterRange('A', 'Z'));
+ characterClass->m_ranges.append(CharacterRange('a', 'z'));
+
+ return characterClass;
+}
+
+CharacterClass* nondigitsCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_ranges.append(CharacterRange(0, '0' - 1));
+ characterClass->m_ranges.append(CharacterRange('9' + 1, 0x7f));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x80, 0xffff));
+
+ return characterClass;
+}
+
+CharacterClass* nonspacesCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_ranges.append(CharacterRange(0, '\t' - 1));
+ characterClass->m_ranges.append(CharacterRange('\r' + 1, ' ' - 1));
+ characterClass->m_ranges.append(CharacterRange(' ' + 1, 0x7f));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0x009f));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x00a1, 0x167f));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x1681, 0x180d));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x180f, 0x1fff));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x200b, 0x2027));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x202a, 0x202e));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x2030, 0x205e));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x2060, 0x2fff));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x3001, 0xffff));
+
+ return characterClass;
+}
+
+CharacterClass* nonwordcharCreate()
+{
+ CharacterClass* characterClass = new CharacterClass();
+
+ characterClass->m_matches.append('`');
+ characterClass->m_ranges.append(CharacterRange(0, '0' - 1));
+ characterClass->m_ranges.append(CharacterRange('9' + 1, 'A' - 1));
+ characterClass->m_ranges.append(CharacterRange('Z' + 1, '_' - 1));
+ characterClass->m_ranges.append(CharacterRange('z' + 1, 0x7f));
+ characterClass->m_rangesUnicode.append(CharacterRange(0x80, 0xffff));
+
+ return characterClass;
+}
+
+
+class RegexPatternConstructor {
+public:
+ RegexPatternConstructor(RegexPattern& pattern)
+ : m_pattern(pattern)
+ , m_characterClassConstructor(pattern.m_ignoreCase)
+ {
+ }
+
+ ~RegexPatternConstructor()
+ {
+ }
+
+ void reset()
+ {
+ m_pattern.reset();
+ m_characterClassConstructor.reset();
+ }
+
+ void assertionBOL()
+ {
+ m_alternative->m_terms.append(PatternTerm::BOL());
+ }
+ void assertionEOL()
+ {
+ m_alternative->m_terms.append(PatternTerm::EOL());
+ }
+ void assertionWordBoundary(bool invert)
+ {
+ m_alternative->m_terms.append(PatternTerm::WordBoundary(invert));
+ }
+
+ void atomPatternCharacter(UChar ch)
+ {
+ // We handle case-insensitive checking of unicode characters which do have both
+ // cases by handling them as if they were defined using a CharacterClass.
+ if (m_pattern.m_ignoreCase && !isASCII(ch) && (Unicode::toUpper(ch) != Unicode::toLower(ch))) {
+ atomCharacterClassBegin();
+ atomCharacterClassAtom(ch);
+ atomCharacterClassEnd();
+ } else
+ m_alternative->m_terms.append(PatternTerm(ch));
+ }
+
+ void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
+ {
+ switch (classID) {
+ case DigitClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), invert));
+ break;
+ case SpaceClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), invert));
+ break;
+ case WordClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), invert));
+ break;
+ case NewlineClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), invert));
+ break;
+ }
+ }
+
+ void atomCharacterClassBegin(bool invert = false)
+ {
+ m_invertCharacterClass = invert;
+ }
+
+ void atomCharacterClassAtom(UChar ch)
+ {
+ m_characterClassConstructor.putChar(ch);
+ }
+
+ void atomCharacterClassRange(UChar begin, UChar end)
+ {
+ m_characterClassConstructor.putRange(begin, end);
+ }
+
+ void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
+ {
+ ASSERT(classID != NewlineClassID);
+
+ switch (classID) {
+ case DigitClassID:
+ m_characterClassConstructor.append(invert ? m_pattern.nondigitsCharacterClass() : m_pattern.digitsCharacterClass());
+ break;
+
+ case SpaceClassID:
+ m_characterClassConstructor.append(invert ? m_pattern.nonspacesCharacterClass() : m_pattern.spacesCharacterClass());
+ break;
+
+ case WordClassID:
+ m_characterClassConstructor.append(invert ? m_pattern.nonwordcharCharacterClass() : m_pattern.wordcharCharacterClass());
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ void atomCharacterClassEnd()
+ {
+ CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
+ m_pattern.m_userCharacterClasses.append(newCharacterClass);
+ m_alternative->m_terms.append(PatternTerm(newCharacterClass, m_invertCharacterClass));
+ }
+
+ void atomParenthesesSubpatternBegin(bool capture = true)
+ {
+ unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
+ if (capture)
+ m_pattern.m_numSubpatterns++;
+
+ PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
+ m_pattern.m_disjunctions.append(parenthesesDisjunction);
+ m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture));
+ m_alternative = parenthesesDisjunction->addNewAlternative();
+ }
+
+ void atomParentheticalAssertionBegin(bool invert = false)
+ {
+ PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
+ m_pattern.m_disjunctions.append(parenthesesDisjunction);
+ m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert));
+ m_alternative = parenthesesDisjunction->addNewAlternative();
+ }
+
+ void atomParenthesesEnd()
+ {
+ ASSERT(m_alternative->m_parent);
+ ASSERT(m_alternative->m_parent->m_parent);
+ m_alternative = m_alternative->m_parent->m_parent;
+
+ m_alternative->lastTerm().parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
+ }
+
+ void atomBackReference(unsigned subpatternId)
+ {
+ ASSERT(subpatternId);
+ m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId);
+
+ if (subpatternId > m_pattern.m_numSubpatterns) {
+ m_alternative->m_terms.append(PatternTerm::ForwardReference());
+ return;
+ }
+
+ PatternAlternative* currentAlternative = m_alternative;
+ ASSERT(currentAlternative);
+
+ // Note to self: if we waited until the AST was baked, we could also remove forwards refs
+ while ((currentAlternative = currentAlternative->m_parent->m_parent)) {
+ PatternTerm& term = currentAlternative->lastTerm();
+ ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
+
+ if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.invertOrCapture && (subpatternId == term.subpatternId)) {
+ m_alternative->m_terms.append(PatternTerm::ForwardReference());
+ return;
+ }
+ }
+
+ m_alternative->m_terms.append(PatternTerm(subpatternId));
+ }
+
+ PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction)
+ {
+ PatternDisjunction* newDisjunction = new PatternDisjunction();
+
+ newDisjunction->m_parent = disjunction->m_parent;
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+ PatternAlternative* alternative = disjunction->m_alternatives[alt];
+ PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
+ for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
+ newAlternative->m_terms.append(copyTerm(alternative->m_terms[i]));
+ }
+
+ m_pattern.m_disjunctions.append(newDisjunction);
+ return newDisjunction;
+ }
+
+ PatternTerm copyTerm(PatternTerm& term)
+ {
+ if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion))
+ return PatternTerm(term);
+
+ PatternTerm termCopy = term;
+ termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction);
+ return termCopy;
+ }
+
+ void quantifyAtom(unsigned min, unsigned max, bool greedy)
+ {
+ ASSERT(min <= max);
+ ASSERT(m_alternative->m_terms.size());
+
+ if (!max) {
+ m_alternative->removeLastTerm();
+ return;
+ }
+
+ PatternTerm& term = m_alternative->lastTerm();
+ ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
+ ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
+
+ // For any assertion with a zero minimum, not matching is valid and has no effect,
+ // remove it. Otherwise, we need to match as least once, but there is no point
+ // matching more than once, so remove the quantifier. It is not entirely clear
+ // from the spec whether or not this behavior is correct, but I believe this
+ // matches Firefox. :-/
+ if (term.type == PatternTerm::TypeParentheticalAssertion) {
+ if (!min)
+ m_alternative->removeLastTerm();
+ return;
+ }
+
+ if (min == 0)
+ term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy);
+ else if (min == max)
+ term.quantify(min, QuantifierFixedCount);
+ else {
+ term.quantify(min, QuantifierFixedCount);
+ m_alternative->m_terms.append(copyTerm(term));
+ // NOTE: this term is interesting from an analysis perspective, in that it can be ignored.....
+ m_alternative->lastTerm().quantify((max == UINT_MAX) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
+ if (m_alternative->lastTerm().type == PatternTerm::TypeParenthesesSubpattern)
+ m_alternative->lastTerm().parentheses.isCopy = true;
+ }
+ }
+
+ void disjunction()
+ {
+ m_alternative = m_alternative->m_parent->addNewAlternative();
+ }
+
+ void regexBegin()
+ {
+ m_pattern.m_body = new PatternDisjunction();
+ m_alternative = m_pattern.m_body->addNewAlternative();
+ m_pattern.m_disjunctions.append(m_pattern.m_body);
+ }
+ void regexEnd()
+ {
+ }
+ void regexError()
+ {
+ }
+
+ unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
+ {
+ alternative->m_hasFixedSize = true;
+ unsigned currentInputPosition = initialInputPosition;
+
+ for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+ PatternTerm& term = alternative->m_terms[i];
+
+ switch (term.type) {
+ case PatternTerm::TypeAssertionBOL:
+ case PatternTerm::TypeAssertionEOL:
+ case PatternTerm::TypeAssertionWordBoundary:
+ term.inputPosition = currentInputPosition;
+ break;
+
+ case PatternTerm::TypeBackReference:
+ term.inputPosition = currentInputPosition;
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += RegexStackSpaceForBackTrackInfoBackReference;
+ alternative->m_hasFixedSize = false;
+ break;
+
+ case PatternTerm::TypeForwardReference:
+ break;
+
+ case PatternTerm::TypePatternCharacter:
+ term.inputPosition = currentInputPosition;
+ if (term.quantityType != QuantifierFixedCount) {
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += RegexStackSpaceForBackTrackInfoPatternCharacter;
+ alternative->m_hasFixedSize = false;
+ } else
+ currentInputPosition += term.quantityCount;
+ break;
+
+ case PatternTerm::TypeCharacterClass:
+ term.inputPosition = currentInputPosition;
+ if (term.quantityType != QuantifierFixedCount) {
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += RegexStackSpaceForBackTrackInfoCharacterClass;
+ alternative->m_hasFixedSize = false;
+ } else
+ currentInputPosition += term.quantityCount;
+ break;
+
+ case PatternTerm::TypeParenthesesSubpattern:
+ // Note: for fixed once parentheses we will ensure at least the minimum is available; others are on their own.
+ term.frameLocation = currentCallFrameSize;
+ if ((term.quantityCount == 1) && !term.parentheses.isCopy) {
+ if (term.quantityType == QuantifierFixedCount) {
+ currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
+ currentInputPosition += term.parentheses.disjunction->m_minimumSize;
+ } else {
+ currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesOnce;
+ currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
+ }
+ term.inputPosition = currentInputPosition;
+ } else {
+ term.inputPosition = currentInputPosition;
+ setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition);
+ currentCallFrameSize += RegexStackSpaceForBackTrackInfoParentheses;
+ }
+ // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
+ alternative->m_hasFixedSize = false;
+ break;
+
+ case PatternTerm::TypeParentheticalAssertion:
+ term.inputPosition = currentInputPosition;
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + RegexStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
+ break;
+ }
+ }
+
+ alternative->m_minimumSize = currentInputPosition - initialInputPosition;
+ return currentCallFrameSize;
+ }
+
+ unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition)
+ {
+ if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
+ initialCallFrameSize += RegexStackSpaceForBackTrackInfoAlternative;
+
+ unsigned minimumInputSize = UINT_MAX;
+ unsigned maximumCallFrameSize = 0;
+ bool hasFixedSize = true;
+
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+ PatternAlternative* alternative = disjunction->m_alternatives[alt];
+ unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
+ minimumInputSize = min(minimumInputSize, alternative->m_minimumSize);
+ maximumCallFrameSize = max(maximumCallFrameSize, currentAlternativeCallFrameSize);
+ hasFixedSize &= alternative->m_hasFixedSize;
+ }
+
+ ASSERT(minimumInputSize != UINT_MAX);
+ ASSERT(maximumCallFrameSize >= initialCallFrameSize);
+
+ disjunction->m_hasFixedSize = hasFixedSize;
+ disjunction->m_minimumSize = minimumInputSize;
+ disjunction->m_callFrameSize = maximumCallFrameSize;
+ return maximumCallFrameSize;
+ }
+
+ void setupOffsets()
+ {
+ setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
+ }
+
+private:
+ RegexPattern& m_pattern;
+ PatternAlternative* m_alternative;
+ CharacterClassConstructor m_characterClassConstructor;
+ bool m_invertCharacterClass;
+};
+
+
+const char* compileRegex(const UString& patternString, RegexPattern& pattern)
+{
+ RegexPatternConstructor constructor(pattern);
+
+ if (const char* error = parse(constructor, patternString))
+ return error;
+
+ // If the pattern contains illegal backreferences reset & reparse.
+ // Quoting Netscape's "What's new in JavaScript 1.2",
+ // "Note: if the number of left parentheses is less than the number specified
+ // in \#, the \# is taken as an octal escape as described in the next row."
+ if (pattern.containsIllegalBackReference()) {
+ unsigned numSubpatterns = pattern.m_numSubpatterns;
+
+ constructor.reset();
+#ifndef NDEBUG
+ const char* error =
+#endif
+ parse(constructor, patternString, numSubpatterns);
+
+ ASSERT(!error);
+ ASSERT(numSubpatterns == pattern.m_numSubpatterns);
+ }
+
+ constructor.setupOffsets();
+
+ return false;
+};
+
+
+} }
+
+#endif
--- /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 RegexCompiler_h
+#define RegexCompiler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(YARR)
+
+#include <wtf/unicode/Unicode.h>
+#include "RegexParser.h"
+#include "RegexPattern.h"
+
+namespace JSC { namespace Yarr {
+
+const char* compileRegex(const UString& patternString, RegexPattern& pattern);
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // RegexCompiler_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 "RegexInterpreter.h"
+
+#include "RegexCompiler.h"
+#include "RegexPattern.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+#if ENABLE(YARR)
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+class Interpreter {
+public:
+ struct ParenthesesDisjunctionContext;
+
+ struct BackTrackInfoPatternCharacter {
+ uintptr_t matchAmount;
+ };
+ struct BackTrackInfoCharacterClass {
+ uintptr_t matchAmount;
+ };
+ struct BackTrackInfoBackReference {
+ uintptr_t begin; // Not really needed for greedy quantifiers.
+ uintptr_t matchAmount; // Not really needed for fixed quantifiers.
+ };
+ struct BackTrackInfoAlternative {
+ uintptr_t offset;
+ };
+ struct BackTrackInfoParentheticalAssertion {
+ uintptr_t begin;
+ };
+ struct BackTrackInfoParenthesesOnce {
+ uintptr_t inParentheses;
+ };
+ struct BackTrackInfoParentheses {
+ uintptr_t matchAmount;
+ ParenthesesDisjunctionContext* lastContext;
+ uintptr_t prevBegin;
+ uintptr_t prevEnd;
+ };
+
+ static inline void appendParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack, ParenthesesDisjunctionContext* context)
+ {
+ context->next = backTrack->lastContext;
+ backTrack->lastContext = context;
+ ++backTrack->matchAmount;
+ }
+
+ static inline void popParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack)
+ {
+ ASSERT(backTrack->matchAmount);
+ ASSERT(backTrack->lastContext);
+ backTrack->lastContext = backTrack->lastContext->next;
+ --backTrack->matchAmount;
+ }
+
+ struct DisjunctionContext
+ {
+ DisjunctionContext()
+ : term(0)
+ {
+ }
+
+ void* operator new(size_t, void* where)
+ {
+ return where;
+ }
+
+ int term;
+ unsigned matchBegin;
+ unsigned matchEnd;
+ uintptr_t frame[1];
+ };
+
+ DisjunctionContext* allocDisjunctionContext(ByteDisjunction* disjunction)
+ {
+ return new(malloc(sizeof(DisjunctionContext) + (disjunction->m_frameSize - 1) * sizeof(uintptr_t))) DisjunctionContext();
+ }
+
+ void freeDisjunctionContext(DisjunctionContext* context)
+ {
+ free(context);
+ }
+
+ struct ParenthesesDisjunctionContext
+ {
+ ParenthesesDisjunctionContext(int* output, ByteTerm& term)
+ : next(0)
+ {
+ unsigned firstSubpatternId = term.atom.subpatternId;
+ unsigned numNestedSubpatterns = term.atom.parenthesesDisjunction->m_numSubpatterns;
+
+ for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) {
+ subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
+ output[(firstSubpatternId << 1) + i] = -1;
+ }
+
+ new(getDisjunctionContext(term)) DisjunctionContext();
+ }
+
+ void* operator new(size_t, void* where)
+ {
+ return where;
+ }
+
+ void restoreOutput(int* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns)
+ {
+ for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
+ output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
+ }
+
+ DisjunctionContext* getDisjunctionContext(ByteTerm& term)
+ {
+ return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
+ }
+
+ ParenthesesDisjunctionContext* next;
+ int subpatternBackup[1];
+ };
+
+ ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, int* output, ByteTerm& term)
+ {
+ return new(malloc(sizeof(ParenthesesDisjunctionContext) + (((term.atom.parenthesesDisjunction->m_numSubpatterns << 1) - 1) * sizeof(int)) + sizeof(DisjunctionContext) + (disjunction->m_frameSize - 1) * sizeof(uintptr_t))) ParenthesesDisjunctionContext(output, term);
+ }
+
+ void freeParenthesesDisjunctionContext(ParenthesesDisjunctionContext* context)
+ {
+ free(context);
+ }
+
+ class InputStream {
+ public:
+ InputStream(const UChar* input, unsigned start, unsigned length)
+ : input(input)
+ , pos(start)
+ , length(length)
+ {
+ }
+
+ void next()
+ {
+ ++pos;
+ }
+
+ void rewind(unsigned amount)
+ {
+ ASSERT(pos >= amount);
+ pos -= amount;
+ }
+
+ int read()
+ {
+ ASSERT(pos < length);
+ if (pos < length)
+ return input[pos];
+ return -1;
+ }
+
+ int readChecked(int position)
+ {
+ ASSERT(position < 0);
+ ASSERT((unsigned)-position <= pos);
+ unsigned p = pos + position;
+ ASSERT(p < length);
+ return input[p];
+ }
+
+ int reread(unsigned from)
+ {
+ ASSERT(from < length);
+ return input[from];
+ }
+
+ int prev()
+ {
+ ASSERT(!(pos > length));
+ if (pos && length)
+ return input[pos - 1];
+ return -1;
+ }
+
+ unsigned getPos()
+ {
+ return pos;
+ }
+
+ void setPos(unsigned p)
+ {
+ pos = p;
+ }
+
+ bool atStart()
+ {
+ return pos == 0;
+ }
+
+ bool atEnd()
+ {
+ return pos == length;
+ }
+
+ bool checkInput(int count)
+ {
+ if ((pos + count) <= length) {
+ pos += count;
+ return true;
+ } else
+ return false;
+ }
+
+ void uncheckInput(int count)
+ {
+ pos -= count;
+ }
+
+ bool atStart(int position)
+ {
+ return (pos + position) == 0;
+ }
+
+ bool atEnd(int position)
+ {
+ return (pos + position) == length;
+ }
+
+ private:
+ const UChar* input;
+ unsigned pos;
+ unsigned length;
+ };
+
+ bool testCharacterClass(CharacterClass* characterClass, int ch)
+ {
+ if (ch & 0xFF80) {
+ for (unsigned i = 0; i < characterClass->m_matchesUnicode.size(); ++i)
+ if (ch == characterClass->m_matchesUnicode[i])
+ return true;
+ for (unsigned i = 0; i < characterClass->m_rangesUnicode.size(); ++i)
+ if ((ch >= characterClass->m_rangesUnicode[i].begin) && (ch <= characterClass->m_rangesUnicode[i].end))
+ return true;
+ } else {
+ for (unsigned i = 0; i < characterClass->m_matches.size(); ++i)
+ if (ch == characterClass->m_matches[i])
+ return true;
+ for (unsigned i = 0; i < characterClass->m_ranges.size(); ++i)
+ if ((ch >= characterClass->m_ranges[i].begin) && (ch <= characterClass->m_ranges[i].end))
+ return true;
+ }
+
+ return false;
+ }
+
+ bool tryConsumeCharacter(int testChar)
+ {
+ if (input.atEnd())
+ return false;
+
+ int ch = input.read();
+
+ if (pattern->m_ignoreCase ? ((Unicode::toLower(testChar) == ch) || (Unicode::toUpper(testChar) == ch)) : (testChar == ch)) {
+ input.next();
+ return true;
+ }
+ return false;
+ }
+
+ bool checkCharacter(int testChar, int inputPosition)
+ {
+ return testChar == input.readChecked(inputPosition);
+ }
+
+ bool checkCasedCharacter(int loChar, int hiChar, int inputPosition)
+ {
+ int ch = input.readChecked(inputPosition);
+ return (loChar == ch) || (hiChar == ch);
+ }
+
+ bool tryConsumeCharacterClass(CharacterClass* characterClass, bool invert)
+ {
+ if (input.atEnd())
+ return false;
+
+ bool match = testCharacterClass(characterClass, input.read());
+
+ if (invert)
+ match = !match;
+
+ if (match) {
+ input.next();
+ return true;
+ }
+ return false;
+ }
+
+ bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition)
+ {
+ bool match = testCharacterClass(characterClass, input.readChecked(inputPosition));
+ return invert ? !match : match;
+ }
+
+ bool tryConsumeBackReference(int matchBegin, int matchEnd, int inputOffset)
+ {
+ int matchSize = matchEnd - matchBegin;
+
+ if (!input.checkInput(matchSize))
+ return false;
+
+ for (int i = 0; i < matchSize; ++i) {
+ if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) {
+ input.uncheckInput(matchSize);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool matchAssertionBOL(ByteTerm& term)
+ {
+ return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition - 1)));
+ }
+
+ bool matchAssertionEOL(ByteTerm& term)
+ {
+ if (term.inputPosition)
+ return (input.atEnd(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition)));
+ else
+ return (input.atEnd()) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.read()));
+ }
+
+ bool matchAssertionWordBoundary(ByteTerm& term)
+ {
+ bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition - 1));
+ bool readIsWordchar;
+ if (term.inputPosition)
+ readIsWordchar = !input.atEnd(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition));
+ else
+ readIsWordchar = !input.atEnd() && testCharacterClass(pattern->wordcharCharacterClass, input.read());
+
+ bool wordBoundary = prevIsWordchar != readIsWordchar;
+ return term.invert() ? !wordBoundary : wordBoundary;
+ }
+
+ bool backtrackPatternCharacter(ByteTerm& term, DisjunctionContext* context)
+ {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount:
+ break;
+
+ case QuantifierGreedy:
+ if (backTrack->matchAmount) {
+ --backTrack->matchAmount;
+ input.uncheckInput(1);
+ return true;
+ }
+ break;
+
+ case QuantifierNonGreedy:
+ if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+ ++backTrack->matchAmount;
+ if (checkCharacter(term.atom.patternCharacter, term.inputPosition - 1))
+ return true;
+ }
+ input.uncheckInput(backTrack->matchAmount);
+ break;
+ }
+
+ return false;
+ }
+
+ bool backtrackPatternCasedCharacter(ByteTerm& term, DisjunctionContext* context)
+ {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount:
+ break;
+
+ case QuantifierGreedy:
+ if (backTrack->matchAmount) {
+ --backTrack->matchAmount;
+ input.uncheckInput(1);
+ return true;
+ }
+ break;
+
+ case QuantifierNonGreedy:
+ if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+ ++backTrack->matchAmount;
+ if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition - 1))
+ return true;
+ }
+ input.uncheckInput(backTrack->matchAmount);
+ break;
+ }
+
+ return false;
+ }
+
+ bool matchCharacterClass(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeCharacterClass);
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount: {
+ for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
+ if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + matchAmount))
+ return false;
+ }
+ return true;
+ }
+
+ case QuantifierGreedy: {
+ unsigned matchAmount = 0;
+ while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+ if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) {
+ input.uncheckInput(1);
+ break;
+ }
+ ++matchAmount;
+ }
+ backTrack->matchAmount = matchAmount;
+
+ return true;
+ }
+
+ case QuantifierNonGreedy:
+ backTrack->matchAmount = 0;
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ bool backtrackCharacterClass(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeCharacterClass);
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount:
+ break;
+
+ case QuantifierGreedy:
+ if (backTrack->matchAmount) {
+ --backTrack->matchAmount;
+ input.uncheckInput(1);
+ return true;
+ }
+ break;
+
+ case QuantifierNonGreedy:
+ if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+ ++backTrack->matchAmount;
+ if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1))
+ return true;
+ }
+ input.uncheckInput(backTrack->matchAmount);
+ break;
+ }
+
+ return false;
+ }
+
+ bool matchBackReference(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeBackReference);
+ BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
+
+ int matchBegin = output[(term.atom.subpatternId << 1)];
+ int matchEnd = output[(term.atom.subpatternId << 1) + 1];
+ ASSERT((matchBegin == -1) == (matchEnd == -1));
+ ASSERT(matchBegin <= matchEnd);
+
+ if (matchBegin == matchEnd)
+ return true;
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount: {
+ backTrack->begin = input.getPos();
+ for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
+ if (!tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
+ input.setPos(backTrack->begin);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ case QuantifierGreedy: {
+ unsigned matchAmount = 0;
+ while ((matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition))
+ ++matchAmount;
+ backTrack->matchAmount = matchAmount;
+ return true;
+ }
+
+ case QuantifierNonGreedy:
+ backTrack->begin = input.getPos();
+ backTrack->matchAmount = 0;
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ bool backtrackBackReference(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeBackReference);
+ BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
+
+ int matchBegin = output[(term.atom.subpatternId << 1)];
+ int matchEnd = output[(term.atom.subpatternId << 1) + 1];
+ ASSERT((matchBegin == -1) == (matchEnd == -1));
+ ASSERT(matchBegin <= matchEnd);
+
+ if (matchBegin == matchEnd)
+ return false;
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount:
+ // for quantityCount == 1, could rewind.
+ input.setPos(backTrack->begin);
+ break;
+
+ case QuantifierGreedy:
+ if (backTrack->matchAmount) {
+ --backTrack->matchAmount;
+ input.rewind(matchEnd - matchBegin);
+ return true;
+ }
+ break;
+
+ case QuantifierNonGreedy:
+ if ((backTrack->matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
+ ++backTrack->matchAmount;
+ return true;
+ } else
+ input.setPos(backTrack->begin);
+ break;
+ }
+
+ return false;
+ }
+
+ void recordParenthesesMatch(ByteTerm& term, ParenthesesDisjunctionContext* context)
+ {
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1)] = context->getDisjunctionContext(term)->matchBegin + term.inputPosition;
+ output[(subpatternId << 1) + 1] = context->getDisjunctionContext(term)->matchEnd + term.inputPosition;
+ }
+ }
+ void resetMatches(ByteTerm& term, ParenthesesDisjunctionContext* context)
+ {
+ unsigned firstSubpatternId = term.atom.subpatternId;
+ unsigned count = term.atom.parenthesesDisjunction->m_numSubpatterns;
+ context->restoreOutput(output, firstSubpatternId, count);
+ }
+ void resetAssertionMatches(ByteTerm& term)
+ {
+ unsigned firstSubpatternId = term.atom.subpatternId;
+ unsigned count = term.atom.parenthesesDisjunction->m_numSubpatterns;
+ for (unsigned i = 0; i < (count << 1); ++i)
+ output[(firstSubpatternId << 1) + i] = -1;
+ }
+ bool parenthesesDoBacktrack(ByteTerm& term, BackTrackInfoParentheses* backTrack)
+ {
+ while (backTrack->matchAmount) {
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+
+ if (matchDisjunction(term.atom.parenthesesDisjunction, context->getDisjunctionContext(term), true))
+ return true;
+
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ popParenthesesDisjunctionContext(backTrack);
+ }
+
+ return false;
+ }
+
+ bool matchParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierGreedy: {
+ // set this speculatively; if we get to the parens end this will be true.
+ backTrack->inParentheses = 1;
+ break;
+ }
+ case QuantifierNonGreedy: {
+ backTrack->inParentheses = 0;
+ context->term += term.atom.parenthesesWidth;
+ return true;
+ }
+ case QuantifierFixedCount:
+ break;
+ }
+
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1)] = input.getPos() + term.inputPosition;
+ }
+
+ return true;
+ }
+
+ bool matchParenthesesOnceEnd(ByteTerm& term, DisjunctionContext*)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
+ ASSERT(term.atom.quantityCount == 1);
+
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1) + 1] = input.getPos() + term.inputPosition;
+ }
+ return true;
+ }
+
+ bool backtrackParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1)] = -1;
+ output[(subpatternId << 1) + 1] = -1;
+ }
+
+ switch (term.atom.quantityType) {
+ case QuantifierGreedy:
+ // if we backtrack to this point, there is another chance - try matching nothing.
+ ASSERT(backTrack->inParentheses);
+ backTrack->inParentheses = 0;
+ context->term += term.atom.parenthesesWidth;
+ return true;
+ case QuantifierNonGreedy:
+ ASSERT(backTrack->inParentheses);
+ case QuantifierFixedCount:
+ break;
+ }
+
+ return false;
+ }
+
+ bool backtrackParenthesesOnceEnd(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+ switch (term.atom.quantityType) {
+ case QuantifierGreedy:
+ if (!backTrack->inParentheses) {
+ context->term -= term.atom.parenthesesWidth;
+ return false;
+ }
+ case QuantifierNonGreedy:
+ if (!backTrack->inParentheses) {
+ // now try to match the parens; set this speculatively.
+ backTrack->inParentheses = 1;
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1) + 1] = input.getPos() + term.inputPosition;
+ }
+ context->term -= term.atom.parenthesesWidth;
+ return true;
+ }
+ case QuantifierFixedCount:
+ break;
+ }
+
+ return false;
+ }
+
+ bool matchParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+ backTrack->begin = input.getPos();
+ return true;
+ }
+
+ bool matchParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+ input.setPos(backTrack->begin);
+
+ // We've reached the end of the parens; if they are inverted, this is failure.
+ if (term.invert()) {
+ context->term -= term.atom.parenthesesWidth;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool backtrackParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
+ ASSERT(term.atom.quantityCount == 1);
+
+ // We've failed to match parens; if they are inverted, this is win!
+ if (term.invert()) {
+ context->term += term.atom.parenthesesWidth;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool backtrackParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
+ ASSERT(term.atom.quantityCount == 1);
+
+ BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+ input.setPos(backTrack->begin);
+
+ context->term -= term.atom.parenthesesWidth;
+ return false;
+ }
+
+ bool matchParentheses(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
+
+ BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
+
+ unsigned subpatternId = term.atom.subpatternId;
+ ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
+
+ backTrack->prevBegin = output[(subpatternId << 1)];
+ backTrack->prevEnd = output[(subpatternId << 1) + 1];
+
+ backTrack->matchAmount = 0;
+ backTrack->lastContext = 0;
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount: {
+ // While we haven't yet reached our fixed limit,
+ while (backTrack->matchAmount < term.atom.quantityCount) {
+ // Try to do a match, and it it succeeds, add it to the list.
+ ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+ if (matchDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
+ appendParenthesesDisjunctionContext(backTrack, context);
+ else {
+ // The match failed; try to find an alternate point to carry on from.
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ if (!parenthesesDoBacktrack(term, backTrack))
+ return false;
+ }
+ }
+
+ ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+ recordParenthesesMatch(term, context);
+ return true;
+ }
+
+ case QuantifierGreedy: {
+ while (backTrack->matchAmount < term.atom.quantityCount) {
+ ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+ if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
+ appendParenthesesDisjunctionContext(backTrack, context);
+ else {
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ break;
+ }
+ }
+
+ if (backTrack->matchAmount) {
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+ recordParenthesesMatch(term, context);
+ }
+ return true;
+ }
+
+ case QuantifierNonGreedy:
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ // Rules for backtracking differ depending on whether this is greedy or non-greedy.
+ //
+ // Greedy matches never should try just adding more - you should already have done
+ // the 'more' cases. Always backtrack, at least a leetle bit. However cases where
+ // you backtrack an item off the list needs checking, since we'll never have matched
+ // the one less case. Tracking forwards, still add as much as possible.
+ //
+ // Non-greedy, we've already done the one less case, so don't match on popping.
+ // We haven't done the one more case, so always try to add that.
+ //
+ bool backtrackParentheses(ByteTerm& term, DisjunctionContext* context)
+ {
+ ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
+
+ BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
+
+ if (term.capture()) {
+ unsigned subpatternId = term.atom.subpatternId;
+ output[(subpatternId << 1)] = backTrack->prevBegin;
+ output[(subpatternId << 1) + 1] = backTrack->prevEnd;
+ }
+
+ ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
+
+ switch (term.atom.quantityType) {
+ case QuantifierFixedCount: {
+ ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+
+ ParenthesesDisjunctionContext* context = 0;
+
+ if (!parenthesesDoBacktrack(term, backTrack))
+ return false;
+
+ // While we haven't yet reached our fixed limit,
+ while (backTrack->matchAmount < term.atom.quantityCount) {
+ // Try to do a match, and it it succeeds, add it to the list.
+ context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+ if (matchDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
+ appendParenthesesDisjunctionContext(backTrack, context);
+ else {
+ // The match failed; try to find an alternate point to carry on from.
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ if (!parenthesesDoBacktrack(term, backTrack))
+ return false;
+ }
+ }
+
+ ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+ context = backTrack->lastContext;
+ recordParenthesesMatch(term, context);
+ return true;
+ }
+
+ case QuantifierGreedy: {
+ if (!backTrack->matchAmount)
+ return false;
+
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+ if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true)) {
+ while (backTrack->matchAmount < term.atom.quantityCount) {
+ ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+ if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
+ appendParenthesesDisjunctionContext(backTrack, context);
+ else {
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ break;
+ }
+ }
+ } else {
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ popParenthesesDisjunctionContext(backTrack);
+ }
+
+ if (backTrack->matchAmount) {
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+ recordParenthesesMatch(term, context);
+ }
+ return true;
+ }
+
+ case QuantifierNonGreedy: {
+ // If we've not reached the limit, try to add one more match.
+ if (backTrack->matchAmount < term.atom.quantityCount) {
+ ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+ if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term))) {
+ appendParenthesesDisjunctionContext(backTrack, context);
+ recordParenthesesMatch(term, context);
+ return true;
+ } else {
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ }
+ }
+
+ // Nope - okay backtrack looking for an alternative.
+ while (backTrack->matchAmount) {
+ ParenthesesDisjunctionContext* context = backTrack->lastContext;
+ if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true)) {
+ // successful backtrack! we're back in the game!
+ if (backTrack->matchAmount) {
+ context = backTrack->lastContext;
+ recordParenthesesMatch(term, context);
+ }
+ return true;
+ }
+
+ // pop a match off the stack
+ resetMatches(term, context);
+ freeParenthesesDisjunctionContext(context);
+ popParenthesesDisjunctionContext(backTrack);
+ }
+
+ return false;
+ }
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+#define MATCH_NEXT() { ++context->term; goto matchAgain; }
+#define BACKTRACK() { --context->term; goto backtrack; }
+#define currentTerm() (disjunction->terms[context->term])
+ bool matchDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
+ {
+ if (btrack)
+ BACKTRACK();
+
+ context->matchBegin = input.getPos();
+ context->term = 0;
+
+ matchAgain:
+ ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
+
+ switch (currentTerm().type) {
+ case ByteTerm::TypeSubpatternBegin:
+ MATCH_NEXT();
+ case ByteTerm::TypeSubpatternEnd:
+ context->matchEnd = input.getPos();
+ return true;
+
+ case ByteTerm::TypeBodyAlternativeBegin:
+ MATCH_NEXT();
+ case ByteTerm::TypeBodyAlternativeDisjunction:
+ case ByteTerm::TypeBodyAlternativeEnd:
+ context->matchEnd = input.getPos();
+ return true;
+
+ case ByteTerm::TypeAlternativeBegin:
+ MATCH_NEXT();
+ case ByteTerm::TypeAlternativeDisjunction:
+ case ByteTerm::TypeAlternativeEnd: {
+ int offset = currentTerm().alternative.end;
+ BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
+ backTrack->offset = offset;
+ context->term += offset;
+ MATCH_NEXT();
+ }
+
+ case ByteTerm::TypeAssertionBOL:
+ if (matchAssertionBOL(currentTerm()))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeAssertionEOL:
+ if (matchAssertionEOL(currentTerm()))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeAssertionWordBoundary:
+ if (matchAssertionWordBoundary(currentTerm()))
+ MATCH_NEXT();
+ BACKTRACK();
+
+ case ByteTerm::TypePatternCharacterOnce:
+ case ByteTerm::TypePatternCharacterFixed: {
+ for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
+ if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + matchAmount))
+ BACKTRACK();
+ }
+ MATCH_NEXT();
+ }
+ case ByteTerm::TypePatternCharacterGreedy: {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+ unsigned matchAmount = 0;
+ while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
+ if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - 1)) {
+ input.uncheckInput(1);
+ break;
+ }
+ ++matchAmount;
+ }
+ backTrack->matchAmount = matchAmount;
+
+ MATCH_NEXT();
+ }
+ case ByteTerm::TypePatternCharacterNonGreedy: {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+ backTrack->matchAmount = 0;
+ MATCH_NEXT();
+ }
+
+ case ByteTerm::TypePatternCasedCharacterOnce:
+ case ByteTerm::TypePatternCasedCharacterFixed: {
+ for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
+ if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + matchAmount))
+ BACKTRACK();
+ }
+ MATCH_NEXT();
+ }
+ case ByteTerm::TypePatternCasedCharacterGreedy: {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+ unsigned matchAmount = 0;
+ while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
+ if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - 1)) {
+ input.uncheckInput(1);
+ break;
+ }
+ ++matchAmount;
+ }
+ backTrack->matchAmount = matchAmount;
+
+ MATCH_NEXT();
+ }
+ case ByteTerm::TypePatternCasedCharacterNonGreedy: {
+ BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+ backTrack->matchAmount = 0;
+ MATCH_NEXT();
+ }
+
+ case ByteTerm::TypeCharacterClass:
+ if (matchCharacterClass(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeBackReference:
+ if (matchBackReference(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpattern:
+ if (matchParentheses(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpatternOnceBegin:
+ if (matchParenthesesOnceBegin(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpatternOnceEnd:
+ if (matchParenthesesOnceEnd(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParentheticalAssertionBegin:
+ if (matchParentheticalAssertionBegin(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParentheticalAssertionEnd:
+ if (matchParentheticalAssertionEnd(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+
+ case ByteTerm::TypeCheckInput:
+ if (input.checkInput(currentTerm().checkInputCount))
+ MATCH_NEXT();
+ BACKTRACK();
+ }
+
+ // We should never fall-through to here.
+ ASSERT_NOT_REACHED();
+
+ backtrack:
+ ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
+
+ switch (currentTerm().type) {
+ case ByteTerm::TypeSubpatternBegin:
+ return false;
+ case ByteTerm::TypeSubpatternEnd:
+ ASSERT_NOT_REACHED();
+
+ case ByteTerm::TypeBodyAlternativeBegin:
+ case ByteTerm::TypeBodyAlternativeDisjunction: {
+ int offset = currentTerm().alternative.next;
+ context->term += offset;
+ if (offset > 0)
+ MATCH_NEXT();
+
+ if (input.atEnd())
+ return false;
+
+ input.next();
+ context->matchBegin = input.getPos();
+ MATCH_NEXT();
+ }
+ case ByteTerm::TypeBodyAlternativeEnd:
+ ASSERT_NOT_REACHED();
+
+ case ByteTerm::TypeAlternativeBegin:
+ case ByteTerm::TypeAlternativeDisjunction: {
+ int offset = currentTerm().alternative.next;
+ context->term += offset;
+ if (offset > 0)
+ MATCH_NEXT();
+ BACKTRACK();
+ }
+ case ByteTerm::TypeAlternativeEnd: {
+ // We should never backtrack back into an alternative of the main body of the regex.
+ BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
+ unsigned offset = backTrack->offset;
+ context->term -= offset;
+ BACKTRACK();
+ }
+
+ case ByteTerm::TypeAssertionBOL:
+ case ByteTerm::TypeAssertionEOL:
+ case ByteTerm::TypeAssertionWordBoundary:
+ BACKTRACK();
+
+ case ByteTerm::TypePatternCharacterOnce:
+ case ByteTerm::TypePatternCharacterFixed:
+ case ByteTerm::TypePatternCharacterGreedy:
+ case ByteTerm::TypePatternCharacterNonGreedy:
+ if (backtrackPatternCharacter(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypePatternCasedCharacterOnce:
+ case ByteTerm::TypePatternCasedCharacterFixed:
+ case ByteTerm::TypePatternCasedCharacterGreedy:
+ case ByteTerm::TypePatternCasedCharacterNonGreedy:
+ if (backtrackPatternCasedCharacter(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeCharacterClass:
+ if (backtrackCharacterClass(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeBackReference:
+ if (backtrackBackReference(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpattern:
+ if (backtrackParentheses(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpatternOnceBegin:
+ if (backtrackParenthesesOnceBegin(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParenthesesSubpatternOnceEnd:
+ if (backtrackParenthesesOnceEnd(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParentheticalAssertionBegin:
+ if (backtrackParentheticalAssertionBegin(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+ case ByteTerm::TypeParentheticalAssertionEnd:
+ if (backtrackParentheticalAssertionEnd(currentTerm(), context))
+ MATCH_NEXT();
+ BACKTRACK();
+
+ case ByteTerm::TypeCheckInput:
+ input.uncheckInput(currentTerm().checkInputCount);
+ BACKTRACK();
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ bool matchNonZeroDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
+ {
+ if (matchDisjunction(disjunction, context, btrack)) {
+ while (context->matchBegin == context->matchEnd) {
+ if (!matchDisjunction(disjunction, context, true))
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ int interpret()
+ {
+ for (unsigned i = 0; i < ((pattern->m_body->m_numSubpatterns + 1) << 1); ++i)
+ output[i] = -1;
+
+ DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
+
+ if (matchDisjunction(pattern->m_body.get(), context)) {
+ output[0] = context->matchBegin;
+ output[1] = context->matchEnd;
+ }
+
+ freeDisjunctionContext(context);
+
+ return output[0];
+ }
+
+ Interpreter(BytecodePattern* pattern, int* output, const UChar* inputChar, unsigned start, unsigned length)
+ : pattern(pattern)
+ , output(output)
+ , input(inputChar, start, length)
+ {
+ }
+
+private:
+ BytecodePattern *pattern;
+ int* output;
+ InputStream input;
+};
+
+
+
+class ByteCompiler {
+ struct ParenthesesStackEntry {
+ unsigned beginTerm;
+ unsigned savedAlternativeIndex;
+ ParenthesesStackEntry(unsigned beginTerm, unsigned savedAlternativeIndex/*, unsigned subpatternId, bool capture = false*/)
+ : beginTerm(beginTerm)
+ , savedAlternativeIndex(savedAlternativeIndex)
+ {
+ }
+ };
+
+public:
+ ByteCompiler(RegexPattern& pattern)
+ : m_pattern(pattern)
+ {
+ bodyDisjunction = 0;
+ currentAlternativeIndex = 0;
+ }
+
+ BytecodePattern* compile()
+ {
+ regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize);
+ emitDisjunction(m_pattern.m_body);
+ regexEnd();
+
+ return new BytecodePattern(bodyDisjunction, m_allParenthesesInfo, m_pattern);
+ }
+
+ void checkInput(unsigned count)
+ {
+ bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
+ }
+
+ void assertionBOL(int inputPosition)
+ {
+ bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
+ }
+
+ void assertionEOL(int inputPosition)
+ {
+ bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
+ }
+
+ void assertionWordBoundary(bool invert, int inputPosition)
+ {
+ bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
+ }
+
+ void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+ {
+ if (m_pattern.m_ignoreCase) {
+ UChar lo = Unicode::toLower(ch);
+ UChar hi = Unicode::toUpper(ch);
+
+ if (lo != hi) {
+ bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityCount, quantityType));
+ return;
+ }
+ }
+
+ bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
+ }
+
+ void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+ {
+ bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
+
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+ }
+
+ void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+ {
+ ASSERT(subpatternId);
+
+ bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
+
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+ }
+
+ void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+ {
+ int beginTerm = bodyDisjunction->terms.size();
+
+ bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+ bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+ m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, currentAlternativeIndex));
+ currentAlternativeIndex = beginTerm + 1;
+ }
+
+ void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
+ {
+ int beginTerm = bodyDisjunction->terms.size();
+
+ bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, invert, 0));
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+ bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+ bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+ m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, currentAlternativeIndex));
+ currentAlternativeIndex = beginTerm + 1;
+ }
+
+ unsigned popParenthesesStack()
+ {
+ ASSERT(m_parenthesesStack.size());
+ int stackEnd = m_parenthesesStack.size() - 1;
+ unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
+ currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
+ m_parenthesesStack.shrink(stackEnd);
+
+ ASSERT(beginTerm < bodyDisjunction->terms.size());
+ ASSERT(currentAlternativeIndex < bodyDisjunction->terms.size());
+
+ return beginTerm;
+ }
+
+#ifndef NDEBUG
+ void dumpDisjunction(ByteDisjunction* disjunction)
+ {
+ printf("ByteDisjunction(%p):\n\t", disjunction);
+ for (unsigned i = 0; i < disjunction->terms.size(); ++i)
+ printf("{ %d } ", disjunction->terms[i].type);
+ printf("\n");
+ }
+#endif
+
+ void closeAlternative(int beginTerm)
+ {
+ int origBeginTerm = beginTerm;
+ ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
+ int endIndex = bodyDisjunction->terms.size();
+
+ unsigned frameLocation = bodyDisjunction->terms[beginTerm].frameLocation;
+
+ if (!bodyDisjunction->terms[beginTerm].alternative.next)
+ bodyDisjunction->terms.remove(beginTerm);
+ else {
+ while (bodyDisjunction->terms[beginTerm].alternative.next) {
+ beginTerm += bodyDisjunction->terms[beginTerm].alternative.next;
+ ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeDisjunction);
+ bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+ bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+ }
+
+ bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+ bodyDisjunction->terms.append(ByteTerm::AlternativeEnd());
+ bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+ }
+ }
+
+ void closeBodyAlternative()
+ {
+ int beginTerm = 0;
+ int origBeginTerm = 0;
+ ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
+ int endIndex = bodyDisjunction->terms.size();
+
+ unsigned frameLocation = bodyDisjunction->terms[beginTerm].frameLocation;
+
+ while (bodyDisjunction->terms[beginTerm].alternative.next) {
+ beginTerm += bodyDisjunction->terms[beginTerm].alternative.next;
+ ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeDisjunction);
+ bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+ bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+ }
+
+ bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+ bodyDisjunction->terms.append(ByteTerm::BodyAlternativeEnd());
+ bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+ }
+
+ void atomParenthesesEnd(bool doInline, unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
+ {
+ unsigned beginTerm = popParenthesesStack();
+ closeAlternative(beginTerm + 1);
+ unsigned endTerm = bodyDisjunction->terms.size();
+
+ bool isAssertion = bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin;
+ bool invertOrCapture = bodyDisjunction->terms[beginTerm].invertOrCapture;
+ unsigned subpatternId = bodyDisjunction->terms[beginTerm].atom.subpatternId;
+
+ bodyDisjunction->terms.append(ByteTerm(isAssertion ? ByteTerm::TypeParentheticalAssertionEnd : ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, invertOrCapture, inputPosition));
+ bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
+ bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
+ bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
+
+ if (doInline) {
+ bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+ bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+ bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
+ bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
+ } else {
+ ByteTerm& parenthesesBegin = bodyDisjunction->terms[beginTerm];
+ ASSERT(parenthesesBegin.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+
+ bool invertOrCapture = parenthesesBegin.invertOrCapture;
+ unsigned subpatternId = parenthesesBegin.atom.subpatternId;
+
+ unsigned numSubpatterns = lastSubpatternId - subpatternId + 1;
+ ByteDisjunction* parenthesesDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
+
+ parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
+ for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
+ parenthesesDisjunction->terms.append(bodyDisjunction->terms[termInParentheses]);
+ parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
+
+ bodyDisjunction->terms.shrink(beginTerm);
+
+ m_allParenthesesInfo.append(parenthesesDisjunction);
+ bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, invertOrCapture, inputPosition));
+
+ bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+ bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+ bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+ }
+ }
+
+ void regexBegin(unsigned numSubpatterns, unsigned callFrameSize)
+ {
+ bodyDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
+ bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin());
+ bodyDisjunction->terms[0].frameLocation = 0;
+ currentAlternativeIndex = 0;
+ }
+
+ void regexEnd()
+ {
+ closeBodyAlternative();
+ }
+
+ void alterantiveBodyDisjunction()
+ {
+ int newAlternativeIndex = bodyDisjunction->terms.size();
+ bodyDisjunction->terms[currentAlternativeIndex].alternative.next = newAlternativeIndex - currentAlternativeIndex;
+ bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction());
+
+ currentAlternativeIndex = newAlternativeIndex;
+ }
+
+ void alterantiveDisjunction()
+ {
+ int newAlternativeIndex = bodyDisjunction->terms.size();
+ bodyDisjunction->terms[currentAlternativeIndex].alternative.next = newAlternativeIndex - currentAlternativeIndex;
+ bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
+
+ currentAlternativeIndex = newAlternativeIndex;
+ }
+
+ void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
+ {
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+ unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
+
+ if (alt) {
+ if (disjunction == m_pattern.m_body)
+ alterantiveBodyDisjunction();
+ else
+ alterantiveDisjunction();
+ }
+
+ PatternAlternative* alternative = disjunction->m_alternatives[alt];
+ unsigned minimumSize = alternative->m_minimumSize;
+
+ ASSERT(minimumSize >= parenthesesInputCountAlreadyChecked);
+ unsigned countToCheck = minimumSize - parenthesesInputCountAlreadyChecked;
+ if (countToCheck)
+ checkInput(countToCheck);
+ currentCountAlreadyChecked += countToCheck;
+
+ for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+ PatternTerm& term = alternative->m_terms[i];
+
+ switch (term.type) {
+ case PatternTerm::TypeAssertionBOL:
+ assertionBOL(term.inputPosition - currentCountAlreadyChecked);
+ break;
+
+ case PatternTerm::TypeAssertionEOL:
+ assertionEOL(term.inputPosition - currentCountAlreadyChecked);
+ break;
+
+ case PatternTerm::TypeAssertionWordBoundary:
+ assertionWordBoundary(term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked);
+ break;
+
+ case PatternTerm::TypePatternCharacter:
+ atomPatternCharacter(term.patternCharacter, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+ break;
+
+ case PatternTerm::TypeCharacterClass:
+ atomCharacterClass(term.characterClass, term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+ break;
+
+ case PatternTerm::TypeBackReference:
+ atomBackReference(term.subpatternId, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+ break;
+
+ case PatternTerm::TypeForwardReference:
+ break;
+
+ case PatternTerm::TypeParenthesesSubpattern: {
+ unsigned disjunctionAlreadyCheckedCount = 0;
+ if ((term.quantityCount == 1) && !term.parentheses.isCopy) {
+ if (term.quantityType == QuantifierFixedCount) {
+ disjunctionAlreadyCheckedCount = term.parentheses.disjunction->m_minimumSize;
+ unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+ atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation);
+ emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, term.parentheses.disjunction->m_minimumSize);
+ atomParenthesesEnd(true, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
+ } else {
+ unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+ atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + RegexStackSpaceForBackTrackInfoParenthesesOnce);
+ emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
+ atomParenthesesEnd(true, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
+ }
+ } else {
+ unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+ atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0);
+ emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
+ atomParenthesesEnd(false, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
+ }
+ break;
+ }
+
+ case PatternTerm::TypeParentheticalAssertion: {
+ unsigned alternativeFrameLocation = term.inputPosition + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
+
+ atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation);
+ emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
+ atomParenthesesEnd(true, term.parentheses.lastSubpatternId, 0, term.frameLocation, term.quantityCount, term.quantityType);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+private:
+ RegexPattern& m_pattern;
+ ByteDisjunction* bodyDisjunction;
+ unsigned currentAlternativeIndex;
+ Vector<ParenthesesStackEntry> m_parenthesesStack;
+ Vector<ByteDisjunction*> m_allParenthesesInfo;
+};
+
+
+BytecodePattern* byteCompileRegex(const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
+{
+ RegexPattern pattern(ignoreCase, multiline);
+
+ if ((error = compileRegex(patternString, pattern)))
+ return 0;
+
+ numSubpatterns = pattern.m_numSubpatterns;
+
+ return ByteCompiler(pattern).compile();
+}
+
+int interpretRegex(BytecodePattern* regex, const UChar* input, unsigned start, unsigned length, int* output)
+{
+ return Interpreter(regex, output, input, start, length).interpret();
+}
+
+
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (RegexStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoPatternCharacter);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (RegexStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoCharacterClass);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (RegexStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoBackReference);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (RegexStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoAlternative);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (RegexStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheticalAssertion);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (RegexStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParenthesesOnce);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (RegexStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheses);
+
+
+} }
+
+#endif
--- /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 RegexInterpreter_h
+#define RegexInterpreter_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(YARR)
+
+#include <wtf/unicode/Unicode.h>
+#include "RegexParser.h"
+#include "RegexPattern.h"
+
+namespace JSC { namespace Yarr {
+
+class ByteDisjunction;
+
+struct ByteTerm {
+ enum Type {
+ TypeBodyAlternativeBegin,
+ TypeBodyAlternativeDisjunction,
+ TypeBodyAlternativeEnd,
+ TypeAlternativeBegin,
+ TypeAlternativeDisjunction,
+ TypeAlternativeEnd,
+ TypeSubpatternBegin,
+ TypeSubpatternEnd,
+ TypeAssertionBOL,
+ TypeAssertionEOL,
+ TypeAssertionWordBoundary,
+ TypePatternCharacterOnce,
+ TypePatternCharacterFixed,
+ TypePatternCharacterGreedy,
+ TypePatternCharacterNonGreedy,
+ TypePatternCasedCharacterOnce,
+ TypePatternCasedCharacterFixed,
+ TypePatternCasedCharacterGreedy,
+ TypePatternCasedCharacterNonGreedy,
+ TypeCharacterClass,
+ TypeBackReference,
+ TypeParenthesesSubpattern,
+ TypeParenthesesSubpatternOnceBegin,
+ TypeParenthesesSubpatternOnceEnd,
+ TypeParentheticalAssertionBegin,
+ TypeParentheticalAssertionEnd,
+ TypeCheckInput,
+ } type;
+ bool invertOrCapture;
+ union {
+ struct {
+ union {
+ UChar patternCharacter;
+ struct {
+ UChar lo;
+ UChar hi;
+ } casedCharacter;
+ CharacterClass* characterClass;
+ unsigned subpatternId;
+ };
+ union {
+ ByteDisjunction* parenthesesDisjunction;
+ unsigned parenthesesWidth;
+ };
+ QuantifierType quantityType;
+ unsigned quantityCount;
+ } atom;
+ struct {
+ int next;
+ int end;
+ } alternative;
+ unsigned checkInputCount;
+ };
+ unsigned frameLocation;
+ int inputPosition;
+
+ ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+ : frameLocation(frameLocation)
+ {
+ switch (quantityType) {
+ case QuantifierFixedCount:
+ type = (quantityCount == 1) ? ByteTerm::TypePatternCharacterOnce : ByteTerm::TypePatternCharacterFixed;
+ break;
+ case QuantifierGreedy:
+ type = ByteTerm::TypePatternCharacterGreedy;
+ break;
+ case QuantifierNonGreedy:
+ type = ByteTerm::TypePatternCharacterNonGreedy;
+ break;
+ }
+
+ atom.patternCharacter = ch;
+ atom.quantityType = quantityType;
+ atom.quantityCount = quantityCount;
+ inputPosition = inputPos;
+ }
+
+ ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+ : frameLocation(frameLocation)
+ {
+ switch (quantityType) {
+ case QuantifierFixedCount:
+ type = (quantityCount == 1) ? ByteTerm::TypePatternCasedCharacterOnce : ByteTerm::TypePatternCasedCharacterFixed;
+ break;
+ case QuantifierGreedy:
+ type = ByteTerm::TypePatternCasedCharacterGreedy;
+ break;
+ case QuantifierNonGreedy:
+ type = ByteTerm::TypePatternCasedCharacterNonGreedy;
+ break;
+ }
+
+ atom.casedCharacter.lo = lo;
+ atom.casedCharacter.hi = hi;
+ atom.quantityType = quantityType;
+ atom.quantityCount = quantityCount;
+ inputPosition = inputPos;
+ }
+
+ ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
+ : type(ByteTerm::TypeCharacterClass)
+ , invertOrCapture(invert)
+ {
+ atom.characterClass = characterClass;
+ atom.quantityType = QuantifierFixedCount;
+ atom.quantityCount = 1;
+ inputPosition = inputPos;
+ }
+
+ ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool invertOrCapture, int inputPos)
+ : type(type)
+ , invertOrCapture(invertOrCapture)
+ {
+ atom.subpatternId = subpatternId;
+ atom.parenthesesDisjunction = parenthesesInfo;
+ atom.quantityType = QuantifierFixedCount;
+ atom.quantityCount = 1;
+ inputPosition = inputPos;
+ }
+
+ ByteTerm(Type type, bool invert = false)
+ : type(type)
+ , invertOrCapture(invert)
+ {
+ atom.quantityType = QuantifierFixedCount;
+ atom.quantityCount = 1;
+ }
+
+ ByteTerm(Type type, unsigned subpatternId, bool invertOrCapture, int inputPos)
+ : type(type)
+ , invertOrCapture(invertOrCapture)
+ {
+ atom.subpatternId = subpatternId;
+ atom.quantityType = QuantifierFixedCount;
+ atom.quantityCount = 1;
+ inputPosition = inputPos;
+ }
+
+ static ByteTerm BOL(int inputPos)
+ {
+ ByteTerm term(TypeAssertionBOL);
+ term.inputPosition = inputPos;
+ return term;
+ }
+
+ static ByteTerm CheckInput(unsigned count)
+ {
+ ByteTerm term(TypeCheckInput);
+ term.checkInputCount = count;
+ return term;
+ }
+
+ static ByteTerm EOL(int inputPos)
+ {
+ ByteTerm term(TypeAssertionEOL);
+ term.inputPosition = inputPos;
+ return term;
+ }
+
+ static ByteTerm WordBoundary(bool invert, int inputPos)
+ {
+ ByteTerm term(TypeAssertionWordBoundary, invert);
+ term.inputPosition = inputPos;
+ return term;
+ }
+
+ static ByteTerm BackReference(unsigned subpatternId, int inputPos)
+ {
+ return ByteTerm(TypeBackReference, subpatternId, false, inputPos);
+ }
+
+ static ByteTerm BodyAlternativeBegin()
+ {
+ ByteTerm term(TypeBodyAlternativeBegin);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm BodyAlternativeDisjunction()
+ {
+ ByteTerm term(TypeBodyAlternativeDisjunction);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm BodyAlternativeEnd()
+ {
+ ByteTerm term(TypeBodyAlternativeEnd);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm AlternativeBegin()
+ {
+ ByteTerm term(TypeAlternativeBegin);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm AlternativeDisjunction()
+ {
+ ByteTerm term(TypeAlternativeDisjunction);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm AlternativeEnd()
+ {
+ ByteTerm term(TypeAlternativeEnd);
+ term.alternative.next = 0;
+ term.alternative.end = 0;
+ return term;
+ }
+
+ static ByteTerm SubpatternBegin()
+ {
+ return ByteTerm(TypeSubpatternBegin);
+ }
+
+ static ByteTerm SubpatternEnd()
+ {
+ return ByteTerm(TypeSubpatternEnd);
+ }
+
+ bool invert()
+ {
+ return invertOrCapture;
+ }
+
+ bool capture()
+ {
+ return invertOrCapture;
+ }
+};
+
+class ByteDisjunction {
+public:
+ ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
+ : m_numSubpatterns(numSubpatterns)
+ , m_frameSize(frameSize)
+ {
+ }
+
+ Vector<ByteTerm> terms;
+ unsigned m_numSubpatterns;
+ unsigned m_frameSize;
+};
+
+struct BytecodePattern {
+ BytecodePattern(ByteDisjunction* body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
+ : m_body(body)
+ , m_ignoreCase(pattern.m_ignoreCase)
+ , m_multiline(pattern.m_multiline)
+ {
+ newlineCharacterClass = pattern.newlineCharacterClass();
+ wordcharCharacterClass = pattern.wordcharCharacterClass();
+
+ m_allParenthesesInfo.append(allParenthesesInfo);
+ m_userCharacterClasses.append(pattern.m_userCharacterClasses);
+ // 'Steal' the RegexPattern's CharacterClasses! We clear its
+ // array, so that it won't delete them on destruction. We'll
+ // take responsibility for that.
+ pattern.m_userCharacterClasses.clear();
+ }
+
+ ~BytecodePattern()
+ {
+ deleteAllValues(m_allParenthesesInfo);
+ deleteAllValues(m_userCharacterClasses);
+ }
+
+ OwnPtr<ByteDisjunction> m_body;
+ bool m_ignoreCase;
+ bool m_multiline;
+
+ CharacterClass* newlineCharacterClass;
+ CharacterClass* wordcharCharacterClass;
+private:
+ Vector<ByteDisjunction*> m_allParenthesesInfo;
+ Vector<CharacterClass*> m_userCharacterClasses;
+};
+
+BytecodePattern* byteCompileRegex(const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
+int interpretRegex(BytecodePattern* v_regex, const UChar* input, unsigned start, unsigned length, int* output);
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // RegexInterpreter_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 "RegexJIT.h"
+
+#include "ASCIICType.h"
+#include "JSGlobalData.h"
+#include "LinkBuffer.h"
+#include "MacroAssembler.h"
+#include "RegexCompiler.h"
+
+#include "pcre.h" // temporary, remove when fallback is removed.
+
+#if ENABLE(YARR_JIT)
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+
+class RegexGenerator : private MacroAssembler {
+ friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
+
+#if PLATFORM_ARM_ARCH(7)
+ static const RegisterID input = ARM::r0;
+ static const RegisterID index = ARM::r1;
+ static const RegisterID length = ARM::r2;
+
+ static const RegisterID output = ARM::r4;
+ static const RegisterID regT0 = ARM::r5;
+ static const RegisterID regT1 = ARM::r6;
+
+ static const RegisterID returnRegister = ARM::r0;
+#endif
+#if PLATFORM(X86)
+ static const RegisterID input = X86::eax;
+ static const RegisterID index = X86::edx;
+ static const RegisterID length = X86::ecx;
+ static const RegisterID output = X86::edi;
+
+ static const RegisterID regT0 = X86::ebx;
+ static const RegisterID regT1 = X86::esi;
+
+ static const RegisterID returnRegister = X86::eax;
+#endif
+#if PLATFORM(X86_64)
+ static const RegisterID input = X86::edi;
+ static const RegisterID index = X86::esi;
+ static const RegisterID length = X86::edx;
+ static const RegisterID output = X86::ecx;
+
+ static const RegisterID regT0 = X86::eax;
+ static const RegisterID regT1 = X86::ebx;
+
+ static const RegisterID returnRegister = X86::eax;
+#endif
+
+ void optimizeAlternative(PatternAlternative* alternative)
+ {
+ if (!alternative->m_terms.size())
+ return;
+
+ for (unsigned i = 0; i < alternative->m_terms.size() - 1; ++i) {
+ PatternTerm& term = alternative->m_terms[i];
+ PatternTerm& nextTerm = alternative->m_terms[i + 1];
+
+ if ((term.type == PatternTerm::TypeCharacterClass)
+ && (term.quantityType == QuantifierFixedCount)
+ && (nextTerm.type == PatternTerm::TypePatternCharacter)
+ && (nextTerm.quantityType == QuantifierFixedCount)) {
+ PatternTerm termCopy = term;
+ alternative->m_terms[i] = nextTerm;
+ alternative->m_terms[i + 1] = termCopy;
+ }
+ }
+ }
+
+ void matchCharacterClassRange(RegisterID character, 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 = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
+
+ // generate code for all ranges before this one
+ if (which)
+ matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+
+ while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
+ matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex])));
+ ++*matchIndex;
+ }
+ failures.append(jump());
+
+ loOrAbove.link(this);
+ } else if (which) {
+ Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
+
+ matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+ failures.append(jump());
+
+ loOrAbove.link(this);
+ } else
+ failures.append(branch32(LessThan, character, Imm32((unsigned short)lo)));
+
+ while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
+ ++*matchIndex;
+
+ matchDest.append(branch32(LessThanOrEqual, 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 matchCharacterClass(RegisterID character, JumpList& matchDest, const CharacterClass* charClass)
+ {
+ Jump unicodeFail;
+ if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size()) {
+ Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f));
+
+ if (charClass->m_matchesUnicode.size()) {
+ for (unsigned i = 0; i < charClass->m_matchesUnicode.size(); ++i) {
+ UChar ch = charClass->m_matchesUnicode[i];
+ matchDest.append(branch32(Equal, character, Imm32(ch)));
+ }
+ }
+
+ if (charClass->m_rangesUnicode.size()) {
+ for (unsigned i = 0; i < charClass->m_rangesUnicode.size(); ++i) {
+ UChar lo = charClass->m_rangesUnicode[i].begin;
+ UChar hi = charClass->m_rangesUnicode[i].end;
+
+ Jump below = branch32(LessThan, character, Imm32(lo));
+ matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi)));
+ below.link(this);
+ }
+ }
+
+ unicodeFail = jump();
+ isAscii.link(this);
+ }
+
+ if (charClass->m_ranges.size()) {
+ unsigned matchIndex = 0;
+ JumpList failures;
+ matchCharacterClassRange(character, failures, matchDest, charClass->m_ranges.begin(), charClass->m_ranges.size(), &matchIndex, charClass->m_matches.begin(), charClass->m_matches.size());
+ while (matchIndex < charClass->m_matches.size())
+ matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass->m_matches[matchIndex++])));
+
+ failures.link(this);
+ } else if (charClass->m_matches.size()) {
+ // optimization: gather 'a','A' etc back together, can mask & test once.
+ Vector<char> matchesAZaz;
+
+ for (unsigned i = 0; i < charClass->m_matches.size(); ++i) {
+ char ch = charClass->m_matches[i];
+ if (m_pattern.m_ignoreCase) {
+ if (isASCIILower(ch)) {
+ matchesAZaz.append(ch);
+ continue;
+ }
+ if (isASCIIUpper(ch))
+ continue;
+ }
+ matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch)));
+ }
+
+ if (unsigned countAZaz = matchesAZaz.size()) {
+ or32(Imm32(32), character);
+ for (unsigned i = 0; i < countAZaz; ++i)
+ matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i])));
+ }
+ }
+
+ if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size())
+ unicodeFail.link(this);
+ }
+
+ // Jumps if input not available; will have (incorrectly) incremented already!
+ Jump jumpIfNoAvailableInput(unsigned countToCheck)
+ {
+ add32(Imm32(countToCheck), index);
+ return branch32(Above, index, length);
+ }
+
+ Jump jumpIfAvailableInput(unsigned countToCheck)
+ {
+ add32(Imm32(countToCheck), index);
+ return branch32(BelowOrEqual, index, length);
+ }
+
+ Jump checkInput()
+ {
+ return branch32(BelowOrEqual, index, length);
+ }
+
+ Jump atEndOfInput()
+ {
+ return branch32(Equal, index, length);
+ }
+
+ Jump notAtEndOfInput()
+ {
+ return branch32(NotEqual, index, length);
+ }
+
+ Jump jumpIfCharEquals(UChar ch, int inputPosition)
+ {
+ return branch16(Equal, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
+ }
+
+ Jump jumpIfCharNotEquals(UChar ch, int inputPosition)
+ {
+ return branch16(NotEqual, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
+ }
+
+ void readCharacter(int inputPosition, RegisterID reg)
+ {
+ load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
+ }
+
+ void storeToFrame(RegisterID reg, unsigned frameLocation)
+ {
+ poke(reg, frameLocation);
+ }
+
+ void storeToFrame(Imm32 imm, unsigned frameLocation)
+ {
+ poke(imm, frameLocation);
+ }
+
+ DataLabelPtr storeToFrameWithPatch(unsigned frameLocation)
+ {
+ return storePtrWithPatch(ImmPtr(0), Address(stackPointerRegister, frameLocation * sizeof(void*)));
+ }
+
+ void loadFromFrame(unsigned frameLocation, RegisterID reg)
+ {
+ peek(reg, frameLocation);
+ }
+
+ void loadFromFrameAndJump(unsigned frameLocation)
+ {
+ jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
+ }
+
+ struct AlternativeBacktrackRecord {
+ DataLabelPtr dataLabel;
+ Label backtrackLocation;
+
+ AlternativeBacktrackRecord(DataLabelPtr dataLabel, Label backtrackLocation)
+ : dataLabel(dataLabel)
+ , backtrackLocation(backtrackLocation)
+ {
+ }
+ };
+
+ struct TermGenerationState {
+ TermGenerationState(PatternDisjunction* disjunction, unsigned checkedTotal)
+ : disjunction(disjunction)
+ , checkedTotal(checkedTotal)
+ {
+ }
+
+ void resetAlternative()
+ {
+ isBackTrackGenerated = false;
+ alt = 0;
+ }
+ bool alternativeValid()
+ {
+ return alt < disjunction->m_alternatives.size();
+ }
+ void nextAlternative()
+ {
+ ++alt;
+ }
+ PatternAlternative* alternative()
+ {
+ return disjunction->m_alternatives[alt];
+ }
+
+ void resetTerm()
+ {
+ ASSERT(alternativeValid());
+ t = 0;
+ }
+ bool termValid()
+ {
+ ASSERT(alternativeValid());
+ return t < alternative()->m_terms.size();
+ }
+ void nextTerm()
+ {
+ ASSERT(alternativeValid());
+ ++t;
+ }
+ PatternTerm& term()
+ {
+ ASSERT(alternativeValid());
+ return alternative()->m_terms[t];
+ }
+
+ PatternTerm& lookaheadTerm()
+ {
+ ASSERT(alternativeValid());
+ ASSERT((t + 1) < alternative()->m_terms.size());
+ return alternative()->m_terms[t + 1];
+ }
+ bool isSinglePatternCharacterLookaheadTerm()
+ {
+ ASSERT(alternativeValid());
+ return ((t + 1) < alternative()->m_terms.size())
+ && (lookaheadTerm().type == PatternTerm::TypePatternCharacter)
+ && (lookaheadTerm().quantityType == QuantifierFixedCount)
+ && (lookaheadTerm().quantityCount == 1);
+ }
+
+ int inputOffset()
+ {
+ return term().inputPosition - checkedTotal;
+ }
+
+ void jumpToBacktrack(Jump jump, MacroAssembler* masm)
+ {
+ if (isBackTrackGenerated)
+ jump.linkTo(backtrackLabel, masm);
+ else
+ backTrackJumps.append(jump);
+ }
+ void jumpToBacktrack(JumpList& jumps, MacroAssembler* masm)
+ {
+ if (isBackTrackGenerated)
+ jumps.linkTo(backtrackLabel, masm);
+ else
+ backTrackJumps.append(jumps);
+ }
+ bool plantJumpToBacktrackIfExists(MacroAssembler* masm)
+ {
+ if (isBackTrackGenerated) {
+ masm->jump(backtrackLabel);
+ return true;
+ }
+ return false;
+ }
+ void addBacktrackJump(Jump jump)
+ {
+ backTrackJumps.append(jump);
+ }
+ void setBacktrackGenerated(Label label)
+ {
+ isBackTrackGenerated = true;
+ backtrackLabel = label;
+ }
+ void linkAlternativeBacktracks(MacroAssembler* masm)
+ {
+ isBackTrackGenerated = false;
+ backTrackJumps.link(masm);
+ }
+ void linkAlternativeBacktracksTo(Label label, MacroAssembler* masm)
+ {
+ isBackTrackGenerated = false;
+ backTrackJumps.linkTo(label, masm);
+ }
+ void propagateBacktrackingFrom(TermGenerationState& nestedParenthesesState, MacroAssembler* masm)
+ {
+ jumpToBacktrack(nestedParenthesesState.backTrackJumps, masm);
+ if (nestedParenthesesState.isBackTrackGenerated)
+ setBacktrackGenerated(nestedParenthesesState.backtrackLabel);
+ }
+
+ PatternDisjunction* disjunction;
+ int checkedTotal;
+ private:
+ unsigned alt;
+ unsigned t;
+ JumpList backTrackJumps;
+ Label backtrackLabel;
+ bool isBackTrackGenerated;
+ };
+
+ void generateAssertionBOL(TermGenerationState& state)
+ {
+ PatternTerm& term = state.term();
+
+ if (m_pattern.m_multiline) {
+ const RegisterID character = regT0;
+
+ JumpList matchDest;
+ if (!term.inputPosition)
+ matchDest.append(branch32(Equal, index, Imm32(state.checkedTotal)));
+
+ readCharacter(state.inputOffset() - 1, character);
+ matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
+ state.jumpToBacktrack(jump(), this);
+
+ matchDest.link(this);
+ } else {
+ // Erk, really should poison out these alternatives early. :-/
+ if (term.inputPosition)
+ state.jumpToBacktrack(jump(), this);
+ else
+ state.jumpToBacktrack(branch32(NotEqual, index, Imm32(state.checkedTotal)), this);
+ }
+ }
+
+ void generateAssertionEOL(TermGenerationState& state)
+ {
+ PatternTerm& term = state.term();
+
+ if (m_pattern.m_multiline) {
+ const RegisterID character = regT0;
+
+ JumpList matchDest;
+ if (term.inputPosition == state.checkedTotal)
+ matchDest.append(atEndOfInput());
+
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
+ state.jumpToBacktrack(jump(), this);
+
+ matchDest.link(this);
+ } else {
+ if (term.inputPosition == state.checkedTotal)
+ state.jumpToBacktrack(notAtEndOfInput(), this);
+ // Erk, really should poison out these alternatives early. :-/
+ else
+ state.jumpToBacktrack(jump(), this);
+ }
+ }
+
+ // Also falls though on nextIsNotWordChar.
+ void matchAssertionWordchar(TermGenerationState& state, JumpList& nextIsWordChar, JumpList& nextIsNotWordChar)
+ {
+ const RegisterID character = regT0;
+ PatternTerm& term = state.term();
+
+ if (term.inputPosition == state.checkedTotal)
+ nextIsNotWordChar.append(atEndOfInput());
+
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
+ }
+
+ void generateAssertionWordBoundary(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ PatternTerm& term = state.term();
+
+ Jump atBegin;
+ JumpList matchDest;
+ if (!term.inputPosition)
+ atBegin = branch32(Equal, index, Imm32(state.checkedTotal));
+ readCharacter(state.inputOffset() - 1, character);
+ matchCharacterClass(character, matchDest, m_pattern.wordcharCharacterClass());
+ if (!term.inputPosition)
+ atBegin.link(this);
+
+ // We fall through to here if the last character was not a wordchar.
+ JumpList nonWordCharThenWordChar;
+ JumpList nonWordCharThenNonWordChar;
+ if (term.invertOrCapture) {
+ matchAssertionWordchar(state, nonWordCharThenNonWordChar, nonWordCharThenWordChar);
+ nonWordCharThenWordChar.append(jump());
+ } else {
+ matchAssertionWordchar(state, nonWordCharThenWordChar, nonWordCharThenNonWordChar);
+ nonWordCharThenNonWordChar.append(jump());
+ }
+ state.jumpToBacktrack(nonWordCharThenNonWordChar, this);
+
+ // We jump here if the last character was a wordchar.
+ matchDest.link(this);
+ JumpList wordCharThenWordChar;
+ JumpList wordCharThenNonWordChar;
+ if (term.invertOrCapture) {
+ matchAssertionWordchar(state, wordCharThenNonWordChar, wordCharThenWordChar);
+ wordCharThenWordChar.append(jump());
+ } else {
+ matchAssertionWordchar(state, wordCharThenWordChar, wordCharThenNonWordChar);
+ // This can fall-though!
+ }
+
+ state.jumpToBacktrack(wordCharThenWordChar, this);
+
+ nonWordCharThenWordChar.link(this);
+ wordCharThenNonWordChar.link(this);
+ }
+
+ void generatePatternCharacterSingle(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ UChar ch = state.term().patternCharacter;
+
+ if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+ readCharacter(state.inputOffset(), character);
+ or32(Imm32(32), character);
+ state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
+ } else {
+ ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+ state.jumpToBacktrack(jumpIfCharNotEquals(ch, state.inputOffset()), this);
+ }
+ }
+
+ void generatePatternCharacterPair(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ UChar ch1 = state.term().patternCharacter;
+ UChar ch2 = state.lookaheadTerm().patternCharacter;
+
+ int mask = 0;
+ int chPair = ch1 | (ch2 << 16);
+
+ if (m_pattern.m_ignoreCase) {
+ if (isASCIIAlpha(ch1))
+ mask |= 32;
+ if (isASCIIAlpha(ch2))
+ mask |= 32 << 16;
+ }
+
+ if (mask) {
+ load32(BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), character);
+ or32(Imm32(mask), character);
+ state.jumpToBacktrack(branch32(NotEqual, character, Imm32(chPair | mask)), this);
+ } else
+ state.jumpToBacktrack(branch32(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)), this);
+ }
+
+ void generatePatternCharacterFixed(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+ UChar ch = term.patternCharacter;
+
+ move(index, countRegister);
+ sub32(Imm32(term.quantityCount), countRegister);
+
+ Label loop(this);
+ if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+ load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character);
+ or32(Imm32(32), character);
+ state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
+ } else {
+ ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+ state.jumpToBacktrack(branch16(NotEqual, BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), Imm32(ch)), this);
+ }
+ add32(Imm32(1), countRegister);
+ branch32(NotEqual, countRegister, index).linkTo(loop, this);
+ }
+
+ void generatePatternCharacterGreedy(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+ UChar ch = term.patternCharacter;
+
+ move(Imm32(0), countRegister);
+
+ JumpList failures;
+ Label loop(this);
+ failures.append(atEndOfInput());
+ if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+ readCharacter(state.inputOffset(), character);
+ or32(Imm32(32), character);
+ failures.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
+ } else {
+ ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+ failures.append(jumpIfCharNotEquals(ch, state.inputOffset()));
+ }
+ add32(Imm32(1), countRegister);
+ add32(Imm32(1), index);
+ branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this);
+ failures.append(jump());
+
+ Label backtrackBegin(this);
+ loadFromFrame(term.frameLocation, countRegister);
+ state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
+ sub32(Imm32(1), countRegister);
+ sub32(Imm32(1), index);
+
+ failures.link(this);
+
+ storeToFrame(countRegister, term.frameLocation);
+
+ state.setBacktrackGenerated(backtrackBegin);
+ }
+
+ void generatePatternCharacterNonGreedy(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+ UChar ch = term.patternCharacter;
+
+ move(Imm32(0), countRegister);
+
+ Jump firstTimeDoNothing = jump();
+
+ Label hardFail(this);
+ sub32(countRegister, index);
+ state.jumpToBacktrack(jump(), this);
+
+ Label backtrackBegin(this);
+ loadFromFrame(term.frameLocation, countRegister);
+
+ atEndOfInput().linkTo(hardFail, this);
+ branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail);
+ if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+ readCharacter(state.inputOffset(), character);
+ or32(Imm32(32), character);
+ branch32(NotEqual, character, Imm32(Unicode::toLower(ch))).linkTo(hardFail, this);
+ } else {
+ ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+ jumpIfCharNotEquals(ch, state.inputOffset()).linkTo(hardFail, this);
+ }
+
+ add32(Imm32(1), countRegister);
+ add32(Imm32(1), index);
+
+ firstTimeDoNothing.link(this);
+ storeToFrame(countRegister, term.frameLocation);
+
+ state.setBacktrackGenerated(backtrackBegin);
+ }
+
+ void generateCharacterClassSingle(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ PatternTerm& term = state.term();
+
+ JumpList matchDest;
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, matchDest, term.characterClass);
+
+ if (term.invertOrCapture)
+ state.jumpToBacktrack(matchDest, this);
+ else {
+ state.jumpToBacktrack(jump(), this);
+ matchDest.link(this);
+ }
+ }
+
+ void generateCharacterClassFixed(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+
+ move(index, countRegister);
+ sub32(Imm32(term.quantityCount), countRegister);
+
+ Label loop(this);
+ JumpList matchDest;
+ load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character);
+ matchCharacterClass(character, matchDest, term.characterClass);
+
+ if (term.invertOrCapture)
+ state.jumpToBacktrack(matchDest, this);
+ else {
+ state.jumpToBacktrack(jump(), this);
+ matchDest.link(this);
+ }
+
+ add32(Imm32(1), countRegister);
+ branch32(NotEqual, countRegister, index).linkTo(loop, this);
+ }
+
+ void generateCharacterClassGreedy(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+
+ move(Imm32(0), countRegister);
+
+ JumpList failures;
+ Label loop(this);
+ failures.append(atEndOfInput());
+
+ if (term.invertOrCapture) {
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, failures, term.characterClass);
+ } else {
+ JumpList matchDest;
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, matchDest, term.characterClass);
+ failures.append(jump());
+ matchDest.link(this);
+ }
+
+ add32(Imm32(1), countRegister);
+ add32(Imm32(1), index);
+ branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this);
+ failures.append(jump());
+
+ Label backtrackBegin(this);
+ loadFromFrame(term.frameLocation, countRegister);
+ state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
+ sub32(Imm32(1), countRegister);
+ sub32(Imm32(1), index);
+
+ failures.link(this);
+
+ storeToFrame(countRegister, term.frameLocation);
+
+ state.setBacktrackGenerated(backtrackBegin);
+ }
+
+ void generateCharacterClassNonGreedy(TermGenerationState& state)
+ {
+ const RegisterID character = regT0;
+ const RegisterID countRegister = regT1;
+ PatternTerm& term = state.term();
+
+ move(Imm32(0), countRegister);
+
+ Jump firstTimeDoNothing = jump();
+
+ Label hardFail(this);
+ sub32(countRegister, index);
+ state.jumpToBacktrack(jump(), this);
+
+ Label backtrackBegin(this);
+ loadFromFrame(term.frameLocation, countRegister);
+
+ atEndOfInput().linkTo(hardFail, this);
+ branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail);
+
+ JumpList matchDest;
+ readCharacter(state.inputOffset(), character);
+ matchCharacterClass(character, matchDest, term.characterClass);
+
+ if (term.invertOrCapture)
+ matchDest.linkTo(hardFail, this);
+ else {
+ jump(hardFail);
+ matchDest.link(this);
+ }
+
+ add32(Imm32(1), countRegister);
+ add32(Imm32(1), index);
+
+ firstTimeDoNothing.link(this);
+ storeToFrame(countRegister, term.frameLocation);
+
+ state.setBacktrackGenerated(backtrackBegin);
+ }
+
+ void generateParenthesesDisjunction(PatternTerm& parenthesesTerm, TermGenerationState& state, unsigned alternativeFrameLocation)
+ {
+ ASSERT((parenthesesTerm.type == PatternTerm::TypeParenthesesSubpattern) || (parenthesesTerm.type == PatternTerm::TypeParentheticalAssertion));
+ ASSERT(parenthesesTerm.quantityCount == 1);
+
+ PatternDisjunction* disjunction = parenthesesTerm.parentheses.disjunction;
+ unsigned preCheckedCount = ((parenthesesTerm.quantityType == QuantifierFixedCount) && (parenthesesTerm.type != PatternTerm::TypeParentheticalAssertion)) ? disjunction->m_minimumSize : 0;
+
+ if (disjunction->m_alternatives.size() == 1) {
+ state.resetAlternative();
+ ASSERT(state.alternativeValid());
+ PatternAlternative* alternative = state.alternative();
+ optimizeAlternative(alternative);
+
+ int countToCheck = alternative->m_minimumSize - preCheckedCount;
+ if (countToCheck) {
+ ASSERT((parenthesesTerm.type == PatternTerm::TypeParentheticalAssertion) || (parenthesesTerm.quantityType != QuantifierFixedCount));
+
+ // FIXME: This is quite horrible. The call to 'plantJumpToBacktrackIfExists'
+ // will be forced to always trampoline into here, just to decrement the index.
+ // Ick.
+ Jump skip = jump();
+
+ Label backtrackBegin(this);
+ sub32(Imm32(countToCheck), index);
+ state.addBacktrackJump(jump());
+
+ skip.link(this);
+
+ state.setBacktrackGenerated(backtrackBegin);
+
+ state.jumpToBacktrack(jumpIfNoAvailableInput(countToCheck), this);
+ state.checkedTotal += countToCheck;
+ }
+
+ for (state.resetTerm(); state.termValid(); state.nextTerm())
+ generateTerm(state);
+
+ state.checkedTotal -= countToCheck;
+ } else {
+ JumpList successes;
+
+ for (state.resetAlternative(); state.alternativeValid(); state.nextAlternative()) {
+
+ PatternAlternative* alternative = state.alternative();
+ optimizeAlternative(alternative);
+
+ ASSERT(alternative->m_minimumSize >= preCheckedCount);
+ int countToCheck = alternative->m_minimumSize - preCheckedCount;
+ if (countToCheck) {
+ state.addBacktrackJump(jumpIfNoAvailableInput(countToCheck));
+ state.checkedTotal += countToCheck;
+ }
+
+ for (state.resetTerm(); state.termValid(); state.nextTerm())
+ generateTerm(state);
+
+ // Matched an alternative.
+ DataLabelPtr dataLabel = storeToFrameWithPatch(alternativeFrameLocation);
+ successes.append(jump());
+
+ // Alternative did not match.
+ Label backtrackLocation(this);
+
+ // Can we backtrack the alternative? - if so, do so. If not, just fall through to the next one.
+ state.plantJumpToBacktrackIfExists(this);
+
+ state.linkAlternativeBacktracks(this);
+
+ if (countToCheck) {
+ sub32(Imm32(countToCheck), index);
+ state.checkedTotal -= countToCheck;
+ }
+
+ m_backtrackRecords.append(AlternativeBacktrackRecord(dataLabel, backtrackLocation));
+ }
+ // We fall through to here when the last alternative fails.
+ // Add a backtrack out of here for the parenthese handling code to link up.
+ state.addBacktrackJump(jump());
+
+ // Generate a trampoline for the parens code to backtrack to, to retry the
+ // next alternative.
+ state.setBacktrackGenerated(label());
+ loadFromFrameAndJump(alternativeFrameLocation);
+
+ // FIXME: both of the above hooks are a little inefficient, in that you
+ // may end up trampolining here, just to trampoline back out to the
+ // parentheses code, or vice versa. We can probably eliminate a jump
+ // by restructuring, but coding this way for now for simplicity during
+ // development.
+
+ successes.link(this);
+ }
+ }
+
+ void generateParenthesesSingle(TermGenerationState& state)
+ {
+ const RegisterID indexTemporary = regT0;
+ PatternTerm& term = state.term();
+ PatternDisjunction* disjunction = term.parentheses.disjunction;
+ ASSERT(term.quantityCount == 1);
+
+ unsigned preCheckedCount = ((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount)) ? disjunction->m_minimumSize : 0;
+
+ unsigned parenthesesFrameLocation = term.frameLocation;
+ unsigned alternativeFrameLocation = parenthesesFrameLocation;
+ if (term.quantityType != QuantifierFixedCount)
+ alternativeFrameLocation += RegexStackSpaceForBackTrackInfoParenthesesOnce;
+
+ // optimized case - no capture & no quantifier can be handled in a light-weight manner.
+ if (!term.invertOrCapture && (term.quantityType == QuantifierFixedCount)) {
+ TermGenerationState parenthesesState(disjunction, state.checkedTotal);
+ generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
+ // this expects that any backtracks back out of the parentheses will be in the
+ // parenthesesState's backTrackJumps vector, and that if they need backtracking
+ // they will have set an entry point on the parenthesesState's backtrackLabel.
+ state.propagateBacktrackingFrom(parenthesesState, this);
+ } else {
+ Jump nonGreedySkipParentheses;
+ Label nonGreedyTryParentheses;
+ if (term.quantityType == QuantifierGreedy)
+ storeToFrame(Imm32(1), parenthesesFrameLocation);
+ else if (term.quantityType == QuantifierNonGreedy) {
+ storeToFrame(Imm32(0), parenthesesFrameLocation);
+ nonGreedySkipParentheses = jump();
+ nonGreedyTryParentheses = label();
+ storeToFrame(Imm32(1), parenthesesFrameLocation);
+ }
+
+ // store the match start index
+ if (term.invertOrCapture) {
+ int inputOffset = state.inputOffset() - preCheckedCount;
+ if (inputOffset) {
+ move(index, indexTemporary);
+ add32(Imm32(inputOffset), indexTemporary);
+ store32(indexTemporary, Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
+ } else
+ store32(index, Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
+ }
+
+ // generate the body of the parentheses
+ TermGenerationState parenthesesState(disjunction, state.checkedTotal);
+ generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
+
+ // store the match end index
+ if (term.invertOrCapture) {
+ int inputOffset = state.inputOffset();
+ if (inputOffset) {
+ move(index, indexTemporary);
+ add32(Imm32(state.inputOffset()), indexTemporary);
+ store32(indexTemporary, Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
+ } else
+ store32(index, Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
+ }
+ Jump success = jump();
+
+ // A failure AFTER the parens jumps here
+ Label backtrackFromAfterParens(this);
+
+ if (term.quantityType == QuantifierGreedy) {
+ // If this is zero we have now tested with both with and without the parens.
+ loadFromFrame(parenthesesFrameLocation, indexTemporary);
+ state.jumpToBacktrack(branchTest32(Zero, indexTemporary), this);
+ } else if (term.quantityType == QuantifierNonGreedy) {
+ // If this is zero we have now tested with both with and without the parens.
+ loadFromFrame(parenthesesFrameLocation, indexTemporary);
+ branchTest32(Zero, indexTemporary).linkTo(nonGreedyTryParentheses, this);
+ }
+
+ parenthesesState.plantJumpToBacktrackIfExists(this);
+ // A failure WITHIN the parens jumps here
+ parenthesesState.linkAlternativeBacktracks(this);
+ if (term.invertOrCapture) {
+ store32(Imm32(-1), Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
+ store32(Imm32(-1), Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
+ }
+
+ if (term.quantityType == QuantifierGreedy)
+ storeToFrame(Imm32(0), parenthesesFrameLocation);
+ else
+ state.jumpToBacktrack(jump(), this);
+
+ state.setBacktrackGenerated(backtrackFromAfterParens);
+ if (term.quantityType == QuantifierNonGreedy)
+ nonGreedySkipParentheses.link(this);
+ success.link(this);
+ }
+ }
+
+ void generateParentheticalAssertion(TermGenerationState& state)
+ {
+ PatternTerm& term = state.term();
+ PatternDisjunction* disjunction = term.parentheses.disjunction;
+ ASSERT(term.quantityCount == 1);
+ ASSERT(term.quantityType == QuantifierFixedCount);
+
+ unsigned parenthesesFrameLocation = term.frameLocation;
+ unsigned alternativeFrameLocation = parenthesesFrameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
+
+ int countCheckedAfterAssertion = state.checkedTotal - term.inputPosition;
+
+ if (term.invertOrCapture) {
+ // Inverted case
+ storeToFrame(index, parenthesesFrameLocation);
+
+ state.checkedTotal -= countCheckedAfterAssertion;
+ if (countCheckedAfterAssertion)
+ sub32(Imm32(countCheckedAfterAssertion), index);
+
+ TermGenerationState parenthesesState(disjunction, state.checkedTotal);
+ generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
+ // Success! - which means - Fail!
+ loadFromFrame(parenthesesFrameLocation, index);
+ state.jumpToBacktrack(jump(), this);
+
+ // And fail means success.
+ parenthesesState.linkAlternativeBacktracks(this);
+ loadFromFrame(parenthesesFrameLocation, index);
+
+ state.checkedTotal += countCheckedAfterAssertion;
+ } else {
+ // Normal case
+ storeToFrame(index, parenthesesFrameLocation);
+
+ state.checkedTotal -= countCheckedAfterAssertion;
+ if (countCheckedAfterAssertion)
+ sub32(Imm32(countCheckedAfterAssertion), index);
+
+ TermGenerationState parenthesesState(disjunction, state.checkedTotal);
+ generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
+ // Success! - which means - Success!
+ loadFromFrame(parenthesesFrameLocation, index);
+ Jump success = jump();
+
+ parenthesesState.linkAlternativeBacktracks(this);
+ loadFromFrame(parenthesesFrameLocation, index);
+ state.jumpToBacktrack(jump(), this);
+
+ success.link(this);
+
+ state.checkedTotal += countCheckedAfterAssertion;
+ }
+ }
+
+ void generateTerm(TermGenerationState& state)
+ {
+ PatternTerm& term = state.term();
+
+ switch (term.type) {
+ case PatternTerm::TypeAssertionBOL:
+ generateAssertionBOL(state);
+ break;
+
+ case PatternTerm::TypeAssertionEOL:
+ generateAssertionEOL(state);
+ break;
+
+ case PatternTerm::TypeAssertionWordBoundary:
+ generateAssertionWordBoundary(state);
+ break;
+
+ case PatternTerm::TypePatternCharacter:
+ switch (term.quantityType) {
+ case QuantifierFixedCount:
+ if (term.quantityCount == 1) {
+ if (state.isSinglePatternCharacterLookaheadTerm() && (state.lookaheadTerm().inputPosition == (term.inputPosition + 1))) {
+ generatePatternCharacterPair(state);
+ state.nextTerm();
+ } else
+ generatePatternCharacterSingle(state);
+ } else
+ generatePatternCharacterFixed(state);
+ break;
+ case QuantifierGreedy:
+ generatePatternCharacterGreedy(state);
+ break;
+ case QuantifierNonGreedy:
+ generatePatternCharacterNonGreedy(state);
+ break;
+ }
+ break;
+
+ case PatternTerm::TypeCharacterClass:
+ switch (term.quantityType) {
+ case QuantifierFixedCount:
+ if (term.quantityCount == 1)
+ generateCharacterClassSingle(state);
+ else
+ generateCharacterClassFixed(state);
+ break;
+ case QuantifierGreedy:
+ generateCharacterClassGreedy(state);
+ break;
+ case QuantifierNonGreedy:
+ generateCharacterClassNonGreedy(state);
+ break;
+ }
+ break;
+
+ case PatternTerm::TypeBackReference:
+ m_generationFailed = true;
+ break;
+
+ case PatternTerm::TypeForwardReference:
+ break;
+
+ case PatternTerm::TypeParenthesesSubpattern:
+ if ((term.quantityCount == 1) && !term.parentheses.isCopy)
+ generateParenthesesSingle(state);
+ else
+ m_generationFailed = true;
+ break;
+
+ case PatternTerm::TypeParentheticalAssertion:
+ generateParentheticalAssertion(state);
+ break;
+ }
+ }
+
+ void generateDisjunction(PatternDisjunction* disjunction)
+ {
+ TermGenerationState state(disjunction, 0);
+ state.resetAlternative();
+
+ // Plant a check to see if there is sufficient input available to run the first alternative.
+ // Jumping back to the label 'firstAlternative' will get to this check, jumping to
+ // 'firstAlternativeInputChecked' will jump directly to matching the alternative having
+ // skipped this check.
+
+ Label firstAlternative(this);
+
+ // check availability for the next alternative
+ int countCheckedForCurrentAlternative = 0;
+ int countToCheckForFirstAlternative = 0;
+ bool hasShorterAlternatives = false;
+ JumpList notEnoughInputForPreviousAlternative;
+
+ if (state.alternativeValid()) {
+ PatternAlternative* alternative = state.alternative();
+ countToCheckForFirstAlternative = alternative->m_minimumSize;
+ state.checkedTotal += countToCheckForFirstAlternative;
+ if (countToCheckForFirstAlternative)
+ notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForFirstAlternative));
+ countCheckedForCurrentAlternative = countToCheckForFirstAlternative;
+ }
+
+ Label firstAlternativeInputChecked(this);
+
+ while (state.alternativeValid()) {
+ // Track whether any alternatives are shorter than the first one.
+ hasShorterAlternatives = hasShorterAlternatives || (countCheckedForCurrentAlternative < countToCheckForFirstAlternative);
+
+ PatternAlternative* alternative = state.alternative();
+ optimizeAlternative(alternative);
+
+ for (state.resetTerm(); state.termValid(); state.nextTerm())
+ generateTerm(state);
+
+ // If we get here, the alternative matched.
+ if (m_pattern.m_body->m_callFrameSize)
+ addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+
+ ASSERT(index != returnRegister);
+ if (m_pattern.m_body->m_hasFixedSize) {
+ move(index, returnRegister);
+ if (alternative->m_minimumSize)
+ sub32(Imm32(alternative->m_minimumSize), returnRegister);
+ } else
+ pop(returnRegister);
+ store32(index, Address(output, 4));
+ store32(returnRegister, output);
+
+ generateReturn();
+
+ state.nextAlternative();
+
+ // if there are any more alternatives, plant the check for input before looping.
+ if (state.alternativeValid()) {
+ PatternAlternative* nextAlternative = state.alternative();
+ int countToCheckForNextAlternative = nextAlternative->m_minimumSize;
+
+ if (countCheckedForCurrentAlternative > countToCheckForNextAlternative) { // CASE 1: current alternative was longer than the next one.
+ // If we get here, there the last input checked failed.
+ notEnoughInputForPreviousAlternative.link(this);
+
+ // Check if sufficent input available to run the next alternative
+ notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForNextAlternative - countCheckedForCurrentAlternative));
+ // We are now in the correct state to enter the next alternative; this add is only required
+ // to mirror and revert operation of the sub32, just below.
+ add32(Imm32(countCheckedForCurrentAlternative - countToCheckForNextAlternative), index);
+
+ // If we get here, there the last input checked passed.
+ state.linkAlternativeBacktracks(this);
+ // No need to check if we can run the next alternative, since it is shorter -
+ // just update index.
+ sub32(Imm32(countCheckedForCurrentAlternative - countToCheckForNextAlternative), index);
+ } else if (countCheckedForCurrentAlternative < countToCheckForNextAlternative) { // CASE 2: next alternative is longer than the current one.
+ // If we get here, there the last input checked failed.
+ // If there is insufficient input to run the current alternative, and the next alternative is longer,
+ // then there is definitely not enough input to run it - don't even check. Just adjust index, as if
+ // we had checked.
+ notEnoughInputForPreviousAlternative.link(this);
+ add32(Imm32(countToCheckForNextAlternative - countCheckedForCurrentAlternative), index);
+ notEnoughInputForPreviousAlternative.append(jump());
+
+ // The next alternative is longer than the current one; check the difference.
+ state.linkAlternativeBacktracks(this);
+ notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForNextAlternative - countCheckedForCurrentAlternative));
+ } else { // CASE 3: Both alternatives are the same length.
+ ASSERT(countCheckedForCurrentAlternative == countToCheckForNextAlternative);
+
+ // If the next alterative is the same length as this one, then no need to check the input -
+ // if there was sufficent input to run the current alternative then there is sufficient
+ // input to run the next one; if not, there isn't.
+ state.linkAlternativeBacktracks(this);
+ }
+
+ state.checkedTotal -= countCheckedForCurrentAlternative;
+ countCheckedForCurrentAlternative = countToCheckForNextAlternative;
+ state.checkedTotal += countCheckedForCurrentAlternative;
+ }
+ }
+
+ // If we get here, all Alternatives failed...
+
+ state.checkedTotal -= countCheckedForCurrentAlternative;
+
+ // How much more input need there be to be able to retry from the first alternative?
+ // examples:
+ // /yarr_jit/ or /wrec|pcre/
+ // In these examples we need check for one more input before looping.
+ // /yarr_jit|pcre/
+ // In this case we need check for 5 more input to loop (+4 to allow for the first alterative
+ // being four longer than the last alternative checked, and another +1 to effectively move
+ // the start position along by one).
+ // /yarr|rules/ or /wrec|notsomuch/
+ // In these examples, provided that there was sufficient input to have just been matching for
+ // the second alternative we can loop without checking for available input (since the second
+ // alternative is longer than the first). In the latter example we need to decrement index
+ // (by 4) so the start position is only progressed by 1 from the last iteration.
+ int incrementForNextIter = (countToCheckForFirstAlternative - countCheckedForCurrentAlternative) + 1;
+
+ // First, deal with the cases where there was sufficient input to try the last alternative.
+ if (incrementForNextIter > 0) // We need to check for more input anyway, fall through to the checking below.
+ state.linkAlternativeBacktracks(this);
+ else if (m_pattern.m_body->m_hasFixedSize && !incrementForNextIter) // No need to update anything, link these backtracks straight to the to pof the loop!
+ state.linkAlternativeBacktracksTo(firstAlternativeInputChecked, this);
+ else { // no need to check the input, but we do have some bookkeeping to do first.
+ state.linkAlternativeBacktracks(this);
+
+ // Where necessary update our preserved start position.
+ if (!m_pattern.m_body->m_hasFixedSize) {
+ move(index, regT0);
+ sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
+ poke(regT0, m_pattern.m_body->m_callFrameSize);
+ }
+
+ // Update index if necessary, and loop (without checking).
+ if (incrementForNextIter)
+ add32(Imm32(incrementForNextIter), index);
+ jump().linkTo(firstAlternativeInputChecked, this);
+ }
+
+ notEnoughInputForPreviousAlternative.link(this);
+ // Update our idea of the start position, if we're tracking this.
+ if (!m_pattern.m_body->m_hasFixedSize) {
+ if (countCheckedForCurrentAlternative - 1) {
+ move(index, regT0);
+ sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
+ poke(regT0, m_pattern.m_body->m_callFrameSize);
+ } else
+ poke(index, m_pattern.m_body->m_callFrameSize);
+ }
+ // Check if there is sufficent input to run the first alternative again.
+ jumpIfAvailableInput(incrementForNextIter).linkTo(firstAlternativeInputChecked, this);
+ // No - insufficent input to run the first alteranative, are there any other alternatives we
+ // might need to check? If so, the last check will have left the index incremented by
+ // (countToCheckForFirstAlternative + 1), so we need test whether countToCheckForFirstAlternative
+ // LESS input is available, to have the effect of just progressing the start position by 1
+ // from the last iteration. If this check passes we can just jump up to the check associated
+ // with the first alternative in the loop. This is a bit sad, since we'll end up trying the
+ // first alternative again, and this check will fail (otherwise the check planted just above
+ // here would have passed). This is a bit sad, however it saves trying to do something more
+ // complex here in compilation, and in the common case we should end up coallescing the checks.
+ //
+ // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least
+ // of the minimum-alterantive-lengths. E.g. if I have two alternatives of length 200 and 150,
+ // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there
+ // is sufficient input to run either alternative (constantly failing). If there had been only
+ // one alternative, or if the shorter alternative had come first, we would have terminated
+ // immediately. :-/
+ if (hasShorterAlternatives)
+ jumpIfAvailableInput(-countToCheckForFirstAlternative).linkTo(firstAlternative, this);
+ // index will now be a bit garbled (depending on whether 'hasShorterAlternatives' is true,
+ // it has either been incremented by 1 or by (countToCheckForFirstAlternative + 1) ...
+ // but since we're about to return a failure this doesn't really matter!)
+
+ unsigned frameSize = m_pattern.m_body->m_callFrameSize;
+ if (!m_pattern.m_body->m_hasFixedSize)
+ ++frameSize;
+ if (frameSize)
+ addPtr(Imm32(frameSize * sizeof(void*)), stackPointerRegister);
+
+ move(Imm32(-1), returnRegister);
+
+ generateReturn();
+ }
+
+ void generateEnter()
+ {
+#if PLATFORM(X86_64)
+ push(X86::ebp);
+ move(stackPointerRegister, X86::ebp);
+ push(X86::ebx);
+#elif PLATFORM(X86)
+ push(X86::ebp);
+ move(stackPointerRegister, X86::ebp);
+ // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
+ push(X86::ebx);
+ push(X86::edi);
+ push(X86::esi);
+ // load output into edi (2 = saved ebp + return address).
+ #if COMPILER(MSVC)
+ loadPtr(Address(X86::ebp, 2 * sizeof(void*)), input);
+ loadPtr(Address(X86::ebp, 3 * sizeof(void*)), index);
+ loadPtr(Address(X86::ebp, 4 * sizeof(void*)), length);
+ loadPtr(Address(X86::ebp, 5 * sizeof(void*)), output);
+ #else
+ loadPtr(Address(X86::ebp, 2 * sizeof(void*)), output);
+ #endif
+#elif PLATFORM_ARM_ARCH(7)
+ push(ARM::r4);
+ push(ARM::r5);
+ push(ARM::r6);
+ move(ARM::r3, output);
+#endif
+ }
+
+ void generateReturn()
+ {
+#if PLATFORM(X86_64)
+ pop(X86::ebx);
+ pop(X86::ebp);
+#elif PLATFORM(X86)
+ pop(X86::esi);
+ pop(X86::edi);
+ pop(X86::ebx);
+ pop(X86::ebp);
+#elif PLATFORM_ARM_ARCH(7)
+ pop(ARM::r6);
+ pop(ARM::r5);
+ pop(ARM::r4);
+#endif
+ ret();
+ }
+
+public:
+ RegexGenerator(RegexPattern& pattern)
+ : m_pattern(pattern)
+ , m_generationFailed(false)
+ {
+ }
+
+ void generate()
+ {
+ generateEnter();
+
+ // TODO: do I really want this on the stack?
+ if (!m_pattern.m_body->m_hasFixedSize)
+ push(index);
+
+ if (m_pattern.m_body->m_callFrameSize)
+ subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+
+ generateDisjunction(m_pattern.m_body);
+ }
+
+ void compile(JSGlobalData* globalData, RegexCodeBlock& jitObject)
+ {
+ generate();
+
+ LinkBuffer patchBuffer(this, globalData->executableAllocator.poolForSize(size()));
+
+ for (unsigned i = 0; i < m_backtrackRecords.size(); ++i)
+ patchBuffer.patch(m_backtrackRecords[i].dataLabel, patchBuffer.locationOf(m_backtrackRecords[i].backtrackLocation));
+
+ jitObject.set(patchBuffer.finalizeCode());
+ }
+
+ bool generationFailed()
+ {
+ return m_generationFailed;
+ }
+
+private:
+ RegexPattern& m_pattern;
+ Vector<AlternativeBacktrackRecord> m_backtrackRecords;
+ bool m_generationFailed;
+};
+
+void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
+{
+ RegexPattern pattern(ignoreCase, multiline);
+
+ if ((error = compileRegex(patternString, pattern)))
+ return;
+
+ numSubpatterns = pattern.m_numSubpatterns;
+
+ RegexGenerator generator(pattern);
+ generator.compile(globalData, jitObject);
+
+ if (generator.generationFailed()) {
+ JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase;
+ JSRegExpMultilineOption multilineOption = multiline ? JSRegExpMultiline : JSRegExpSingleLine;
+ jitObject.setFallback(jsRegExpCompile(reinterpret_cast<const UChar*>(patternString.data()), patternString.size(), ignoreCaseOption, multilineOption, &numSubpatterns, &error));
+ }
+}
+
+int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize)
+{
+ if (JSRegExp* fallback = jitObject.getFallback())
+ return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0];
+
+ return jitObject.execute(input, start, length, output);
+}
+
+}}
+
+#endif
+
+
+
+
+
--- /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 RegexJIT_h
+#define RegexJIT_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(YARR_JIT)
+
+#include "MacroAssembler.h"
+#include "RegexPattern.h"
+#include <UString.h>
+
+#include <pcre.h>
+struct JSRegExp; // temporary, remove when fallback is removed.
+
+#if PLATFORM(X86) && !COMPILER(MSVC)
+#define YARR_CALL __attribute__ ((regparm (3)))
+#else
+#define YARR_CALL
+#endif
+
+namespace JSC {
+
+class JSGlobalData;
+class ExecutablePool;
+
+namespace Yarr {
+
+class RegexCodeBlock {
+ typedef int (*RegexJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+
+public:
+ RegexCodeBlock()
+ : m_fallback(0)
+ {
+ }
+
+ ~RegexCodeBlock()
+ {
+ if (m_fallback)
+ jsRegExpFree(m_fallback);
+ }
+
+ JSRegExp* getFallback() { return m_fallback; }
+ void setFallback(JSRegExp* fallback) { m_fallback = fallback; }
+
+ bool operator!() { return !m_ref.m_code.executableAddress(); }
+ void set(MacroAssembler::CodeRef ref) { m_ref = ref; }
+
+ int execute(const UChar* input, unsigned start, unsigned length, int* output)
+ {
+ return reinterpret_cast<RegexJITCode>(m_ref.m_code.executableAddress())(input, start, length, output);
+ }
+
+private:
+ MacroAssembler::CodeRef m_ref;
+ JSRegExp* m_fallback;
+};
+
+void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
+int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize);
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // RegexJIT_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.
+ */
+
+#ifndef RegexParser_h
+#define RegexParser_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(YARR)
+
+#include <UString.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/unicode/Unicode.h>
+#include <limits.h>
+
+namespace JSC { namespace Yarr {
+
+enum BuiltInCharacterClassID {
+ DigitClassID,
+ SpaceClassID,
+ WordClassID,
+ NewlineClassID,
+};
+
+// The Parser class should not be used directly - only via the Yarr::parse() method.
+template<class Delegate>
+class Parser {
+private:
+ template<class FriendDelegate>
+ friend const char* parse(FriendDelegate& delegate, const UString& pattern, unsigned backReferenceLimit);
+
+ enum ErrorCode {
+ NoError,
+ PatternTooLarge,
+ QuantifierOutOfOrder,
+ QuantifierWithoutAtom,
+ MissingParentheses,
+ ParenthesesUnmatched,
+ ParenthesesTypeInvalid,
+ CharacterClassUnmatched,
+ CharacterClassOutOfOrder,
+ EscapeUnterminated,
+ NumberOfErrorCodes
+ };
+
+ /*
+ * CharacterClassParserDelegate:
+ *
+ * The class CharacterClassParserDelegate is used in the parsing of character
+ * classes. This class handles detection of character ranges. This class
+ * implements enough of the delegate interface such that it can be passed to
+ * parseEscape() as an EscapeDelegate. This allows parseEscape() to be reused
+ * to perform the parsing of escape characters in character sets.
+ */
+ class CharacterClassParserDelegate {
+ public:
+ CharacterClassParserDelegate(Delegate& delegate, ErrorCode& err)
+ : m_delegate(delegate)
+ , m_err(err)
+ , m_state(empty)
+ {
+ }
+
+ /*
+ * begin():
+ *
+ * Called at beginning of construction.
+ */
+ void begin(bool invert)
+ {
+ m_delegate.atomCharacterClassBegin(invert);
+ }
+
+ /*
+ * atomPatternCharacterUnescaped():
+ *
+ * This method is called directly from parseCharacterClass(), to report a new
+ * pattern character token. This method differs from atomPatternCharacter(),
+ * which will be called from parseEscape(), since a hypen provided via this
+ * method may be indicating a character range, but a hyphen parsed by
+ * parseEscape() cannot be interpreted as doing so.
+ */
+ void atomPatternCharacterUnescaped(UChar ch)
+ {
+ switch (m_state) {
+ case empty:
+ m_character = ch;
+ m_state = cachedCharacter;
+ break;
+
+ case cachedCharacter:
+ if (ch == '-')
+ m_state = cachedCharacterHyphen;
+ else {
+ m_delegate.atomCharacterClassAtom(m_character);
+ m_character = ch;
+ }
+ break;
+
+ case cachedCharacterHyphen:
+ if (ch >= m_character)
+ m_delegate.atomCharacterClassRange(m_character, ch);
+ else
+ m_err = CharacterClassOutOfOrder;
+ m_state = empty;
+ }
+ }
+
+ /*
+ * atomPatternCharacter():
+ *
+ * Adds a pattern character, called by parseEscape(), as such will not
+ * interpret a hyphen as indicating a character range.
+ */
+ void atomPatternCharacter(UChar ch)
+ {
+ // Flush if a character is already pending to prevent the
+ // hyphen from begin interpreted as indicating a range.
+ if((ch == '-') && (m_state == cachedCharacter))
+ flush();
+
+ atomPatternCharacterUnescaped(ch);
+ }
+
+ /*
+ * atomBuiltInCharacterClass():
+ *
+ * Adds a built-in character class, called by parseEscape().
+ */
+ void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
+ {
+ flush();
+ m_delegate.atomCharacterClassBuiltIn(classID, invert);
+ }
+
+ /*
+ * end():
+ *
+ * Called at end of construction.
+ */
+ void end()
+ {
+ flush();
+ m_delegate.atomCharacterClassEnd();
+ }
+
+ // parseEscape() should never call these delegate methods when
+ // invoked with inCharacterClass set.
+ void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
+ void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
+
+ private:
+ void flush()
+ {
+ if (m_state != empty) // either cachedCharacter or cachedCharacterHyphen
+ m_delegate.atomCharacterClassAtom(m_character);
+ if (m_state == cachedCharacterHyphen)
+ m_delegate.atomCharacterClassAtom('-');
+ m_state = empty;
+ }
+
+ Delegate& m_delegate;
+ ErrorCode& m_err;
+ enum CharacterClassConstructionState {
+ empty,
+ cachedCharacter,
+ cachedCharacterHyphen,
+ } m_state;
+ UChar m_character;
+ };
+
+ Parser(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit)
+ : m_delegate(delegate)
+ , m_backReferenceLimit(backReferenceLimit)
+ , m_err(NoError)
+ , m_data(pattern.data())
+ , m_size(pattern.size())
+ , m_index(0)
+ , m_parenthesesNestingDepth(0)
+ {
+ }
+
+ /*
+ * parseEscape():
+ *
+ * Helper for parseTokens() AND parseCharacterClass().
+ * Unlike the other parser methods, this function does not report tokens
+ * directly to the member delegate (m_delegate), instead tokens are
+ * emitted to the delegate provided as an argument. In the case of atom
+ * escapes, parseTokens() will call parseEscape() passing m_delegate as
+ * an argument, and as such the escape will be reported to the delegate.
+ *
+ * However this method may also be used by parseCharacterClass(), in which
+ * case a CharacterClassParserDelegate will be passed as the delegate that
+ * tokens should be added to. A boolean flag is also provided to indicate
+ * whether that an escape in a CharacterClass is being parsed (some parsing
+ * rules change in this context).
+ *
+ * The boolean value returned by this method indicates whether the token
+ * parsed was an atom (outside of a characted class \b and \B will be
+ * interpreted as assertions).
+ */
+ template<bool inCharacterClass, class EscapeDelegate>
+ bool parseEscape(EscapeDelegate& delegate)
+ {
+ ASSERT(!m_err);
+ ASSERT(peek() == '\\');
+ consume();
+
+ if (atEndOfPattern()) {
+ m_err = EscapeUnterminated;
+ return false;
+ }
+
+ switch (peek()) {
+ // Assertions
+ case 'b':
+ consume();
+ if (inCharacterClass)
+ delegate.atomPatternCharacter('\b');
+ else {
+ delegate.assertionWordBoundary(false);
+ return false;
+ }
+ break;
+ case 'B':
+ consume();
+ if (inCharacterClass)
+ delegate.atomPatternCharacter('B');
+ else {
+ delegate.assertionWordBoundary(true);
+ return false;
+ }
+ break;
+
+ // CharacterClassEscape
+ case 'd':
+ consume();
+ delegate.atomBuiltInCharacterClass(DigitClassID, false);
+ break;
+ case 's':
+ consume();
+ delegate.atomBuiltInCharacterClass(SpaceClassID, false);
+ break;
+ case 'w':
+ consume();
+ delegate.atomBuiltInCharacterClass(WordClassID, false);
+ break;
+ case 'D':
+ consume();
+ delegate.atomBuiltInCharacterClass(DigitClassID, true);
+ break;
+ case 'S':
+ consume();
+ delegate.atomBuiltInCharacterClass(SpaceClassID, true);
+ break;
+ case 'W':
+ consume();
+ delegate.atomBuiltInCharacterClass(WordClassID, true);
+ break;
+
+ // DecimalEscape
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ // To match Firefox, we parse an invalid backreference in the range [1-7] as an octal escape.
+ // First, try to parse this as backreference.
+ if (!inCharacterClass) {
+ ParseState state = saveState();
+
+ unsigned backReference = consumeNumber();
+ if (backReference <= m_backReferenceLimit) {
+ delegate.atomBackReference(backReference);
+ break;
+ }
+
+ restoreState(state);
+ }
+
+ // Not a backreference, and not octal.
+ if (peek() >= '8') {
+ delegate.atomPatternCharacter('\\');
+ break;
+ }
+
+ // Fall-through to handle this as an octal escape.
+ }
+
+ // Octal escape
+ case '0':
+ delegate.atomPatternCharacter(consumeOctal());
+ break;
+
+ // ControlEscape
+ case 'f':
+ consume();
+ delegate.atomPatternCharacter('\f');
+ break;
+ case 'n':
+ consume();
+ delegate.atomPatternCharacter('\n');
+ break;
+ case 'r':
+ consume();
+ delegate.atomPatternCharacter('\r');
+ break;
+ case 't':
+ consume();
+ delegate.atomPatternCharacter('\t');
+ break;
+ case 'v':
+ consume();
+ delegate.atomPatternCharacter('\v');
+ break;
+
+ // ControlLetter
+ case 'c': {
+ ParseState state = saveState();
+ consume();
+ if (!atEndOfPattern()) {
+ int control = consume();
+
+ // To match Firefox, inside a character class, we also accept numbers and '_' as control characters.
+ if (inCharacterClass ? WTF::isASCIIAlphanumeric(control) || (control == '_') : WTF::isASCIIAlpha(control)) {
+ delegate.atomPatternCharacter(control & 0x1f);
+ break;
+ }
+ }
+ restoreState(state);
+ delegate.atomPatternCharacter('\\');
+ break;
+ }
+
+ // HexEscape
+ case 'x': {
+ consume();
+ int x = tryConsumeHex(2);
+ if (x == -1)
+ delegate.atomPatternCharacter('x');
+ else
+ delegate.atomPatternCharacter(x);
+ break;
+ }
+
+ // UnicodeEscape
+ case 'u': {
+ consume();
+ int u = tryConsumeHex(4);
+ if (u == -1)
+ delegate.atomPatternCharacter('u');
+ else
+ delegate.atomPatternCharacter(u);
+ break;
+ }
+
+ // IdentityEscape
+ default:
+ delegate.atomPatternCharacter(consume());
+ }
+
+ return true;
+ }
+
+ /*
+ * parseAtomEscape(), parseCharacterClassEscape():
+ *
+ * These methods alias to parseEscape().
+ */
+ bool parseAtomEscape()
+ {
+ return parseEscape<false>(m_delegate);
+ }
+ void parseCharacterClassEscape(CharacterClassParserDelegate& delegate)
+ {
+ parseEscape<true>(delegate);
+ }
+
+ /*
+ * parseCharacterClass():
+ *
+ * Helper for parseTokens(); calls dirctly and indirectly (via parseCharacterClassEscape)
+ * to an instance of CharacterClassParserDelegate, to describe the character class to the
+ * delegate.
+ */
+ void parseCharacterClass()
+ {
+ ASSERT(!m_err);
+ ASSERT(peek() == '[');
+ consume();
+
+ CharacterClassParserDelegate characterClassConstructor(m_delegate, m_err);
+
+ characterClassConstructor.begin(tryConsume('^'));
+
+ while (!atEndOfPattern()) {
+ switch (peek()) {
+ case ']':
+ consume();
+ characterClassConstructor.end();
+ return;
+
+ case '\\':
+ parseCharacterClassEscape(characterClassConstructor);
+ break;
+
+ default:
+ characterClassConstructor.atomPatternCharacterUnescaped(consume());
+ }
+
+ if (m_err)
+ return;
+ }
+
+ m_err = CharacterClassUnmatched;
+ }
+
+ /*
+ * parseParenthesesBegin():
+ *
+ * Helper for parseTokens(); checks for parentheses types other than regular capturing subpatterns.
+ */
+ void parseParenthesesBegin()
+ {
+ ASSERT(!m_err);
+ ASSERT(peek() == '(');
+ consume();
+
+ if (tryConsume('?')) {
+ if (atEndOfPattern()) {
+ m_err = ParenthesesTypeInvalid;
+ return;
+ }
+
+ switch (consume()) {
+ case ':':
+ m_delegate.atomParenthesesSubpatternBegin(false);
+ break;
+
+ case '=':
+ m_delegate.atomParentheticalAssertionBegin();
+ break;
+
+ case '!':
+ m_delegate.atomParentheticalAssertionBegin(true);
+ break;
+
+ default:
+ m_err = ParenthesesTypeInvalid;
+ }
+ } else
+ m_delegate.atomParenthesesSubpatternBegin();
+
+ ++m_parenthesesNestingDepth;
+ }
+
+ /*
+ * parseParenthesesEnd():
+ *
+ * Helper for parseTokens(); checks for parse errors (due to unmatched parentheses).
+ */
+ void parseParenthesesEnd()
+ {
+ ASSERT(!m_err);
+ ASSERT(peek() == ')');
+ consume();
+
+ if (m_parenthesesNestingDepth > 0)
+ m_delegate.atomParenthesesEnd();
+ else
+ m_err = ParenthesesUnmatched;
+
+ --m_parenthesesNestingDepth;
+ }
+
+ /*
+ * parseQuantifier():
+ *
+ * Helper for parseTokens(); checks for parse errors and non-greedy quantifiers.
+ */
+ void parseQuantifier(bool lastTokenWasAnAtom, unsigned min, unsigned max)
+ {
+ ASSERT(!m_err);
+ ASSERT(min <= max);
+
+ if (lastTokenWasAnAtom)
+ m_delegate.quantifyAtom(min, max, !tryConsume('?'));
+ else
+ m_err = QuantifierWithoutAtom;
+ }
+
+ /*
+ * parseTokens():
+ *
+ * This method loops over the input pattern reporting tokens to the delegate.
+ * The method returns when a parse error is detected, or the end of the pattern
+ * is reached. One piece of state is tracked around the loop, which is whether
+ * the last token passed to the delegate was an atom (this is necessary to detect
+ * a parse error when a quantifier provided without an atom to quantify).
+ */
+ void parseTokens()
+ {
+ bool lastTokenWasAnAtom = false;
+
+ while (!atEndOfPattern()) {
+ switch (peek()) {
+ case '|':
+ consume();
+ m_delegate.disjunction();
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '(':
+ parseParenthesesBegin();
+ lastTokenWasAnAtom = false;
+ break;
+
+ case ')':
+ parseParenthesesEnd();
+ lastTokenWasAnAtom = true;
+ break;
+
+ case '^':
+ consume();
+ m_delegate.assertionBOL();
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '$':
+ consume();
+ m_delegate.assertionEOL();
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '.':
+ consume();
+ m_delegate.atomBuiltInCharacterClass(NewlineClassID, true);
+ lastTokenWasAnAtom = true;
+ break;
+
+ case '[':
+ parseCharacterClass();
+ lastTokenWasAnAtom = true;
+ break;
+
+ case '\\':
+ lastTokenWasAnAtom = parseAtomEscape();
+ break;
+
+ case '*':
+ consume();
+ parseQuantifier(lastTokenWasAnAtom, 0, UINT_MAX);
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '+':
+ consume();
+ parseQuantifier(lastTokenWasAnAtom, 1, UINT_MAX);
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '?':
+ consume();
+ parseQuantifier(lastTokenWasAnAtom, 0, 1);
+ lastTokenWasAnAtom = false;
+ break;
+
+ case '{': {
+ ParseState state = saveState();
+
+ consume();
+ if (peekIsDigit()) {
+ unsigned min = consumeNumber();
+ unsigned max = min;
+
+ if (tryConsume(','))
+ max = peekIsDigit() ? consumeNumber() : UINT_MAX;
+
+ if (tryConsume('}')) {
+ if (min <= max)
+ parseQuantifier(lastTokenWasAnAtom, min, max);
+ else
+ m_err = QuantifierOutOfOrder;
+ lastTokenWasAnAtom = false;
+ break;
+ }
+ }
+
+ restoreState(state);
+ } // if we did not find a complete quantifer, fall through to the default case.
+
+ default:
+ m_delegate.atomPatternCharacter(consume());
+ lastTokenWasAnAtom = true;
+ }
+
+ if (m_err)
+ return;
+ }
+
+ if (m_parenthesesNestingDepth > 0)
+ m_err = MissingParentheses;
+ }
+
+ /*
+ * parse():
+ *
+ * This method calls regexBegin(), calls parseTokens() to parse over the input
+ * patterns, calls regexEnd() or regexError() as appropriate, and converts any
+ * error code to a const char* for a result.
+ */
+ const char* parse()
+ {
+ m_delegate.regexBegin();
+
+ if (m_size > MAX_PATTERN_SIZE)
+ m_err = PatternTooLarge;
+ else
+ parseTokens();
+ ASSERT(atEndOfPattern() || m_err);
+
+ if (m_err)
+ m_delegate.regexError();
+ else
+ m_delegate.regexEnd();
+
+ // The order of this array must match the ErrorCode enum.
+ static const char* errorMessages[NumberOfErrorCodes] = {
+ 0, // NoError
+ "regular expression too large",
+ "numbers out of order in {} quantifier",
+ "nothing to repeat",
+ "missing )",
+ "unmatched parentheses",
+ "unrecognized character after (?",
+ "missing terminating ] for character class",
+ "range out of order in character class",
+ "\\ at end of pattern"
+ };
+
+ return errorMessages[m_err];
+ }
+
+
+ // Misc helper functions:
+
+ typedef unsigned ParseState;
+
+ ParseState saveState()
+ {
+ return m_index;
+ }
+
+ void restoreState(ParseState state)
+ {
+ m_index = state;
+ }
+
+ bool atEndOfPattern()
+ {
+ ASSERT(m_index <= m_size);
+ return m_index == m_size;
+ }
+
+ int peek()
+ {
+ ASSERT(m_index < m_size);
+ return m_data[m_index];
+ }
+
+ bool peekIsDigit()
+ {
+ return !atEndOfPattern() && WTF::isASCIIDigit(peek());
+ }
+
+ unsigned peekDigit()
+ {
+ ASSERT(peekIsDigit());
+ return peek() - '0';
+ }
+
+ int consume()
+ {
+ ASSERT(m_index < m_size);
+ return m_data[m_index++];
+ }
+
+ unsigned consumeDigit()
+ {
+ ASSERT(peekIsDigit());
+ return consume() - '0';
+ }
+
+ unsigned consumeNumber()
+ {
+ unsigned n = consumeDigit();
+ // check for overflow.
+ for (unsigned newValue; peekIsDigit() && ((newValue = n * 10 + peekDigit()) >= n); ) {
+ n = newValue;
+ consume();
+ }
+ return n;
+ }
+
+ unsigned consumeOctal()
+ {
+ ASSERT(WTF::isASCIIOctalDigit(peek()));
+
+ unsigned n = consumeDigit();
+ while (n < 32 && !atEndOfPattern() && WTF::isASCIIOctalDigit(peek()))
+ n = n * 8 + consumeDigit();
+ return n;
+ }
+
+ bool tryConsume(UChar ch)
+ {
+ if (atEndOfPattern() || (m_data[m_index] != ch))
+ return false;
+ ++m_index;
+ return true;
+ }
+
+ int tryConsumeHex(int count)
+ {
+ ParseState state = saveState();
+
+ int n = 0;
+ while (count--) {
+ if (atEndOfPattern() || !WTF::isASCIIHexDigit(peek())) {
+ restoreState(state);
+ return -1;
+ }
+ n = (n << 4) | WTF::toASCIIHexValue(consume());
+ }
+ return n;
+ }
+
+ Delegate& m_delegate;
+ unsigned m_backReferenceLimit;
+ ErrorCode m_err;
+ const UChar* m_data;
+ unsigned m_size;
+ unsigned m_index;
+ unsigned m_parenthesesNestingDepth;
+
+ // Derived by empirical testing of compile time in PCRE and WREC.
+ static const unsigned MAX_PATTERN_SIZE = 1024 * 1024;
+};
+
+/*
+ * Yarr::parse():
+ *
+ * The parse method is passed a pattern to be parsed and a delegate upon which
+ * callbacks will be made to record the parsed tokens forming the regex.
+ * Yarr::parse() returns null on success, or a const C string providing an error
+ * message where a parse error occurs.
+ *
+ * The Delegate must implement the following interface:
+ *
+ * void assertionBOL();
+ * void assertionEOL();
+ * void assertionWordBoundary(bool invert);
+ *
+ * void atomPatternCharacter(UChar ch);
+ * void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert);
+ * void atomCharacterClassBegin(bool invert)
+ * void atomCharacterClassAtom(UChar ch)
+ * void atomCharacterClassRange(UChar begin, UChar end)
+ * void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
+ * void atomCharacterClassEnd()
+ * void atomParenthesesSubpatternBegin(bool capture = true);
+ * void atomParentheticalAssertionBegin(bool invert = false);
+ * void atomParenthesesEnd();
+ * void atomBackReference(unsigned subpatternId);
+ *
+ * void quantifyAtom(unsigned min, unsigned max, bool greedy);
+ *
+ * void disjunction();
+ *
+ * void regexBegin();
+ * void regexEnd();
+ * void regexError();
+ *
+ * Before any call recording tokens are made, regexBegin() will be called on the
+ * delegate once. Once parsing is complete either regexEnd() or regexError() will
+ * be called, as appropriate.
+ *
+ * The regular expression is described by a sequence of assertion*() and atom*()
+ * callbacks to the delegate, describing the terms in the regular expression.
+ * Following an atom a quantifyAtom() call may occur to indicate that the previous
+ * atom should be quantified. In the case of atoms described across multiple
+ * calls (parentheses and character classes) the call to quantifyAtom() will come
+ * after the call to the atom*End() method, never after atom*Begin().
+ *
+ * Character classes may either be described by a single call to
+ * atomBuiltInCharacterClass(), or by a sequence of atomCharacterClass*() calls.
+ * In the latter case, ...Begin() will be called, followed by a sequence of
+ * calls to ...Atom(), ...Range(), and ...BuiltIn(), followed by a call to ...End().
+ *
+ * Sequences of atoms and assertions are broken into alternatives via calls to
+ * disjunction(). Assertions, atoms, and disjunctions emitted between calls to
+ * atomParenthesesBegin() and atomParenthesesEnd() form the body of a subpattern.
+ * atomParenthesesBegin() is passed a subpatternId. In the case of a regular
+ * capturing subpattern, this will be the subpatternId associated with these
+ * parentheses, and will also by definition be the lowest subpatternId of these
+ * parentheses and of any nested paretheses. The atomParenthesesEnd() method
+ * is passed the subpatternId of the last capturing subexpression nested within
+ * these paretheses. In the case of a capturing subpattern with no nested
+ * capturing subpatterns, the same subpatternId will be passed to the begin and
+ * end functions. In the case of non-capturing subpatterns the subpatternId
+ * passed to the begin method is also the first possible subpatternId that might
+ * be nested within these paretheses. If a set of non-capturing parentheses does
+ * not contain any capturing subpatterns, then the subpatternId passed to begin
+ * will be greater than the subpatternId passed to end.
+ */
+
+template<class Delegate>
+const char* parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = UINT_MAX)
+{
+ return Parser<Delegate>(delegate, pattern, backReferenceLimit).parse();
+}
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // RegexParser_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.
+ */
+
+#ifndef RegexPattern_h
+#define RegexPattern_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(YARR)
+
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+
+namespace JSC { namespace Yarr {
+
+#define RegexStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers.
+#define RegexStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers.
+#define RegexStackSpaceForBackTrackInfoBackReference 2
+#define RegexStackSpaceForBackTrackInfoAlternative 1 // One per alternative.
+#define RegexStackSpaceForBackTrackInfoParentheticalAssertion 1
+#define RegexStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers.
+#define RegexStackSpaceForBackTrackInfoParentheses 4
+
+struct PatternDisjunction;
+
+struct CharacterRange {
+ UChar begin;
+ UChar end;
+
+ CharacterRange(UChar begin, UChar end)
+ : begin(begin)
+ , end(end)
+ {
+ }
+};
+
+struct CharacterClass {
+ Vector<UChar> m_matches;
+ Vector<CharacterRange> m_ranges;
+ Vector<UChar> m_matchesUnicode;
+ Vector<CharacterRange> m_rangesUnicode;
+};
+
+enum QuantifierType {
+ QuantifierFixedCount,
+ QuantifierGreedy,
+ QuantifierNonGreedy,
+};
+
+struct PatternTerm {
+ enum Type {
+ TypeAssertionBOL,
+ TypeAssertionEOL,
+ TypeAssertionWordBoundary,
+ TypePatternCharacter,
+ TypeCharacterClass,
+ TypeBackReference,
+ TypeForwardReference,
+ TypeParenthesesSubpattern,
+ TypeParentheticalAssertion,
+ } type;
+ bool invertOrCapture;
+ union {
+ UChar patternCharacter;
+ CharacterClass* characterClass;
+ unsigned subpatternId;
+ struct {
+ PatternDisjunction* disjunction;
+ unsigned subpatternId;
+ unsigned lastSubpatternId;
+ bool isCopy;
+ } parentheses;
+ };
+ QuantifierType quantityType;
+ unsigned quantityCount;
+ int inputPosition;
+ unsigned frameLocation;
+
+ PatternTerm(UChar ch)
+ : type(PatternTerm::TypePatternCharacter)
+ {
+ patternCharacter = ch;
+ quantityType = QuantifierFixedCount;
+ quantityCount = 1;
+ }
+
+ PatternTerm(CharacterClass* charClass, bool invert)
+ : type(PatternTerm::TypeCharacterClass)
+ , invertOrCapture(invert)
+ {
+ characterClass = charClass;
+ quantityType = QuantifierFixedCount;
+ quantityCount = 1;
+ }
+
+ PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool invertOrCapture)
+ : type(type)
+ , invertOrCapture(invertOrCapture)
+ {
+ parentheses.disjunction = disjunction;
+ parentheses.subpatternId = subpatternId;
+ parentheses.isCopy = false;
+ quantityType = QuantifierFixedCount;
+ quantityCount = 1;
+ }
+
+ PatternTerm(Type type, bool invert = false)
+ : type(type)
+ , invertOrCapture(invert)
+ {
+ quantityType = QuantifierFixedCount;
+ quantityCount = 1;
+ }
+
+ PatternTerm(unsigned spatternId)
+ : type(TypeBackReference)
+ , invertOrCapture(invertOrCapture)
+ {
+ subpatternId = spatternId;
+ quantityType = QuantifierFixedCount;
+ quantityCount = 1;
+ }
+
+ static PatternTerm ForwardReference()
+ {
+ return PatternTerm(TypeForwardReference);
+ }
+
+ static PatternTerm BOL()
+ {
+ return PatternTerm(TypeAssertionBOL);
+ }
+
+ static PatternTerm EOL()
+ {
+ return PatternTerm(TypeAssertionEOL);
+ }
+
+ static PatternTerm WordBoundary(bool invert)
+ {
+ return PatternTerm(TypeAssertionWordBoundary, invert);
+ }
+
+ bool invert()
+ {
+ return invertOrCapture;
+ }
+
+ bool capture()
+ {
+ return invertOrCapture;
+ }
+
+ void quantify(unsigned count, QuantifierType type)
+ {
+ quantityCount = count;
+ quantityType = type;
+ }
+};
+
+struct PatternAlternative {
+ PatternAlternative(PatternDisjunction* disjunction)
+ : m_parent(disjunction)
+ {
+ }
+
+ PatternTerm& lastTerm()
+ {
+ ASSERT(m_terms.size());
+ return m_terms[m_terms.size() - 1];
+ }
+
+ void removeLastTerm()
+ {
+ ASSERT(m_terms.size());
+ m_terms.shrink(m_terms.size() - 1);
+ }
+
+ Vector<PatternTerm> m_terms;
+ PatternDisjunction* m_parent;
+ unsigned m_minimumSize;
+ bool m_hasFixedSize;
+};
+
+struct PatternDisjunction {
+ PatternDisjunction(PatternAlternative* parent = 0)
+ : m_parent(parent)
+ {
+ }
+
+ ~PatternDisjunction()
+ {
+ deleteAllValues(m_alternatives);
+ }
+
+ PatternAlternative* addNewAlternative()
+ {
+ PatternAlternative* alternative = new PatternAlternative(this);
+ m_alternatives.append(alternative);
+ return alternative;
+ }
+
+ Vector<PatternAlternative*> m_alternatives;
+ PatternAlternative* m_parent;
+ unsigned m_minimumSize;
+ unsigned m_callFrameSize;
+ bool m_hasFixedSize;
+};
+
+// You probably don't want to be calling these functions directly
+// (please to be calling newlineCharacterClass() et al on your
+// friendly neighborhood RegexPattern instance to get nicely
+// cached copies).
+CharacterClass* newlineCreate();
+CharacterClass* digitsCreate();
+CharacterClass* spacesCreate();
+CharacterClass* wordcharCreate();
+CharacterClass* nondigitsCreate();
+CharacterClass* nonspacesCreate();
+CharacterClass* nonwordcharCreate();
+
+struct RegexPattern {
+ RegexPattern(bool ignoreCase, bool multiline)
+ : m_ignoreCase(ignoreCase)
+ , m_multiline(multiline)
+ , m_numSubpatterns(0)
+ , m_maxBackReference(0)
+ , newlineCached(0)
+ , digitsCached(0)
+ , spacesCached(0)
+ , wordcharCached(0)
+ , nondigitsCached(0)
+ , nonspacesCached(0)
+ , nonwordcharCached(0)
+ {
+ }
+
+ ~RegexPattern()
+ {
+ deleteAllValues(m_disjunctions);
+ deleteAllValues(m_userCharacterClasses);
+ }
+
+ void reset()
+ {
+ m_numSubpatterns = 0;
+ m_maxBackReference = 0;
+
+ newlineCached = 0;
+ digitsCached = 0;
+ spacesCached = 0;
+ wordcharCached = 0;
+ nondigitsCached = 0;
+ nonspacesCached = 0;
+ nonwordcharCached = 0;
+
+ deleteAllValues(m_disjunctions);
+ m_disjunctions.clear();
+ deleteAllValues(m_userCharacterClasses);
+ m_userCharacterClasses.clear();
+ }
+
+ bool containsIllegalBackReference()
+ {
+ return m_maxBackReference > m_numSubpatterns;
+ }
+
+ CharacterClass* newlineCharacterClass()
+ {
+ if (!newlineCached)
+ m_userCharacterClasses.append(newlineCached = newlineCreate());
+ return newlineCached;
+ }
+ CharacterClass* digitsCharacterClass()
+ {
+ if (!digitsCached)
+ m_userCharacterClasses.append(digitsCached = digitsCreate());
+ return digitsCached;
+ }
+ CharacterClass* spacesCharacterClass()
+ {
+ if (!spacesCached)
+ m_userCharacterClasses.append(spacesCached = spacesCreate());
+ return spacesCached;
+ }
+ CharacterClass* wordcharCharacterClass()
+ {
+ if (!wordcharCached)
+ m_userCharacterClasses.append(wordcharCached = wordcharCreate());
+ return wordcharCached;
+ }
+ CharacterClass* nondigitsCharacterClass()
+ {
+ if (!nondigitsCached)
+ m_userCharacterClasses.append(nondigitsCached = nondigitsCreate());
+ return nondigitsCached;
+ }
+ CharacterClass* nonspacesCharacterClass()
+ {
+ if (!nonspacesCached)
+ m_userCharacterClasses.append(nonspacesCached = nonspacesCreate());
+ return nonspacesCached;
+ }
+ CharacterClass* nonwordcharCharacterClass()
+ {
+ if (!nonwordcharCached)
+ m_userCharacterClasses.append(nonwordcharCached = nonwordcharCreate());
+ return nonwordcharCached;
+ }
+
+ bool m_ignoreCase;
+ bool m_multiline;
+ unsigned m_numSubpatterns;
+ unsigned m_maxBackReference;
+ PatternDisjunction* m_body;
+ Vector<PatternDisjunction*, 4> m_disjunctions;
+ Vector<CharacterClass*> m_userCharacterClasses;
+
+private:
+ CharacterClass* newlineCached;
+ CharacterClass* digitsCached;
+ CharacterClass* spacesCached;
+ CharacterClass* wordcharCached;
+ CharacterClass* nondigitsCached;
+ CharacterClass* nonspacesCached;
+ CharacterClass* nonwordcharCached;
+};
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // RegexPattern_h