+2012-06-30 Zan Dobersek <zandobersek@gmail.com>
+
+ Unreviewed, rolling out r121605.
+ http://trac.webkit.org/changeset/121605
+ https://bugs.webkit.org/show_bug.cgi?id=90336
+
+ Changes caused flaky crashes in sputnik/Unicode tests on Apple
+ WK1 and GTK Linux builders
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileSlowCases):
+ * jit/JIT.h:
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateBasicJSObject):
+ (JSC::JIT::emitAllocateJSFinalObject):
+ (JSC):
+ (JSC::JIT::emitAllocateJSFunction):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_new_func):
+ (JSC::JIT::emitSlow_op_new_func):
+ (JSC):
+ (JSC::JIT::emit_op_new_func_exp):
+ (JSC::JIT::emitSlow_op_new_func_exp):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::finishCreation):
+ * runtime/JSObject.h:
+ (JSC::JSObject::isUsingInlineStorage):
+ (JSObject):
+ (JSC::JSObject::finishCreation):
+ (JSC):
+ (JSNonFinalObject):
+ (JSC::JSNonFinalObject::JSNonFinalObject):
+ (JSC::JSNonFinalObject::finishCreation):
+ (JSFinalObject):
+ (JSC::JSFinalObject::finishCreation):
+ (JSC::JSObject::offsetOfInlineStorage):
+ (JSC::JSObject::setPropertyStorage):
+ (JSC::Structure::isUsingInlineStorage):
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::putDirectWithoutTransition):
+ (JSC::JSObject::transitionTo):
+ * runtime/Structure.cpp:
+ (JSC::Structure::Structure):
+ (JSC):
+ (JSC::Structure::growPropertyStorageCapacity):
+ (JSC::Structure::suggestedNewPropertyStorageSize):
+ * runtime/Structure.h:
+ (JSC::Structure::shouldGrowPropertyStorage):
+ (JSC::Structure::propertyStorageSize):
+
2012-06-29 Mark Hahnenberg <mhahnenberg@apple.com>
Remove warning about protected values when the Heap is being destroyed
/*
- * Copyright (C) 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
}
}
- baseObject->setStructureAndReallocateStorageIfNecessary(*globalData, newStructure);
+ baseObject->transitionTo(*globalData, newStructure);
int value = vPC[3].u.operand;
unsigned offset = vPC[7].u.operand;
/*
- * Copyright (C) 2008, 2009, 2012 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
DEFINE_SLOWCASE_OP(op_neq)
DEFINE_SLOWCASE_OP(op_new_array)
DEFINE_SLOWCASE_OP(op_new_object)
+ DEFINE_SLOWCASE_OP(op_new_func)
+ DEFINE_SLOWCASE_OP(op_new_func_exp)
DEFINE_SLOWCASE_OP(op_not)
DEFINE_SLOWCASE_OP(op_nstricteq)
DEFINE_SLOWCASE_OP(op_post_dec)
/*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * 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
template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
void emitAllocateBasicStorage(size_t, RegisterID result, RegisterID storagePtr);
template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
+ void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr);
#if ENABLE(VALUE_PROFILER)
void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitSlow_op_new_array(Instruction*, Vector<SlowCaseEntry>::iterator&);
void emitRightShift(Instruction*, bool isUnsigned);
/*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * 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
storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
// initialize the object's property storage pointer
- if (ClassType::hasInlineStorage()) {
- addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
- storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
- } else
- storePtr(TrustedImmPtr(0), Address(result, ClassType::offsetOfPropertyStorage()));
+ addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
+ storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
}
template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch);
}
+inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
+{
+ emitAllocateBasicJSObject<JSFunction, true>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
+
+ // store the function's scope chain
+ storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
+
+ // store the function's executable member
+ storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
+
+ // clear the function's inheritorID
+ storePtr(TrustedImmPtr(0), Address(result, JSFunction::offsetOfCachedInheritorID()));
+
+ // store the function's name
+ ASSERT(executable->nameValue());
+ int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
+ storePtr(TrustedImmPtr(executable->nameValue()), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#if USE(JSVALUE32_64)
+ store32(TrustedImm32(JSValue::CellTag), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
+}
+
inline void JIT::emitAllocateBasicStorage(size_t size, RegisterID result, RegisterID storagePtr)
{
CopiedAllocator* allocator = &m_globalData->heap.storageAllocator();
/*
- * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
*
* Redistribution and use in source and binary forms, with or without
#endif
}
- JITStubCall stubCall(this, cti_op_new_func);
- stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
- stubCall.call(dst);
+ FunctionExecutable* executable = m_codeBlock->functionDecl(currentInstruction[2].u.operand);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+ emitAllocateJSFunction(executable, regT2, regT0, regT1);
+
+ emitStoreCell(dst, regT0);
if (currentInstruction[3].u.operand) {
#if USE(JSVALUE32_64)
}
}
+void JIT::emitSlow_op_new_func(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_new_func);
+ stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
{
+ FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+
+ // We only inline the allocation of a anonymous function expressions
+ // If we want to be able to allocate a named function expression, we would
+ // need to be able to do inline allocation of a JSStaticScopeObject.
+ if (executable->name().isNull()) {
+ emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+ emitAllocateJSFunction(executable, regT2, regT0, regT1);
+ emitStoreCell(currentInstruction[1].u.operand, regT0);
+ return;
+ }
+
JITStubCall stubCall(this, cti_op_new_func_exp);
stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
stubCall.call(currentInstruction[1].u.operand);
}
+void JIT::emitSlow_op_new_func_exp(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+ FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+ if (!executable->name().isNull())
+ return;
+ linkSlowCase(iter);
+ JITStubCall stubCall(this, cti_op_new_func_exp);
+ stubCall.addArgument(TrustedImmPtr(executable));
+ stubCall.call(currentInstruction[1].u.operand);
+}
+
void JIT::emit_op_new_array(Instruction* currentInstruction)
{
int length = currentInstruction[3].u.operand;
void JSFunction::finishCreation(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
{
- JSGlobalData& globalData = exec->globalData();
- Base::finishCreation(globalData);
+ Base::finishCreation(exec->globalData());
ASSERT(inherits(&s_info));
// Switching the structure here is only safe if we currently have the function structure!
ASSERT(structure() == scopeChainNode->globalObject->functionStructure());
- setStructureAndReallocateStorageIfNecessary(
- globalData,
- scopeChainNode->globalObject->namedFunctionStructure());
- putDirectOffset(globalData, scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
+ setStructure(exec->globalData(), scopeChainNode->globalObject->namedFunctionStructure());
+ putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
}
Structure* JSFunction::cacheInheritorID(ExecState* exec)
Accessor = 1 << 5, // property is a getter/setter
};
-#if USE(JSVALUE32_64)
-#define JSFinalObject_inlineStorageCapacity 6
-#else
-#define JSFinalObject_inlineStorageCapacity 4
-#endif
-
-COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= 0), final_storage_non_negative);
-
class JSObject : public JSCell {
friend class BatchedTransitionOptimizer;
friend class JIT;
void reifyStaticFunctionsForDelete(ExecState* exec);
JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
- bool isUsingInlineStorage() const
- {
- bool result =
- !m_propertyStorage.get()
- || static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1);
- ASSERT(result == structure()->isUsingInlineStorage());
- return result;
- }
+ bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); }
void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*);
-
- bool reallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*);
void* addressOfPropertyStorage()
{
return &m_propertyStorage;
}
+ static const unsigned baseExternalStorageCapacity = 16;
+
void flattenDictionaryObject(JSGlobalData& globalData)
{
structure()->flattenDictionaryStructure(globalData, this);
static JS_EXPORTDATA const ClassInfo s_info;
protected:
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(JSGlobalData& globalData, PropertyStorage inlineStorage)
{
Base::finishCreation(globalData);
ASSERT(inherits(&s_info));
- ASSERT(structure()->isUsingInlineStorage());
+ ASSERT(structure()->propertyStorageCapacity() < baseExternalStorageCapacity);
ASSERT(structure()->isEmpty());
ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
+ ASSERT_UNUSED(inlineStorage, static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
ASSERT(structure()->isObject());
ASSERT(classInfo());
}
};
+#if USE(JSVALUE32_64)
+#define JSNonFinalObject_inlineStorageCapacity 4
+#define JSFinalObject_inlineStorageCapacity 6
+#else
+#define JSNonFinalObject_inlineStorageCapacity 2
+#define JSFinalObject_inlineStorageCapacity 4
+#endif
+
+COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final);
+
// JSNonFinalObject is a type of JSObject that has some internal storage,
// but also preserves some space in the collector cell for additional
// data members in derived types.
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
- static bool hasInlineStorage()
- {
- return false;
- }
-
protected:
explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
- : JSObject(globalData, structure, 0)
+ : JSObject(globalData, structure, m_inlineStorage)
{
}
void finishCreation(JSGlobalData& globalData)
{
- Base::finishCreation(globalData);
- ASSERT(!this->structure()->propertyStorageCapacity());
+ Base::finishCreation(globalData, m_inlineStorage);
+ ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
+ ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
ASSERT(classInfo());
}
+
+ private:
+ WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
};
class JSFinalObject;
static JS_EXPORTDATA const ClassInfo s_info;
- static bool hasInlineStorage()
- {
- return true;
- }
protected:
void finishCreation(JSGlobalData& globalData)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(globalData, m_inlineStorage);
ASSERT(!(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double)));
ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
ASSERT(classInfo());
inline size_t JSObject::offsetOfInlineStorage()
{
+ ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
}
{
ASSERT(storage);
ASSERT(structure);
- ASSERT(!structure->isUsingInlineStorage()
- || (classInfo() == &JSFinalObject::s_info && static_cast<void*>(storage) == static_cast<void*>(this + 1)));
setStructure(globalData, structure);
m_propertyStorage.set(globalData, this, storage);
}
return createInheritorID(globalData);
}
-inline size_t Structure::inlineStorageCapacity() const
-{
- if (classInfo() == &JSFinalObject::s_info)
- return JSFinalObject_inlineStorageCapacity;
- return 0;
-}
-
inline bool Structure::isUsingInlineStorage() const
{
- ASSERT(propertyStorageCapacity() >= inlineStorageCapacity());
- return propertyStorageCapacity() == inlineStorageCapacity();
+ return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
}
inline bool JSCell::inherits(const ClassInfo* info) const
return false;
PropertyStorage newStorage = propertyStorage();
- if (structure()->putWillGrowPropertyStorage())
+ if (structure()->shouldGrowPropertyStorage())
newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
setPropertyStorage(globalData, newStorage, structure());
if ((mode == PutModePut) && !isExtensible())
return false;
+ PropertyStorage newStorage = propertyStorage();
+ if (structure()->shouldGrowPropertyStorage())
+ newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+
Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
-
- ASSERT(offset < structure->propertyStorageCapacity());
- setStructureAndReallocateStorageIfNecessary(globalData, structure);
+ ASSERT(offset < structure->propertyStorageCapacity());
+ setPropertyStorage(globalData, newStorage, structure);
putDirectOffset(globalData, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
return true;
}
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, unsigned oldCapacity, Structure* newStructure)
-{
- ASSERT(oldCapacity <= newStructure->propertyStorageCapacity());
-
- if (oldCapacity == newStructure->propertyStorageCapacity()) {
- setStructure(globalData, newStructure);
- return;
- }
-
- PropertyStorage newStorage = growPropertyStorage(
- globalData, oldCapacity, newStructure->suggestedNewPropertyStorageSize());
- setPropertyStorage(globalData, newStorage, newStructure);
-}
-
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, Structure* newStructure)
-{
- setStructureAndReallocateStorageIfNecessary(
- globalData, structure()->propertyStorageCapacity(), newStructure);
-}
-
inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(value);
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
PropertyStorage newStorage = propertyStorage();
- if (structure()->putWillGrowPropertyStorage())
+ if (structure()->shouldGrowPropertyStorage())
newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value));
setPropertyStorage(globalData, newStorage, structure());
putDirectOffset(globalData, offset, value);
}
+inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
+{
+ PropertyStorage newStorage = propertyStorage();
+ if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
+ newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+ setPropertyStorage(globalData, newStorage, newStructure);
+}
+
inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return methodTable()->defaultValue(this, exec, preferredType);
, m_prototype(globalData, this, prototype)
, m_classInfo(classInfo)
, m_transitionWatchpointSet(InitializedWatching)
- , m_propertyStorageCapacity(typeInfo.isFinalObject() ? JSFinalObject_inlineStorageCapacity : 0)
+ , m_propertyStorageCapacity(typeInfo.isFinalObject() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
, m_offset(noOffset)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
}
}
-inline size_t nextPropertyStorageCapacity(size_t currentCapacity)
-{
- if (!currentCapacity)
- return 4;
- return currentCapacity * 2;
-}
-
void Structure::growPropertyStorageCapacity()
{
- m_propertyStorageCapacity = nextPropertyStorageCapacity(m_propertyStorageCapacity);
+ if (isUsingInlineStorage())
+ m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
+ else
+ m_propertyStorageCapacity *= 2;
}
size_t Structure::suggestedNewPropertyStorageSize()
{
- return nextPropertyStorageCapacity(m_propertyStorageCapacity);
+ if (isUsingInlineStorage())
+ return JSObject::baseExternalStorageCapacity;
+ return m_propertyStorageCapacity * 2;
}
void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, PropertyName propertyName)
/*
- * Copyright (C) 2008, 2009, 2012 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
bool isFrozen(JSGlobalData&);
bool isExtensible() const { return !m_preventExtensions; }
bool didTransition() const { return m_didTransition; }
- bool putWillGrowPropertyStorage()
- {
- ASSERT(propertyStorageCapacity() >= propertyStorageSize());
-
- if (!m_propertyTable) {
- unsigned currentSize = static_cast<unsigned>(m_offset + 1);
- ASSERT(propertyStorageCapacity() >= currentSize);
- return currentSize == propertyStorageCapacity();
- }
-
- ASSERT(propertyStorageCapacity() >= m_propertyTable->propertyStorageSize());
- if (m_propertyTable->hasDeletedOffset())
- return false;
-
- ASSERT(propertyStorageCapacity() >= m_propertyTable->size());
- return m_propertyTable->size() == propertyStorageCapacity();
- }
+ bool shouldGrowPropertyStorage() { return propertyStorageCapacity() == propertyStorageSize(); }
JS_EXPORT_PRIVATE size_t suggestedNewPropertyStorageSize();
Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
void growPropertyStorageCapacity();
unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; }
unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
- size_t inlineStorageCapacity() const;
bool isUsingInlineStorage() const;
size_t get(JSGlobalData&, PropertyName);