Skip to content
Permalink
Browse files
Unreviewed, rolling in r201436.
https://bugs.webkit.org/show_bug.cgi?id=158143

r201562 should haved fixed the Dromaeo DOM core regression.

Restored changeset:

"REGRESSION: JSBench spends a lot of time transitioning
to/from dictionary"
https://bugs.webkit.org/show_bug.cgi?id=158045
http://trac.webkit.org/changeset/201436


Canonical link: https://commits.webkit.org/176365@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@201573 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
geoffreygaren committed Jun 1, 2016
1 parent bcbf356 commit 273fe323e28098af54bf2df64cc1acf50099ed49
@@ -1,3 +1,18 @@
2016-06-01 Geoffrey Garen <ggaren@apple.com>

Unreviewed, rolling in r201436.
https://bugs.webkit.org/show_bug.cgi?id=158143

r201562 should haved fixed the Dromaeo DOM core regression.

Restored changeset:

"REGRESSION: JSBench spends a lot of time transitioning
to/from dictionary"
https://bugs.webkit.org/show_bug.cgi?id=158045
http://trac.webkit.org/changeset/201436


2016-06-01 Commit Queue <commit-queue@webkit.org>

Unreviewed, rolling out r201488.
@@ -251,12 +251,18 @@ ObjectPropertyConditionSet generateConditions(
JSObject* object = jsCast<JSObject*>(value);
structure = object->structure(vm);

// Since we're accessing a prototype repeatedly, it's a good bet that it should not be
// treated as a dictionary.
if (structure->isDictionary()) {
if (concurrency == MainThread)
if (concurrency == MainThread) {
if (structure->hasBeenFlattenedBefore()) {
if (verbose)
dataLog("Dictionary has been flattened before, so invalid.\n");
return ObjectPropertyConditionSet::invalid();
}

if (verbose)
dataLog("Flattening ", pointerDump(structure));
structure->flattenDictionaryStructure(vm, object);
else {
} else {
if (verbose)
dataLog("Cannot flatten dictionary when not on main thread, so invalid.\n");
return ObjectPropertyConditionSet::invalid();
@@ -941,6 +941,9 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, J
if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
return throwTerminatedExecutionException(callFrame);

if (scope->structure()->isUncacheableDictionary())
scope->flattenDictionaryObject(vm);

ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.

ProtoCallFrame protoCallFrame;
@@ -1189,6 +1192,9 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
}
}

if (variableObject->structure()->isUncacheableDictionary())
variableObject->flattenDictionaryObject(vm);

if (numVariables || numFunctions) {
BatchedTransitionOptimizer optimizer(vm, variableObject);
if (variableObject->next())
@@ -1246,6 +1252,9 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
return throwTerminatedExecutionException(callFrame);

if (scope->structure()->isUncacheableDictionary())
scope->flattenDictionaryObject(vm);

ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.

// The |this| of the module is always `undefined`.
@@ -35,22 +35,10 @@ class BatchedTransitionOptimizer {
WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer);
public:
BatchedTransitionOptimizer(VM& vm, JSObject* object)
: m_vm(&vm)
, m_object(object)
{
if (!m_object->structure(vm)->isDictionary())
m_object->convertToDictionary(vm);
if (!object->structure(vm)->isDictionary())
object->convertToDictionary(vm);
}

~BatchedTransitionOptimizer()
{
if (m_object->structure()->isDictionary())
m_object->flattenDictionaryObject(*m_vm);
}

private:
VM* m_vm;
JSObject* m_object;
};

} // namespace JSC
@@ -319,6 +319,8 @@ void JSGlobalObject::init(VM& vm)
{
ASSERT(vm.currentThreadIsHoldingAPILock());

Base::setStructure(vm, Structure::toCacheableDictionaryTransition(vm, structure()));

JSGlobalObject::globalExec()->init(0, 0, CallFrame::noCaller(), 0, 0);

m_debugger = 0;
@@ -120,4 +120,27 @@ bool jsIsFunctionType(JSValue v)
return false;
}

size_t normalizePrototypeChain(CallFrame* callFrame, Structure* structure)
{
VM& vm = callFrame->vm();
size_t count = 0;
while (1) {
if (structure->isProxy())
return InvalidPrototypeChain;
JSValue v = structure->prototypeForLookup(callFrame);
if (v.isNull())
return count;

JSCell* base = v.asCell();
structure = base->structure(vm);
if (structure->isDictionary()) {
if (structure->hasBeenFlattenedBefore())
return InvalidPrototypeChain;
structure->flattenDictionaryStructure(vm, asObject(base));
}

++count;
}
}

} // namespace JSC
@@ -28,11 +28,14 @@

namespace JSC {

#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())

NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
JSValue jsTypeStringForValue(CallFrame*, JSValue);
JSValue jsTypeStringForValue(VM&, JSGlobalObject*, JSValue);
bool jsIsObjectTypeOrNull(CallFrame*, JSValue);
bool jsIsFunctionType(JSValue);
size_t normalizePrototypeChain(CallFrame*, Structure*);

ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
{
@@ -192,30 +195,6 @@ ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
return jsAddSlowCase(callFrame, v1, v2);
}

#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())

inline size_t normalizePrototypeChain(CallFrame* callFrame, Structure* structure)
{
VM& vm = callFrame->vm();
size_t count = 0;
while (1) {
if (structure->isProxy())
return InvalidPrototypeChain;
JSValue v = structure->prototypeForLookup(callFrame);
if (v.isNull())
return count;

JSCell* base = v.asCell();
structure = base->structure(vm);
// Since we're accessing a prototype in a loop, it's a good bet that it
// should not be treated as a dictionary.
if (structure->isDictionary())
structure->flattenDictionaryStructure(vm, asObject(base));

++count;
}
}

} // namespace JSC

#endif // Operations_h

0 comments on commit 273fe32

Please sign in to comment.