1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/interpreter/interpreter-inl.h" 17 18namespace panda::ecmascript { 19// make EcmaRuntimeCallInfo in stack pointer as fallows: 20// +----------------------+ — 21// | args... | ^ 22// |----------------------| | 23// | numArgs | | 24// |----------------------| | 25// | this | | 26// |----------------------| EcmaRuntimeCallInfo 27// | newTarget | | 28// |----------------------| | 29// | func | v 30// +----------------------+ — 31// | base.type | ^ 32// |----------------------| | 33// | base.prev | InterpretedEntryFrame 34// |----------------------| | 35// | pc | v 36// +--------------------------+ 37EcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfoBase( 38 JSThread *thread, JSTaggedType func, JSTaggedType thisObj, JSTaggedType newTarget, 39 uint32_t numArgs, StackCheck needCheckStack) 40{ 41 JSTaggedType *prevSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); 42 JSTaggedType *newSp = GetInterpreterFrameEnd(thread, prevSp); 43 if (needCheckStack == StackCheck::YES && 44 UNLIKELY(thread->DoStackOverflowCheck(newSp - numArgs - NUM_MANDATORY_JSFUNC_ARGS))) { 45 return nullptr; 46 } 47 48 for (uint32_t i = 0; i < numArgs; i++) { 49 *(--newSp) = JSTaggedValue::VALUE_UNDEFINED; 50 } 51 *(--newSp) = thisObj; 52 *(--newSp) = newTarget; 53 *(--newSp) = func; 54 *(--newSp) = numArgs + NUM_MANDATORY_JSFUNC_ARGS; 55 *(--newSp) = ToUintPtr(thread); 56 EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = reinterpret_cast<EcmaRuntimeCallInfo *>(newSp); 57 58 // create entry frame. 59 InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(newSp); 60 entryState->base.type = FrameType::INTERPRETER_ENTRY_FRAME; 61 entryState->base.prev = prevSp; 62 entryState->pc = nullptr; 63 64 thread->SetCurrentSPFrame(newSp); 65 return ecmaRuntimeCallInfo; 66} 67 68EcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfo( 69 JSThread *thread, JSTaggedValue func, JSTaggedValue thisObj, JSTaggedValue newTarget, 70 uint32_t numArgs, StackCheck needCheckStack) 71{ 72 return NewRuntimeCallInfoBase(thread, func.GetRawData(), thisObj.GetRawData(), newTarget.GetRawData(), 73 numArgs, needCheckStack); 74} 75 76EcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfo( 77 JSThread *thread, JSHandle<JSTaggedValue> func, JSHandle<JSTaggedValue> thisObj, 78 JSHandle<JSTaggedValue> newTarget, uint32_t numArgs, StackCheck needCheckStack) 79{ 80 return NewRuntimeCallInfoBase(thread, func.GetTaggedType(), thisObj.GetTaggedType(), newTarget.GetTaggedType(), 81 numArgs, needCheckStack); 82} 83 84EcmaRuntimeCallInfo* EcmaInterpreter::ReBuildRuntimeCallInfo(JSThread *thread, EcmaRuntimeCallInfo* info, 85 int numArgs, StackCheck needCheckStack) 86{ 87 JSTaggedValue func = info->GetFunctionValue(); 88 JSTaggedValue newTarget = info->GetNewTargetValue(); 89 JSTaggedValue thisObj = info->GetThisValue(); 90 JSTaggedType *currentSp = reinterpret_cast<JSTaggedType *>(info); 91 92 InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp); 93 JSTaggedType *prevSp = currentEntryState->base.prev; 94 95 int actualArgc = static_cast<int>(info->GetArgsNumber()); 96 std::vector<JSTaggedType> args(actualArgc); 97 for (int i = 0; i < actualArgc; i++) { 98 args[i] = info->GetCallArgValue(actualArgc - i - 1).GetRawData(); 99 } 100 currentSp += (info->GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS + 2); // 2: include thread_ and numArgs_ 101 if (needCheckStack == StackCheck::YES && 102 UNLIKELY(thread->DoStackOverflowCheck(currentSp - numArgs - NUM_MANDATORY_JSFUNC_ARGS))) { 103 return nullptr; 104 } 105 ASSERT(numArgs != actualArgc); 106 for (int i = 0; i < (numArgs - actualArgc); i++) { 107 *(--currentSp) = JSTaggedValue::VALUE_UNDEFINED; 108 } 109 for (int i = 0; i < actualArgc; i++) { 110 *(--currentSp) = args[i]; 111 } 112 *(--currentSp) = thisObj.GetRawData(); 113 *(--currentSp) = newTarget.GetRawData(); 114 *(--currentSp) = func.GetRawData(); 115 *(--currentSp) = numArgs + static_cast<int>(NUM_MANDATORY_JSFUNC_ARGS); 116 *(--currentSp) = ToUintPtr(thread); 117 EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = reinterpret_cast<EcmaRuntimeCallInfo *>(currentSp); 118 119 InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(currentSp); 120 entryState->base.type = FrameType::INTERPRETER_ENTRY_FRAME; 121 entryState->base.prev = prevSp; 122 entryState->pc = nullptr; 123 124 thread->SetCurrentSPFrame(currentSp); 125 return ecmaRuntimeCallInfo; 126} 127} // namespace panda::ecmascript 128