void Arguments::tearOff(CallFrame* callFrame) { if (isTornOff()) return; if (!m_numArguments) return; // Must be called for the same call frame from which it was created. ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == m_registers); m_registerArray = std::make_unique<WriteBarrier<Unknown>[]>(m_numArguments); m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; // If we have a captured argument that logically aliases activation storage, // but we optimize away the activation, the argument needs to tear off into // our storage. The simplest way to do this is to revert it to Normal status. if (m_slowArgumentData && !m_activation) { for (size_t i = 0; i < m_numArguments; ++i) { if (m_slowArgumentData->slowArguments[i].status != SlowArgument::Captured) continue; m_slowArgumentData->slowArguments[i].status = SlowArgument::Normal; m_slowArgumentData->slowArguments[i].index = CallFrame::argumentOffset(i); } } for (size_t i = 0; i < m_numArguments; ++i) trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i)); }
void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) { RELEASE_ASSERT(activation); if (isTornOff()) return; if (!m_numArguments) return; m_activation.set(exec->vm(), this, activation); tearOff(exec); }
inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertyDescriptor& descriptor) { SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName()); if (entry.isNull()) return false; // Defend against the inspector asking for a var after it has been optimized out. if (isTornOff() && !isValid(entry)) return false; descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes()); return true; }
inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertySlot& slot) { SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName()); if (entry.isNull()) return false; // Defend against the inspector asking for a var after it has been optimized out. if (isTornOff() && !isValid(entry)) return false; slot.setValue(this, DontEnum, registerAt(entry.getIndex()).get()); return true; }
void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { if (isTornOff()) return; if (!d->numArguments) return; d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); tearOffForInlineCallFrame( callFrame->globalData(), callFrame->registers() + inlineCallFrame->stackOffset, inlineCallFrame); }
void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { RELEASE_ASSERT(!inlineCallFrame->baselineCodeBlock()->needsActivation()); if (isTornOff()) return; if (!m_numArguments) return; m_registers = ®isterArray() - CallFrame::offsetFor(1) - 1; for (size_t i = 0; i < m_numArguments; ++i) { ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; trySetArgument(callFrame->vm(), i, recovery.recover(callFrame)); } }
void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { if (isTornOff()) return; if (!m_numArguments) return; m_registerArray = std::make_unique<WriteBarrier<Unknown>[]>(m_numArguments); m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; for (size_t i = 0; i < m_numArguments; ++i) { ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; trySetArgument(callFrame->vm(), i, recovery.recover(callFrame)); } }
void Arguments::tearOff(CallFrame* callFrame) { if (isTornOff()) return; if (!m_numArguments) return; // Must be called for the same call frame from which it was created. ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == m_registers); allocateRegisterArray(callFrame->vm()); m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; for (size_t i = 0; i < m_numArguments; ++i) { if (m_slowArgumentData && m_slowArgumentData->slowArguments()[i].status == SlowArgument::Captured) continue; trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i)); } }
inline bool JSActivation::symbolTablePut(ExecState* exec, PropertyName propertyName, JSValue value, bool shouldThrow) { VM& vm = exec->vm(); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName()); if (entry.isNull()) return false; if (entry.isReadOnly()) { if (shouldThrow) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return true; } // Defend against the inspector asking for a var after it has been optimized out. if (isTornOff() && !isValid(entry)) return false; registerAt(entry.getIndex()).set(vm, this, value); return true; }
void Arguments::tearOff(CallFrame* callFrame) { if (isTornOff()) return; if (!d->numArguments) return; // Must be called for the same call frame from which it was created. ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == d->registers); d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); if (!callFrame->isInlineCallFrame()) { for (size_t i = 0; i < d->numArguments; ++i) argument(i).set(callFrame->globalData(), this, callFrame->argument(i)); return; } tearOffForInlineCallFrame( callFrame->globalData(), callFrame->registers(), callFrame->inlineCallFrame()); }