#include "JSObject.h"
#include "Register.h"
#include "SymbolTable.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/UnusedParam.h>
namespace JSC {
+ class LLIntOffsetsExtractor;
class Register;
- class JSVariableObject : public JSObject {
+ class JSVariableObject : public JSNonFinalObject {
friend class JIT;
+ friend class LLIntOffsetsExtractor;
public:
- SymbolTable& symbolTable() const { return *d->symbolTable; }
+ typedef JSNonFinalObject Base;
+
+ SymbolTable& symbolTable() const { return *m_symbolTable; }
+
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
- virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
+ static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
- virtual bool deleteProperty(ExecState*, const Identifier&);
- virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- virtual bool isVariableObject() const;
- virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0;
+ bool isDynamicScope(bool& requiresDynamicChecks) const;
- Register& registerAt(int index) const { return d->registers[index]; }
+ WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
- static PassRefPtr<Structure> createStructure(JSValue prototype)
+ WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+ static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
+
+ static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info);
}
protected:
- static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
- // Subclasses of JSVariableObject can subclass this struct to add data
- // without increasing their own size (since there's a hard limit on the
- // size of a JSCell).
- struct JSVariableObjectData {
- JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
- : symbolTable(symbolTable)
- , registers(registers)
- {
- ASSERT(symbolTable);
- }
-
- SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
- Register* registers; // "r" in the register file.
- OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
-
- private:
- JSVariableObjectData(const JSVariableObjectData&);
- JSVariableObjectData& operator=(const JSVariableObjectData&);
- };
-
- JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
- : JSObject(structure)
- , d(data) // Subclass owns this pointer.
+ static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
+
+ JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
+ : JSNonFinalObject(globalData, structure)
+ , m_symbolTable(symbolTable)
+ , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
{
}
- Register* copyRegisterArray(Register* src, size_t count);
- void setRegisters(Register* r, Register* registerArray);
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ ASSERT(m_symbolTable);
+ COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
+ }
+
+ PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts);
+ void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
bool symbolTableGet(const Identifier&, PropertySlot&);
- bool symbolTableGet(const Identifier&, PropertyDescriptor&);
+ JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
- bool symbolTablePut(const Identifier&, JSValue);
- bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
+ bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow);
+ bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
- JSVariableObjectData* d;
+ SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
+ WriteBarrier<Unknown>* m_registers; // "r" in the register file.
+ OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
};
inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
{
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
- slot.setRegisterSlot(®isterAt(entry.getIndex()));
+ slot.setValue(registerAt(entry.getIndex()).get());
return true;
}
return false;
inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
{
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (!entry.isNull()) {
- slot.setRegisterSlot(®isterAt(entry.getIndex()));
+ slot.setValue(registerAt(entry.getIndex()).get());
slotIsWriteable = !entry.isReadOnly();
return true;
}
return false;
}
- inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue value)
+ inline bool JSVariableObject::symbolTablePut(ExecState* exec, const Identifier& propertyName, JSValue value, bool shouldThrow)
{
+ JSGlobalData& globalData = exec->globalData();
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
if (entry.isNull())
return false;
- if (entry.isReadOnly())
+ if (entry.isReadOnly()) {
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return true;
- registerAt(entry.getIndex()) = value;
+ }
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
- inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
+ inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
- SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
+ SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
if (iter == symbolTable().end())
return false;
SymbolTableEntry& entry = iter->second;
ASSERT(!entry.isNull());
entry.setAttributes(attributes);
- registerAt(entry.getIndex()) = value;
+ registerAt(entry.getIndex()).set(globalData, this, value);
return true;
}
- inline Register* JSVariableObject::copyRegisterArray(Register* src, size_t count)
+ inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts)
{
- Register* registerArray = new Register[count];
- memcpy(registerArray, src, count * sizeof(Register));
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]);
+ for (size_t i = 0; i < callframeStarts; i++)
+ registerArray[i].set(globalData, this, src[i].get());
+ for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++)
+ registerArray[i].set(globalData, this, src[i].get());
- return registerArray;
+ return registerArray.release();
}
- inline void JSVariableObject::setRegisters(Register* registers, Register* registerArray)
+ inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray)
{
- ASSERT(registerArray != d->registerArray.get());
- d->registerArray.set(registerArray);
- d->registers = registers;
+ ASSERT(registerArray != m_registerArray);
+ m_registerArray = registerArray;
+ m_registers = registers;
}
} // namespace JSC