]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/JSActivation.cpp
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / JSActivation.cpp
index a2d26347c51c780a178597eed94e7d81865cbd48..09d985afbcfb593d5fbd04599a2a682b5f17f05d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -37,62 +37,116 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
-const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
+const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 };
 
-JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
-    : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame))
+JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
+    : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
+    , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))
+    , m_numCapturedVars(functionExecutable->capturedVariableCount())
+    , m_requiresDynamicChecks(functionExecutable->usesEval())
+    , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
 {
+    ASSERT(inherits(&s_info));
+
+    // We have to manually ref and deref the symbol table as JSVariableObject
+    // doesn't know about SharedSymbolTable
+    static_cast<SharedSymbolTable*>(m_symbolTable)->ref();
 }
 
 JSActivation::~JSActivation()
 {
-    delete d();
+    static_cast<SharedSymbolTable*>(m_symbolTable)->deref();
 }
 
-void JSActivation::mark()
+void JSActivation::visitChildren(SlotVisitor& visitor)
 {
-    Base::mark();
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(visitor);
 
-    Register* registerArray = d()->registerArray.get();
+    // No need to mark our registers if they're still in the RegisterFile.
+    WriteBarrier<Unknown>* registerArray = m_registerArray.get();
     if (!registerArray)
         return;
 
-    size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
+    visitor.appendValues(registerArray, m_numParametersMinusThis);
 
-    size_t i = 0;
-    size_t count = numParametersMinusThis; 
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
-    }
+    // Skip the call frame, which sits between the parameters and vars.
+    visitor.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues);
+}
 
-    size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
+{
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (entry.isNull())
+        return false;
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
 
-    // Skip the call frame, which sits between the parameters and vars.
-    i += RegisterFile::CallFrameHeaderSize;
-    count += RegisterFile::CallFrameHeaderSize + numVars;
+    slot.setValue(registerAt(entry.getIndex()).get());
+    return true;
+}
 
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
+inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
+{
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (entry.isNull())
+        return false;
+    if (entry.isReadOnly())
+        return true;
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
+
+    registerAt(entry.getIndex()).set(globalData, this, value);
+    return true;
+}
+
+void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    SymbolTable::const_iterator end = symbolTable().end();
+    for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+        if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
+            continue;
+        if (it->second.getIndex() >= m_numCapturedVars)
+            continue;
+        propertyNames.add(Identifier(exec, it->first.get()));
     }
+    // Skip the JSVariableObject implementation of getOwnPropertyNames
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+inline bool JSActivation::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.impl());
+    if (iter == symbolTable().end())
+        return false;
+    SymbolTableEntry& entry = iter->second;
+    ASSERT(!entry.isNull());
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
+
+    entry.setAttributes(attributes);
+    registerAt(entry.getIndex()).set(globalData, this, value);
+    return true;
 }
 
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    if (symbolTableGet(propertyName, slot))
+    if (propertyName == exec->propertyNames().arguments) {
+        slot.setCustom(this, getArgumentsGetter());
         return true;
+    }
 
-    if (JSValuePtr* location = getDirectLocation(propertyName)) {
-        slot.setValueSlot(location);
+    if (symbolTableGet(propertyName, slot))
         return true;
-    }
 
-    // Only return the built-in arguments object if it wasn't overridden above.
-    if (propertyName == exec->propertyNames().arguments) {
-        slot.setCustom(this, getArgumentsGetter());
+    if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
+        slot.setValue(location->get());
         return true;
     }
 
@@ -103,26 +157,26 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert
     return false;
 }
 
-void JSActivation::put(ExecState*, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
+void JSActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePut(propertyName, value))
+    if (symbolTablePut(exec->globalData(), propertyName, value))
         return;
 
     // We don't call through to JSObject because __proto__ and getter/setter 
     // properties are non-standard extensions that other implementations do not
     // expose in the activation object.
     ASSERT(!hasGetterSetterProperties());
-    putDirect(propertyName, value, 0, true, slot);
+    putDirect(exec->globalData(), propertyName, value, 0, true, slot);
 }
 
 // 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));
 
-    if (symbolTablePutWithAttributes(propertyName, value, attributes))
+    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
 
     // We don't call through to JSObject because __proto__ and getter/setter 
@@ -130,7 +184,7 @@ void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName,
     // 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)
@@ -146,31 +200,32 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const
     return exec->globalThisValue();
 }
 
-bool JSActivation::isDynamicScope() const
+JSValue JSActivation::toStrictThisObject(ExecState*) const
 {
-    return d()->functionBody->usesEval();
+    return jsNull();
 }
-
-JSValuePtr JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+    
+bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
 {
-    JSActivation* activation = asActivation(slot.slotBase());
-
-    if (activation->d()->functionBody->usesArguments()) {
-        PropertySlot slot;
-        activation->symbolTableGet(exec->propertyNames().arguments, slot);
-        return slot.getValue(exec, exec->propertyNames().arguments);
-    }
-
-    CallFrame* callFrame = CallFrame::create(activation->d()->registers);
-    Arguments* arguments = callFrame->optionalCalleeArguments();
-    if (!arguments) {
-        arguments = new (callFrame) Arguments(callFrame);
-        arguments->copyRegisters();
-        callFrame->setCalleeArguments(arguments);
-    }
-    ASSERT(arguments->isObject(&Arguments::info));
+    requiresDynamicChecks = m_requiresDynamicChecks;
+    return false;
+}
 
-    return arguments;
+JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
+{
+    JSActivation* activation = asActivation(slotBase);
+    CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers));
+    int argumentsRegister = activation->m_argumentsRegister;
+    if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
+        return arguments;
+    int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
+
+    JSValue arguments = JSValue(new (callFrame) Arguments(callFrame));
+    callFrame->uncheckedR(argumentsRegister) = arguments;
+    callFrame->uncheckedR(realArgumentsRegister) = arguments;
+    
+    ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::s_info));
+    return callFrame->uncheckedR(realArgumentsRegister).jsValue();
 }
 
 // These two functions serve the purpose of isolating the common case from a