inline bool JSLexicalEnvironment::symbolTablePut(ExecState* exec, PropertyName propertyName, JSValue value, bool shouldThrow) { VM& vm = exec->vm(); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); WriteBarrierBase<Unknown>* reg; WatchpointSet* set; { GCSafeConcurrentJITLocker locker(symbolTable()->m_lock, exec->vm().heap); SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.uid()); if (iter == symbolTable()->end(locker)) return false; ASSERT(!iter->value.isNull()); if (iter->value.isReadOnly()) { if (shouldThrow) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return true; } ScopeOffset offset = iter->value.scopeOffset(); // Defend against the inspector asking for a var after it has been optimized out. if (!isValid(offset)) return false; set = iter->value.watchpointSet(); reg = &variableAt(offset); } reg->set(vm, this, value); if (set) set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it. return true; }
bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) { ASSERT(thisObj->globalObject()); ASSERT(entry->attributes() & Function); WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName); if (!location) { // If a property is ever deleted from an object with a static table, then we reify // all static functions at that time - after this we shouldn't be re-adding anything. if (thisObj->staticFunctionsReified()) return false; JSFunction* function; JSGlobalObject* globalObject = thisObj->globalObject(); #if ENABLE(JIT) if (entry->generator() || entry->intrinsic() != DFG::NoIntrinsic) function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator(), entry->intrinsic())); else #endif function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, entry->function()); thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(exec->globalData(), propertyName); } slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location)); return true; }
bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { JSFunction* thisObject = static_cast<JSFunction*>(cell); if (thisObject->isHostFunction()) return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); if (propertyName == exec->propertyNames().prototype) { WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName); if (!location) { JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure()); prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum); PutPropertySlot slot; thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum, false, slot); location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype); } slot.setValue(thisObject, location->get(), thisObject->offsetForLocation(location)); } if (propertyName == exec->propertyNames().arguments) { if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); if (!result) { thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); ASSERT(result); } return result; } slot.setCacheableCustom(thisObject, argumentsGetter); return true; } if (propertyName == exec->propertyNames().length) { slot.setCacheableCustom(thisObject, lengthGetter); return true; } if (propertyName == exec->propertyNames().caller) { if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); if (!result) { thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); ASSERT(result); } return result; } slot.setCacheableCustom(thisObject, callerGetter); return true; } return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); }
inline bool JSActivation::symbolTablePutWithAttributes(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); WriteBarrierBase<Unknown>* reg; { ConcurrentJITLocker locker(symbolTable()->m_lock); SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.publicName()); if (iter == symbolTable()->end(locker)) return false; SymbolTableEntry& entry = iter->value; ASSERT(!entry.isNull()); if (!isValid(entry)) return false; entry.setAttributes(attributes); reg = ®isterAt(entry.getIndex()); } reg->set(vm, this, value); return true; }
inline bool JSLexicalEnvironment::symbolTablePutWithAttributes(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); WriteBarrierBase<Unknown>* reg; { ConcurrentJITLocker locker(symbolTable()->m_lock); SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.uid()); if (iter == symbolTable()->end(locker)) return false; SymbolTableEntry& entry = iter->value; ASSERT(!entry.isNull()); ScopeOffset offset = entry.scopeOffset(); if (!isValid(offset)) return false; entry.setAttributes(attributes); reg = &variableAt(offset); } reg->set(vm, this, value); return true; }