ClonedArguments* ClonedArguments::createEmpty( VM& vm, Structure* structure, JSFunction* callee, unsigned length) { unsigned vectorLength = length; if (vectorLength > MAX_STORAGE_VECTOR_LENGTH) return 0; Butterfly* butterfly; if (UNLIKELY(structure->needsSlowPutIndexing())) { butterfly = createArrayStorageButterfly(vm, nullptr, structure, length, vectorLength); butterfly->arrayStorage()->m_numValuesInVector = vectorLength; } else { void* temp = vm.heap.tryAllocateAuxiliary(nullptr, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue))); if (!temp) return 0; butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity()); butterfly->setVectorLength(vectorLength); butterfly->setPublicLength(length); for (unsigned i = length; i < vectorLength; ++i) butterfly->contiguous()[i].clear(); } ClonedArguments* result = new (NotNull, allocateCell<ClonedArguments>(vm.heap)) ClonedArguments(vm, structure, butterfly); result->finishCreation(vm); result->m_callee.set(vm, result, callee); result->putDirect(vm, clonedArgumentsLengthPropertyOffset, jsNumber(length)); return result; }
bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(object); VM& vm = exec->vm(); if (!thisObject->specialsMaterialized()) { FunctionExecutable* executable = jsCast<FunctionExecutable*>(thisObject->m_callee->executable()); bool isStrictMode = executable->isStrictMode(); if (ident == vm.propertyNames->callee) { if (isStrictMode) { slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorArgumentsCalleeAndCallerGetterSetter()); return true; } slot.setValue(thisObject, 0, thisObject->m_callee.get()); return true; } if (ident == vm.propertyNames->iteratorSymbol) { slot.setValue(thisObject, DontEnum, thisObject->globalObject()->arrayProtoValuesFunction()); return true; } } return Base::getOwnPropertySlot(thisObject, exec, ident, slot); }
JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount) { VM& vm = exec->vm(); NativeCallFrameTracer target(&vm, exec); DeferGCForAWhile deferGC(vm.heap); CodeBlock* codeBlock; if (inlineCallFrame) codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame); else codeBlock = exec->codeBlock(); unsigned length = argumentCount - 1; ClonedArguments* result = ClonedArguments::createEmpty( vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee); Register* arguments = exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) + CallFrame::argumentOffset(0); for (unsigned i = length; i--;) result->putDirectIndex(exec, i, arguments[i].jsValue()); result->putDirect(vm, vm.propertyNames->length, jsNumber(length)); return result; }
ClonedArguments* ClonedArguments::createEmpty(ExecState* exec, JSFunction* callee, unsigned length) { VM& vm = exec->vm(); // NB. Some clients might expect that the global object of of this object is the global object // of the callee. We don't do this for now, but maybe we should. ClonedArguments* result = createEmpty(vm, exec->lexicalGlobalObject()->clonedArgumentsStructure(), callee, length); ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType())); return result; }
ClonedArguments* ClonedArguments::createEmpty( VM& vm, Structure* structure, JSFunction* callee) { ClonedArguments* result = new (NotNull, allocateCell<ClonedArguments>(vm.heap)) ClonedArguments(vm, structure); result->finishCreation(vm); result->m_callee.set(vm, result, callee); return result; }
bool ClonedArguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName ident, const PropertyDescriptor& descriptor, bool shouldThrow) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(object); VM& vm = exec->vm(); if (ident == vm.propertyNames->callee || ident == vm.propertyNames->iteratorSymbol) thisObject->materializeSpecialsIfNecessary(exec); return Base::defineOwnProperty(object, exec, ident, descriptor, shouldThrow); }
bool ClonedArguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName ident) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(cell); VM& vm = exec->vm(); if (ident == vm.propertyNames->callee || ident == vm.propertyNames->iteratorSymbol) thisObject->materializeSpecialsIfNecessary(exec); return Base::deleteProperty(thisObject, exec, ident); }
ClonedArguments* ClonedArguments::createByCopyingFrom( ExecState* exec, Structure* structure, Register* argumentStart, unsigned length, JSFunction* callee) { VM& vm = exec->vm(); ClonedArguments* result = createEmpty(vm, structure, callee, length); for (unsigned i = length; i--;) result->initializeIndex(vm, i, argumentStart[i].jsValue()); ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType())); return result; }
ClonedArguments* ClonedArguments::createByCopyingFrom( ExecState* exec, Structure* structure, Register* argumentStart, unsigned length, JSFunction* callee) { VM& vm = exec->vm(); ClonedArguments* result = createEmpty(vm, structure, callee); for (unsigned i = length; i--;) result->putDirectIndex(exec, i, argumentStart[i].jsValue()); result->putDirect(vm, vm.propertyNames->length, jsNumber(length), DontEnum); return result; }
bool ClonedArguments::put(JSCell* cell, ExecState* exec, PropertyName ident, JSValue value, PutPropertySlot& slot) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(cell); VM& vm = exec->vm(); if (ident == vm.propertyNames->callee || ident == vm.propertyNames->iteratorSymbol) { thisObject->materializeSpecialsIfNecessary(exec); PutPropertySlot dummy = slot; // Shadow the given PutPropertySlot to prevent caching. return Base::put(thisObject, exec, ident, value, dummy); } return Base::put(thisObject, exec, ident, value, slot); }
bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(object); VM& vm = exec->vm(); if (ident == vm.propertyNames->callee || ident == vm.propertyNames->caller || ident == vm.propertyNames->iteratorSymbol) thisObject->materializeSpecialsIfNecessary(exec); if (Base::getOwnPropertySlot(thisObject, exec, ident, slot)) return true; return false; }
ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode) { VM& vm = myFrame->vm(); JSFunction* callee; if (inlineCallFrame) callee = jsCast<JSFunction*>(inlineCallFrame->calleeRecovery.recover(targetFrame)); else callee = jsCast<JSFunction*>(targetFrame->callee()); ClonedArguments* result = createEmpty(myFrame, callee); unsigned length = 0; // Initialize because VC needs it. switch (mode) { case ArgumentsMode::Cloned: { if (inlineCallFrame) { if (inlineCallFrame->argumentCountRegister.isValid()) length = targetFrame->r(inlineCallFrame->argumentCountRegister).unboxedInt32(); else length = inlineCallFrame->arguments.size(); length--; for (unsigned i = length; i--;) result->putDirectIndex(myFrame, i, inlineCallFrame->arguments[i + 1].recover(targetFrame)); } else { length = targetFrame->argumentCount(); for (unsigned i = length; i--;) result->putDirectIndex(myFrame, i, targetFrame->uncheckedArgument(i)); } break; } case ArgumentsMode::FakeValues: { length = 0; break; } } result->putDirect(vm, vm.propertyNames->length, jsNumber(length), DontEnum); return result; }
ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode) { VM& vm = myFrame->vm(); JSFunction* callee; if (inlineCallFrame) callee = jsCast<JSFunction*>(inlineCallFrame->calleeRecovery.recover(targetFrame)); else callee = jsCast<JSFunction*>(targetFrame->jsCallee()); ClonedArguments* result = nullptr; unsigned length = 0; // Initialize because VC needs it. switch (mode) { case ArgumentsMode::Cloned: { if (inlineCallFrame) { if (inlineCallFrame->argumentCountRegister.isValid()) length = targetFrame->r(inlineCallFrame->argumentCountRegister).unboxedInt32(); else length = inlineCallFrame->arguments.size(); length--; result = createEmpty(myFrame, callee, length); for (unsigned i = length; i--;) result->initializeIndex(vm, i, inlineCallFrame->arguments[i + 1].recover(targetFrame)); } else { length = targetFrame->argumentCount(); result = createEmpty(myFrame, callee, length); for (unsigned i = length; i--;) result->initializeIndex(vm, i, targetFrame->uncheckedArgument(i)); } break; } case ArgumentsMode::FakeValues: { result = createEmpty(myFrame, callee, 0); break; } } ASSERT(myFrame->lexicalGlobalObject()->clonedArgumentsStructure() == result->structure()); ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType())); return result; }
void ClonedArguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) { ClonedArguments* thisObject = jsCast<ClonedArguments*>(object); thisObject->materializeSpecialsIfNecessary(exec); Base::getOwnPropertyNames(thisObject, exec, array, mode); }
ClonedArguments* ClonedArguments::createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode mode) { ClonedArguments* result = createWithInlineFrame(myFrame, targetFrame, nullptr, mode); ASSERT(!result->structure()->needsSlowPutIndexing() || shouldUseSlowPut(result->structure()->indexingType())); return result; }