Commit 10c38d3c authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSObject fast by-string access optimizations should work even on the prototype...

JSObject fast by-string access optimizations should work even on the prototype chain, and even when the result is undefined
https://bugs.webkit.org/show_bug.cgi?id=112233

Source/JavaScriptCore: 

Reviewed by Oliver Hunt.
        
Extended the existing fast access path for String keys to work over the entire prototype chain,
not just the self access case. This will fail as soon as it sees an object that intercepts
getOwnPropertySlot, so this patch also ensures that ObjectPrototype does not fall into that
category. This is accomplished by making ObjectPrototype eagerly reify all of its properties.
This is safe for ObjectPrototype because it's so common and we expect all of its properties to
be reified for any interesting programs anyway. A new idiom for adding native functions to
prototypes is introduced, which ought to work well for any other prototypes that we wish to do
this conversion for.
        
This is a >60% speed-up in the case that you frequently do by-string lookups that "miss", i.e.
they don't turn up anything.

* CMakeLists.txt:
* DerivedSources.make:
* DerivedSources.pri:
* GNUmakefile.list.am:
* dfg/DFGOperations.cpp:
* interpreter/CallFrame.h:
(JSC::ExecState::objectConstructorTable):
* jit/JITStubs.cpp:
(JSC::getByVal):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
* runtime/CommonIdentifiers.h:
* runtime/JSCell.cpp:
(JSC::JSCell::getByStringSlow):
(JSC):
* runtime/JSCell.h:
(JSCell):
* runtime/JSCellInlines.h:
(JSC):
(JSC::JSCell::getByStringAndKey):
(JSC::JSCell::getByString):
* runtime/JSGlobalData.cpp:
(JSC):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSObject.cpp:
(JSC::JSObject::putDirectNativeFunction):
(JSC):
* runtime/JSObject.h:
(JSObject):
(JSC):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/ObjectPrototype.cpp:
(JSC):
(JSC::ObjectPrototype::finishCreation):
(JSC::ObjectPrototype::create):
* runtime/ObjectPrototype.h:
(ObjectPrototype):
* runtime/PropertyMapHashTable.h:
(JSC::PropertyTable::findWithString):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::get):
(JSC):

LayoutTests: 

Reviewed by Oliver Hunt.

* fast/js/regress/script-tests/string-lookup-hit-identifier.js: Added.
(result):
* fast/js/regress/script-tests/string-lookup-hit.js: Added.
(result):
* fast/js/regress/script-tests/string-lookup-miss.js: Added.
(result):
* fast/js/regress/string-lookup-hit-expected.txt: Added.
* fast/js/regress/string-lookup-hit-identifier-expected.txt: Added.
* fast/js/regress/string-lookup-hit-identifier.html: Added.
* fast/js/regress/string-lookup-hit.html: Added.
* fast/js/regress/string-lookup-miss-expected.txt: Added.
* fast/js/regress/string-lookup-miss.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@145838 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 367b5105
2013-03-14 Filip Pizlo <fpizlo@apple.com>
JSObject fast by-string access optimizations should work even on the prototype chain, and even when the result is undefined
https://bugs.webkit.org/show_bug.cgi?id=112233
Reviewed by Oliver Hunt.
* fast/js/regress/script-tests/string-lookup-hit-identifier.js: Added.
(result):
* fast/js/regress/script-tests/string-lookup-hit.js: Added.
(result):
* fast/js/regress/script-tests/string-lookup-miss.js: Added.
(result):
* fast/js/regress/string-lookup-hit-expected.txt: Added.
* fast/js/regress/string-lookup-hit-identifier-expected.txt: Added.
* fast/js/regress/string-lookup-hit-identifier.html: Added.
* fast/js/regress/string-lookup-hit.html: Added.
* fast/js/regress/string-lookup-miss-expected.txt: Added.
* fast/js/regress/string-lookup-miss.html: Added.
2013-03-14 Kenneth Russell <kbr@google.com>
Unreviewed expectations updates for a couple of failing tests.
var result = (function(){
var o = {};
for (var i = 0; i < 100; ++i)
o["a" + i] = 42;
var result = [];
var strings = [];
for (var i = 0; i < 100; ++i)
strings.push("a" + i);
for (var j = 0; j < 1000; ++j) {
for (var i = 0; i < 100; ++i)
result.push(o[strings[i]]);
}
return result.length;
})();
if (result != 100000)
throw "Error: bad result: " + result;
var result = (function(){
var o = {};
for (var i = 0; i < 100; ++i)
o["a" + i] = 42;
var result = [];
for (var j = 0; j < 1000; ++j) {
for (var i = 0; i < 100; ++i)
result.push(o["a" + i]);
}
return result.length;
})();
if (result != 100000)
throw "Error: bad result: " + result;
var result = (function(){
var o = {};
for (var i = 0; i < 100; ++i)
o["a" + i] = 42;
var result = [];
for (var i = 0; i < 100000; ++i)
result.push(o["a" + i]);
return result.length;
})();
if (result != 100000)
throw "Error: bad result: " + result;
JSRegress/string-lookup-hit
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
JSRegress/string-lookup-hit-identifier
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/string-lookup-hit-identifier.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/string-lookup-hit.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
JSRegress/string-lookup-miss
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/string-lookup-miss.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
......@@ -329,7 +329,6 @@ set(JavaScriptCore_LUT_FILES
runtime/NumberConstructor.cpp
runtime/NumberPrototype.cpp
runtime/ObjectConstructor.cpp
runtime/ObjectPrototype.cpp
runtime/RegExpConstructor.cpp
runtime/RegExpObject.cpp
runtime/RegExpPrototype.cpp
......
2013-03-13 Filip Pizlo <fpizlo@apple.com>
JSObject fast by-string access optimizations should work even on the prototype chain, and even when the result is undefined
https://bugs.webkit.org/show_bug.cgi?id=112233
Reviewed by Oliver Hunt.
Extended the existing fast access path for String keys to work over the entire prototype chain,
not just the self access case. This will fail as soon as it sees an object that intercepts
getOwnPropertySlot, so this patch also ensures that ObjectPrototype does not fall into that
category. This is accomplished by making ObjectPrototype eagerly reify all of its properties.
This is safe for ObjectPrototype because it's so common and we expect all of its properties to
be reified for any interesting programs anyway. A new idiom for adding native functions to
prototypes is introduced, which ought to work well for any other prototypes that we wish to do
this conversion for.
This is a >60% speed-up in the case that you frequently do by-string lookups that "miss", i.e.
they don't turn up anything.
* CMakeLists.txt:
* DerivedSources.make:
* DerivedSources.pri:
* GNUmakefile.list.am:
* dfg/DFGOperations.cpp:
* interpreter/CallFrame.h:
(JSC::ExecState::objectConstructorTable):
* jit/JITStubs.cpp:
(JSC::getByVal):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
* runtime/CommonIdentifiers.h:
* runtime/JSCell.cpp:
(JSC::JSCell::getByStringSlow):
(JSC):
* runtime/JSCell.h:
(JSCell):
* runtime/JSCellInlines.h:
(JSC):
(JSC::JSCell::getByStringAndKey):
(JSC::JSCell::getByString):
* runtime/JSGlobalData.cpp:
(JSC):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSObject.cpp:
(JSC::JSObject::putDirectNativeFunction):
(JSC):
* runtime/JSObject.h:
(JSObject):
(JSC):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/ObjectPrototype.cpp:
(JSC):
(JSC::ObjectPrototype::finishCreation):
(JSC::ObjectPrototype::create):
* runtime/ObjectPrototype.h:
(ObjectPrototype):
* runtime/PropertyMapHashTable.h:
(JSC::PropertyTable::findWithString):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::get):
(JSC):
2013-03-13 Filip Pizlo <fpizlo@apple.com>
DFG bytecode parser is too aggressive about getting rid of GetLocals on captured variables
......
......@@ -50,7 +50,6 @@ all : \
NumberConstructor.lut.h \
NumberPrototype.lut.h \
ObjectConstructor.lut.h \
ObjectPrototype.lut.h \
RegExpConstructor.lut.h \
RegExpPrototype.lut.h \
RegExpJitTables.h \
......
......@@ -20,7 +20,6 @@ LUT_FILES += \
runtime/NumberConstructor.cpp \
runtime/NumberPrototype.cpp \
runtime/ObjectConstructor.cpp \
runtime/ObjectPrototype.cpp \
runtime/RegExpConstructor.cpp \
runtime/RegExpObject.cpp \
runtime/RegExpPrototype.cpp \
......
......@@ -24,7 +24,6 @@ javascriptcore_built_nosources += \
DerivedSources/JavaScriptCore/NumberConstructor.lut.h \
DerivedSources/JavaScriptCore/NumberPrototype.lut.h \
DerivedSources/JavaScriptCore/ObjectConstructor.lut.h \
DerivedSources/JavaScriptCore/ObjectPrototype.lut.h \
DerivedSources/JavaScriptCore/RegExpConstructor.lut.h \
DerivedSources/JavaScriptCore/RegExpObject.lut.h \
DerivedSources/JavaScriptCore/RegExpPrototype.lut.h \
......
......@@ -424,19 +424,17 @@ EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue e
if (LIKELY(baseValue.isCell())) {
JSCell* base = baseValue.asCell();
if (property.isUInt32()) {
if (property.isUInt32())
return getByVal(exec, base, property.asUInt32());
} else if (property.isDouble()) {
if (property.isDouble()) {
double propertyAsDouble = property.asDouble();
uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
if (propertyAsUInt32 == propertyAsDouble)
return getByVal(exec, base, propertyAsUInt32);
} else if (property.isString()) {
if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
return JSValue::encode(result);
}
} else if (property.isString())
return JSValue::encode(base->getByString(exec, asString(property)->value(exec)));
}
if (isName(property))
return JSValue::encode(baseValue.get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
......@@ -453,15 +451,13 @@ EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base
if (property.isUInt32())
return getByVal(exec, base, property.asUInt32());
if (property.isDouble()) {
else if (property.isDouble()) {
double propertyAsDouble = property.asDouble();
uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
if (propertyAsUInt32 == propertyAsDouble)
return getByVal(exec, base, propertyAsUInt32);
} else if (property.isString()) {
if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
return JSValue::encode(result);
}
} else if (property.isString())
return JSValue::encode(base->getByString(exec, asString(property)->value(exec)));
if (isName(property))
return JSValue::encode(JSValue(base).get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
......
......@@ -90,7 +90,6 @@ namespace JSC {
static const HashTable* numberConstructorTable(CallFrame* callFrame) { return callFrame->globalData().numberConstructorTable; }
static const HashTable* numberPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().numberPrototypeTable; }
static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->globalData().objectConstructorTable; }
static const HashTable* objectPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().objectPrototypeTable; }
static const HashTable* privateNamePrototypeTable(CallFrame* callFrame) { return callFrame->globalData().privateNamePrototypeTable; }
static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
......
......@@ -2417,10 +2417,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
static JSValue getByVal(
CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
{
if (LIKELY(baseValue.isCell() && subscript.isString())) {
if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame)))
return result;
}
if (LIKELY(baseValue.isCell() && subscript.isString()))
return baseValue.asCell()->getByString(callFrame, asString(subscript)->value(callFrame));
if (subscript.isUInt32()) {
uint32_t i = subscript.asUInt32();
......
......@@ -1060,10 +1060,8 @@ LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
{
if (LIKELY(baseValue.isCell() && subscript.isString())) {
if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
return result;
}
if (LIKELY(baseValue.isCell() && subscript.isString()))
return baseValue.asCell()->getByString(exec, asString(subscript)->value(exec));
if (subscript.isUInt32()) {
uint32_t i = subscript.asUInt32();
......
......@@ -99,7 +99,11 @@
macro(valueOf) \
macro(writable) \
macro(displayName) \
macro(join)
macro(join) \
macro(__defineGetter__) \
macro(__defineSetter__) \
macro(__lookupGetter__) \
macro(__lookupSetter__)
#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
macro(null) \
......
......@@ -227,4 +227,10 @@ bool JSCell::getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, Prope
return false;
}
JSValue JSCell::getByStringSlow(ExecState* exec, const String& name)
{
Identifier ident(&exec->globalData(), name);
return JSValue(this).get(exec, ident);
}
} // namespace JSC
......@@ -122,7 +122,8 @@ public:
// call this function, not its slower virtual counterpart. (For integer
// property names, we want a similar interface with appropriate optimizations.)
bool fastGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
JSValue fastGetOwnProperty(ExecState*, const String&);
JSValue getByString(ExecState*, const String&);
static ptrdiff_t structureOffset()
{
......@@ -161,6 +162,10 @@ protected:
private:
friend class LLIntOffsetsExtractor;
template<typename KeyType>
JSValue getByStringAndKey(ExecState*, const String&, const KeyType&);
JSValue getByStringSlow(ExecState*, const String&);
WriteBarrier<Structure> m_structure;
};
......
......@@ -169,20 +169,46 @@ ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName
return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot);
}
template<typename KeyType>
ALWAYS_INLINE JSValue JSCell::getByStringAndKey(ExecState* exec, const String& name, const KeyType& key)
{
JSCell* cell = this;
while (true) {
if (UNLIKELY(cell->structure()->typeInfo().overridesGetOwnPropertySlot()))
return getByStringSlow(exec, name);
unsigned attributes;
PropertyOffset offset = cell->structure()->get(exec->globalData(), key, attributes);
if (offset != invalidOffset) {
if (attributes & Accessor)
return cell->getByStringSlow(exec, name);
return asObject(cell)->getDirect(offset);
}
JSValue prototype = cell->structure()->storedPrototype();
if (!prototype.isObject())
break;
cell = asObject(prototype);
}
// Make sure we aren't going after indexed storage, and if we are, then just use that.
unsigned index = toUInt32FromStringImpl(name.impl());
if (index == PropertyName::NotAnIndex)
return jsUndefined();
return JSValue(this).get(exec, index);
}
// Fast call to get a property where we may not yet have converted the string to an
// identifier. The first time we perform a property access with a given string, try
// performing the property map lookup without forming an identifier. We detect this
// case by checking whether the hash has yet been set for this string.
ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name)
{
if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) {
PropertyOffset offset = name.impl()->hasHash()
? structure()->get(exec->globalData(), Identifier(exec, name))
: structure()->get(exec->globalData(), name);
if (offset != invalidOffset)
return asObject(this)->locationForOffset(offset)->get();
}
return JSValue();
ALWAYS_INLINE JSValue JSCell::getByString(ExecState* exec, const String& name)
{
if (name.impl()->hasHash())
return getByStringAndKey(exec, name, Identifier(exec, name));
return getByStringAndKey(exec, name, name);
}
inline bool JSCell::toBoolean(ExecState* exec) const
......
......@@ -93,7 +93,6 @@ extern const HashTable mathTable;
extern const HashTable numberConstructorTable;
extern const HashTable numberPrototypeTable;
JS_EXPORTDATA extern const HashTable objectConstructorTable;
extern const HashTable objectPrototypeTable;
extern const HashTable privateNamePrototypeTable;
extern const HashTable regExpTable;
extern const HashTable regExpConstructorTable;
......@@ -155,7 +154,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
, numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
, objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
, objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
, privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable))
, regExpTable(fastNew<HashTable>(JSC::regExpTable))
, regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
......@@ -286,7 +284,6 @@ JSGlobalData::~JSGlobalData()
numberConstructorTable->deleteTable();
numberPrototypeTable->deleteTable();
objectConstructorTable->deleteTable();
objectPrototypeTable->deleteTable();
privateNamePrototypeTable->deleteTable();
regExpTable->deleteTable();
regExpConstructorTable->deleteTable();
......@@ -306,7 +303,6 @@ JSGlobalData::~JSGlobalData()
fastDelete(const_cast<HashTable*>(numberConstructorTable));
fastDelete(const_cast<HashTable*>(numberPrototypeTable));
fastDelete(const_cast<HashTable*>(objectConstructorTable));
fastDelete(const_cast<HashTable*>(objectPrototypeTable));
fastDelete(const_cast<HashTable*>(privateNamePrototypeTable));
fastDelete(const_cast<HashTable*>(regExpTable));
fastDelete(const_cast<HashTable*>(regExpConstructorTable));
......
......@@ -223,7 +223,6 @@ namespace JSC {
const HashTable* numberConstructorTable;
const HashTable* numberPrototypeTable;
const HashTable* objectConstructorTable;
const HashTable* objectPrototypeTable;
const HashTable* privateNamePrototypeTable;
const HashTable* regExpTable;
const HashTable* regExpConstructorTable;
......
......@@ -2202,6 +2202,16 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV
}
}
void JSObject::putDirectNativeFunction(ExecState* exec, JSGlobalObject* globalObject, const PropertyName& propertyName, unsigned functionLength, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes)
{
StringImpl* name = propertyName.publicName();
ASSERT(name);
JSFunction* function =
JSFunction::create(exec, globalObject, functionLength, name, nativeFunction, intrinsic);
putDirect(exec->globalData(), propertyName, function, attributes);
}
ALWAYS_INLINE unsigned JSObject::getNewVectorLength(unsigned currentVectorLength, unsigned currentLength, unsigned desiredLength)
{
ASSERT(desiredLength <= MAX_STORAGE_VECTOR_LENGTH);
......
......@@ -565,6 +565,8 @@ public:
void putDirect(JSGlobalData& globalData, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(globalData, this, value); }
void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
void putDirectNativeFunction(ExecState*, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
bool isGlobalObject() const;
......@@ -700,7 +702,7 @@ protected:
ASSERT(structure()->isObject());
ASSERT(classInfo());
}
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
......@@ -909,6 +911,7 @@ private:
// Nobody should ever ask any of these questions on something already known to be a JSObject.
using JSCell::isAPIValueWrapper;
using JSCell::isGetterSetter;
void getObject();
void getString(ExecState* exec);
void isObject();
......@@ -1449,6 +1452,14 @@ inline int offsetRelativeToBase(PropertyOffset offset)
COMPILE_ASSERT(!(sizeof(JSObject) % sizeof(WriteBarrierBase<Unknown>)), JSObject_inline_storage_has_correct_alignment);
// Helper for defining native functions, if you're not using a static hash table.
// Use this macro from within finishCreation() methods in prototypes. This assumes
// you've defined variables called exec, globalObject, and globalData, and they
// have the expected meanings. This also assumes that the function you're defining
// doesn't have an intrinsic.
#define JSC_NATIVE_FUNCTION(jsName, cppName, attributes, length) \
putDirectNativeFunction(exec, globalObject, globalData.propertyNames->jsName, (length), cppName, NoIntrinsic, (attributes))
} // namespace JSC
#endif // JSObject_h
......@@ -77,11 +77,9 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
if (thisObj->staticFunctionsReified())
return false;
StringImpl* name = propertyName.publicName();
ASSERT(name);
JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), name, entry->function(), entry->intrinsic());
thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes());
thisObj->putDirectNativeFunction(
exec, thisObj->globalObject(), propertyName, entry->functionLength(),
entry->function(), entry->intrinsic(), entry->attributes());
offset = thisObj->getDirectOffset(exec->globalData(), propertyName);
ASSERT(isValidOffset(offset));
}
......
......@@ -40,51 +40,40 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
}
#include "ObjectPrototype.lut.h"
namespace JSC {
ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectPrototype);
const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable, CREATE_METHOD_TABLE(ObjectPrototype) };
/* Source for ObjectPrototype.lut.h
@begin objectPrototypeTable
toString objectProtoFuncToString DontEnum|Function 0
toLocaleString objectProtoFuncToLocaleString DontEnum|Function 0
valueOf objectProtoFuncValueOf DontEnum|Function 0
hasOwnProperty objectProtoFuncHasOwnProperty DontEnum|Function 1
propertyIsEnumerable objectProtoFuncPropertyIsEnumerable DontEnum|Function 1
isPrototypeOf objectProtoFuncIsPrototypeOf DontEnum|Function 1
__defineGetter__ objectProtoFuncDefineGetter DontEnum|Function 2
__defineSetter__ objectProtoFuncDefineSetter DontEnum|Function 2
__lookupGetter__ objectProtoFuncLookupGetter DontEnum|Function 1
__lookupSetter__ objectProtoFuncLookupSetter DontEnum|Function 1
@end
*/
const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ObjectPrototype) };
ObjectPrototype::ObjectPrototype(ExecState* exec, Structure* stucture)
: JSNonFinalObject(exec->globalData(), stucture)
{
}
void ObjectPrototype::finishCreation(JSGlobalData& globalData, JSGlobalObject*)
void ObjectPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject)
{
JSGlobalData& globalData = exec->globalData();
Base::finishCreation(globalData);
ASSERT(inherits(&s_info));
globalData.prototypeMap.addPrototype(this);
JSC_NATIVE_FUNCTION(toString, objectProtoFuncToString, DontEnum, 0);
JSC_NATIVE_FUNCTION(toLocaleString, objectProtoFuncToLocaleString, DontEnum, 0);
JSC_NATIVE_FUNCTION(valueOf, objectProtoFuncValueOf, DontEnum, 0);
JSC_NATIVE_FUNCTION(hasOwnProperty, objectProtoFuncHasOwnProperty, DontEnum, 1);
JSC_NATIVE_FUNCTION(propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable, DontEnum, 1);
JSC_NATIVE_FUNCTION(isPrototypeOf, objectProtoFuncIsPrototypeOf, DontEnum, 1);
JSC_NATIVE_FUNCTION(__defineGetter__, objectProtoFuncDefineGetter, DontEnum, 2);
JSC_NATIVE_FUNCTION(__defineSetter__, objectProtoFuncDefineSetter, DontEnum, 2);
JSC_NATIVE_FUNCTION(__lookupGetter__, objectProtoFuncLookupGetter, DontEnum, 1);
JSC_NATIVE_FUNCTION(__lookupSetter__, objectProtoFuncLookupSetter, DontEnum, 1);
}