diff --git a/runtime/base/json_stringifier.cpp b/runtime/base/json_stringifier.cpp index 79864721469e76210c2e95c1fe48ebfc5ddb72c9..b860b2f1cc3537970970a526ae90a114f6487197 100644 --- a/runtime/base/json_stringifier.cpp +++ b/runtime/base/json_stringifier.cpp @@ -364,31 +364,31 @@ JSTaggedValue JsonStringifier::SerializeJSONProperty(const JSHandle(valHandle)); str = ValueToQuotedString(str); result_ += str; - return tagValue; + return valHandle.GetTaggedValue(); } case JSType::JS_PRIMITIVE_REF: { SerilaizePrimitiveRef(valHandle); - return tagValue; + return valHandle.GetTaggedValue(); } case JSType::SYMBOL: return JSTaggedValue::Undefined(); default: { - if (!tagValue.IsCallable()) { - if (UNLIKELY(tagValue.IsJSProxy())) { + if (!valHandle->IsCallable()) { + if (UNLIKELY(valHandle->IsJSProxy())) { SerializeJSProxy(valHandle, replacer); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); } else { SerializeJSONObject(valHandle, replacer); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); } - return tagValue; + return valHandle.GetTaggedValue(); } } } @@ -575,8 +575,8 @@ bool JsonStringifier::SerializeJSArray(const JSHandle &value, con if (UNLIKELY(tagVal.IsAccessor())) { tagVal = JSObject::CallGetter(thread_, AccessorData::Cast(tagVal.GetTaggedObject()), value); } - handleKey_.Update(JSTaggedNumber(i).ToString(thread_).GetTaggedValue()); handleValue_.Update(tagVal); + handleKey_.Update(JSTaggedNumber(i).ToString(thread_).GetTaggedValue()); if (i > 0) { result_ += ","; diff --git a/runtime/builtins/builtins_array.cpp b/runtime/builtins/builtins_array.cpp index 1ef008251460953885af304d13beec0eb80946dc..77e598e0a72128c6834e17014934a91d4697aca6 100644 --- a/runtime/builtins/builtins_array.cpp +++ b/runtime/builtins/builtins_array.cpp @@ -102,10 +102,10 @@ JSTaggedValue BuiltinsArray::ArrayConstructor(EcmaRuntimeCallInfo *argv) // 22.1.1.3 Array(...items ) JSTaggedValue newArray = JSArray::ArrayCreate(thread, JSTaggedNumber(argc), newTarget).GetTaggedValue(); + JSHandle newArrayHandle(thread, newArray); if (!newArray.IsArray(thread)) { THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create array.", JSTaggedValue::Exception()); } - JSHandle newArrayHandle(thread, newArray); // 8. Let k be 0. // 9. Let items be a zero-origined List containing the argument items in order. diff --git a/runtime/builtins/builtins_dataview.cpp b/runtime/builtins/builtins_dataview.cpp index 6672a4dfe54ed3136886594e017e1e90ef47e04f..9bcb574d5a8c5f6ab67ee760a79c9a5b94228d89 100644 --- a/runtime/builtins/builtins_dataview.cpp +++ b/runtime/builtins/builtins_dataview.cpp @@ -331,10 +331,14 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle dataView(view); - JSTaggedValue buffer = dataView->GetViewedArrayBuffer(); - // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { - THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception()); + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = dataView->GetViewedArrayBuffer(); + // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception()); + } } // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot. JSTaggedNumber offsetNum = JSTaggedNumber::FromIntOrDouble(thread, dataView->GetByteOffset()); @@ -351,7 +355,12 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandleGetViewedArrayBuffer(); + return BuiltinsArrayBuffer::GetValueFromBuffer(buffer, bufferIndex, type, isLittleEndian); + } } // 24.2.1.2 @@ -388,10 +397,14 @@ JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle dataView(view); - JSTaggedValue buffer = dataView->GetViewedArrayBuffer(); - // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { - THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception()); + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = dataView->GetViewedArrayBuffer(); + // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", JSTaggedValue::Exception()); + } } // 10. Let viewOffset be the value of view’s [[ByteOffset]] internal slot. JSTaggedNumber offsetNum = JSTaggedNumber::FromIntOrDouble(thread, dataView->GetByteOffset()); @@ -407,8 +420,13 @@ JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandleGetViewedArrayBuffer(); + // 15. Return SetValueFromBuffer(buffer, bufferIndex, type, value, isLittleEndian). + return BuiltinsArrayBuffer::SetValueInBuffer(buffer, bufferIndex, type, numVal, isLittleEndian); + } } JSTaggedValue BuiltinsDataView::GetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type) diff --git a/runtime/builtins/builtins_generator.cpp b/runtime/builtins/builtins_generator.cpp index 5cbcce3901ebd04fd805b2008fca047995966878..387bd75548b26bd859b869baee5c99370209eb23 100644 --- a/runtime/builtins/builtins_generator.cpp +++ b/runtime/builtins/builtins_generator.cpp @@ -42,7 +42,7 @@ JSTaggedValue BuiltinsGenerator::GeneratorPrototypeNext(EcmaRuntimeCallInfo *arg JSHandle value = GetCallArg(argv, 0); // 2.Return ? GeneratorResume(g, value). - JSHandle result = JSGeneratorObject::GeneratorResume(thread, generator, value.GetTaggedValue()); + JSHandle result = JSGeneratorObject::GeneratorResume(thread, generator, value); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result.GetTaggedValue(); } diff --git a/runtime/builtins/builtins_map.cpp b/runtime/builtins/builtins_map.cpp index 9d6edc0c21148e8138b548ee45a567bb8ce374b7..a94739bd1b6eb507cf20dc7e4e65f6eeb7b9f6be 100644 --- a/runtime/builtins/builtins_map.cpp +++ b/runtime/builtins/builtins_map.cpp @@ -137,9 +137,13 @@ JSTaggedValue BuiltinsMap::Has(EcmaRuntimeCallInfo *argv) if (!self->IsJSMap()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSMap", JSTaggedValue::Exception()); } - JSMap *jsMap = JSMap::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsMap(thread, JSMap::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle key = GetCallArg(argv, 0); - bool flag = jsMap->Has(key.GetTaggedValue()); + bool flag = false; + if (JSMap::IsKey(key.GetTaggedValue())) { + int hash = LinkedHash::Hash(key.GetTaggedValue()); + flag = jsMap->Has(key.GetTaggedValue(), hash); + } return GetTaggedBoolean(flag); } @@ -154,9 +158,13 @@ JSTaggedValue BuiltinsMap::Get(EcmaRuntimeCallInfo *argv) if (!self->IsJSMap()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSMap", JSTaggedValue::Exception()); } - JSMap *jsMap = JSMap::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsMap(thread, JSMap::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle key = GetCallArg(argv, 0); - JSTaggedValue value = jsMap->Get(key.GetTaggedValue()); + JSTaggedValue value = JSTaggedValue::Undefined(); + if (JSMap::IsKey(key.GetTaggedValue())) { + int hash = LinkedHash::Hash(key.GetTaggedValue()); + value = jsMap->Get(key.GetTaggedValue(), hash); + } return value; } diff --git a/runtime/builtins/builtins_object.cpp b/runtime/builtins/builtins_object.cpp index 773a393200b7153232535b0f3d4826f47c121ebf..9fe71f76ec4befc2f503177de3e0ba085e567103 100644 --- a/runtime/builtins/builtins_object.cpp +++ b/runtime/builtins/builtins_object.cpp @@ -342,9 +342,9 @@ JSTaggedValue BuiltinsObject::FromEntries(EcmaRuntimeCallInfo *argv) // 6. Let adder be ! CreateBuiltinFunction(stepsDefine, lengthDefine, "", « »). ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle adder = - factory->CreateBuiltinFunction(stepsDefine, lengthDefine, JSHandle(factory->NewFromString("")), - JSTaggedValue::Undefined(), thread->GlobalConstants()->GetHandledUndefined()); + JSHandle adder = factory->CreateBuiltinFunction( + stepsDefine, lengthDefine, JSHandle(factory->NewFromString("")), + JSHandle(thread, JSTaggedValue::Undefined()), thread->GlobalConstants()->GetHandledUndefined()); // 7. Return ? AddEntriesFromIterable(obj, iterable, adder). JSHandle adderHandler(thread, adder.GetTaggedValue()); @@ -1087,8 +1087,8 @@ static JSTaggedValue LookupDesc(EcmaRuntimeCallInfo *argv, // ii. Return undefined. // c. Set O to ? O.[[GetPrototypeOf]](). // d. If O is null, return undefined. - JSTaggedValue objval = obj.GetTaggedValue(); - while (!objval.IsNull()) { + JSMutableHandle objval(thread, obj.GetTaggedValue()); + while (!objval->IsNull()) { PropertyDescriptor desc(thread); JSTaggedValue::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -1097,7 +1097,7 @@ static JSTaggedValue LookupDesc(EcmaRuntimeCallInfo *argv, return getDesc(desc); } - objval = JSObject::Cast(objval)->GetPrototype(thread); + objval.Update(JSObject::Cast(objval.GetTaggedValue())->GetPrototype(thread)); } return JSTaggedValue::Undefined(); diff --git a/runtime/builtins/builtins_set.cpp b/runtime/builtins/builtins_set.cpp index fc3f90bdcee3ff0713342b9de2b3242bbcd35ca1..5faaa2a115166714cefd03a4f3f2b643dadedd21 100644 --- a/runtime/builtins/builtins_set.cpp +++ b/runtime/builtins/builtins_set.cpp @@ -171,9 +171,13 @@ JSTaggedValue BuiltinsSet::Has(EcmaRuntimeCallInfo *argv) if (!self->IsJSSet()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSSet", JSTaggedValue::Exception()); } - JSSet *jsSet = JSSet::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsSet(thread, JSSet::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle value = GetCallArg(argv, 0); - bool flag = jsSet->Has(value.GetTaggedValue()); + bool flag = false; + if (JSSet::IsKey(value.GetTaggedValue())) { + int hash = LinkedHash::Hash(value.GetTaggedValue()); + flag = jsSet->Has(value.GetTaggedValue(), hash); + } return GetTaggedBoolean(flag); } diff --git a/runtime/builtins/builtins_weak_map.cpp b/runtime/builtins/builtins_weak_map.cpp index 720750c7ff8de814e4ad347be892f51590e896ed..47c30daa8c90c01ce0a4c32cc00058fb5e91d32d 100644 --- a/runtime/builtins/builtins_weak_map.cpp +++ b/runtime/builtins/builtins_weak_map.cpp @@ -160,13 +160,14 @@ JSTaggedValue BuiltinsWeakMap::Has(EcmaRuntimeCallInfo *argv) if (!self->IsJSWeakMap()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSWeakMap.", JSTaggedValue::Exception()); } - JSWeakMap *jsWeakMap = JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsWeakMap(thread, JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle key = GetCallArg(argv, 0); // 5.if Type(key) is not Object, return false. if (!key->IsHeapObject()) { return GetTaggedBoolean(false); } - return GetTaggedBoolean(jsWeakMap->Has(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + return GetTaggedBoolean(jsWeakMap->Has(key.GetTaggedValue(), hash)); } JSTaggedValue BuiltinsWeakMap::Get(EcmaRuntimeCallInfo *argv) @@ -181,12 +182,13 @@ JSTaggedValue BuiltinsWeakMap::Get(EcmaRuntimeCallInfo *argv) if (!self->IsJSWeakMap()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSWeakMap.", JSTaggedValue::Exception()); } - JSWeakMap *jsWeakMap = JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsWeakMap(thread, JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle key = GetCallArg(argv, 0); if (!key->IsHeapObject()) { return JSTaggedValue::Undefined(); } - return jsWeakMap->Get(key.GetTaggedValue()); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + return jsWeakMap->Get(key.GetTaggedValue(), hash); } JSTaggedValue BuiltinsWeakMap::Set(EcmaRuntimeCallInfo *argv) diff --git a/runtime/builtins/builtins_weak_set.cpp b/runtime/builtins/builtins_weak_set.cpp index 20bf0bebe72b6ad4715a598d9e4bcf70e2c52727..f41aee103e343f70d635b579d1ca74b0f17d2631 100644 --- a/runtime/builtins/builtins_weak_set.cpp +++ b/runtime/builtins/builtins_weak_set.cpp @@ -164,11 +164,12 @@ JSTaggedValue BuiltinsWeakSet::Has(EcmaRuntimeCallInfo *argv) if (!self->IsJSWeakSet()) { THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSWeakSet", JSTaggedValue::Exception()); } - JSWeakSet *jsWeakSet = JSWeakSet::Cast(*JSTaggedValue::ToObject(thread, self)); + JSHandle jsWeakSet(thread, JSWeakSet::Cast(*JSTaggedValue::ToObject(thread, self))); JSHandle value = GetCallArg(argv, 0); if (!value->IsHeapObject()) { GetTaggedBoolean(false); } - return GetTaggedBoolean(jsWeakSet->Has(value.GetTaggedValue())); + int hash = LinkedHash::Hash(value.GetTaggedValue()); + return GetTaggedBoolean(jsWeakSet->Has(value.GetTaggedValue(), hash)); } } // namespace panda::ecmascript::builtins diff --git a/runtime/ic/ic_runtime.cpp b/runtime/ic/ic_runtime.cpp index 34f007aa26699ce03d3104636f01a3cd5877579c..49813b641cdcb361dab6a9730fa17895dd2b06e0 100644 --- a/runtime/ic/ic_runtime.cpp +++ b/runtime/ic/ic_runtime.cpp @@ -184,6 +184,11 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand ASSERT(box.IsPropertyBox()); SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); + // CSA reports usage of 'box' variable after GC in TryUpdateGlobalRecord. + // GC could be triggered when the function throws an exception. + // In this case the next line will not be executed because we check the exception in the previous line + // and return. + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) icAccessor_.AddGlobalRecordHandler(JSHandle(thread_, box)); return JSTaggedValue::Undefined(); } diff --git a/runtime/interpreter/fast_runtime_stub-inl.h b/runtime/interpreter/fast_runtime_stub-inl.h index a747d40ff4408935cb11f4ff8cacb012f44cfe9e..b008c72b6e5b5b900032b82b1c9b21757b846fb8 100644 --- a/runtime/interpreter/fast_runtime_stub-inl.h +++ b/runtime/interpreter/fast_runtime_stub-inl.h @@ -355,27 +355,28 @@ JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValu } template -JSTaggedValue FastRuntimeStub::GetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key) +JSTaggedValue FastRuntimeStub::GetPropertyByValue(JSThread *thread, JSTaggedValue *receiver, JSTaggedValue *key) { INTERPRETER_TRACE(thread, GetPropertyByValue); - if (UNLIKELY(!key.IsNumber() && !key.IsStringOrSymbol())) { + if (UNLIKELY(!key->IsNumber() && !key->IsStringOrSymbol())) { return JSTaggedValue::Hole(); } // fast path - auto index = TryToElementsIndex(key); + auto index = TryToElementsIndex(*key); if (LIKELY(index < JSObject::MAX_ELEMENT_INDEX)) { - return GetPropertyByIndex(thread, receiver, index); + return GetPropertyByIndex(thread, *receiver, index); } - if (!key.IsNumber()) { - if (key.IsString() && !EcmaString::Cast(key.GetTaggedObject())->IsInternString()) { + if (!key->IsNumber()) { + if (key->IsString() && !EcmaString::Cast(key->GetTaggedObject())->IsInternString()) { // update string stable [[maybe_unused]] EcmaHandleScope handleScope(thread); - JSHandle receiverHandler(thread, receiver); - key = JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(JSHandle(thread, key))); + JSHandle receiverHandler(thread, *receiver); + *key = + JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(JSHandle(thread, *key))); // Maybe moved by GC - receiver = receiverHandler.GetTaggedValue(); + *receiver = receiverHandler.GetTaggedValue(); } - return FastRuntimeStub::GetPropertyByName(thread, receiver, key); + return FastRuntimeStub::GetPropertyByName(thread, *receiver, *key); } return JSTaggedValue::Hole(); } @@ -648,7 +649,12 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec if (!result.IsHole()) { return result != JSTaggedValue::Exception(); } + // CSA reports usage of 'receiver' and 'value' after GC in function FastRuntimeStub::SetPropertyByIndex. + // In case the function throws an exception its result will be JSTaggedValue::Exception() we gets in + // the 'if' condition above and return. + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return JSTaggedValue::SetProperty(thread, JSHandle(thread, receiver), index, + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) JSHandle(thread, value), true); } @@ -660,7 +666,12 @@ bool FastRuntimeStub::FastSetPropertyByValue(JSThread *thread, JSTaggedValue rec if (!result.IsHole()) { return result != JSTaggedValue::Exception(); } + // CSA reports usage of 'receiver' and 'value' after GC in the function 'SetPropertyByName' called from + // 'SetPropertyByValue'. + // In this case we get in the 'if' condition above and return. + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return JSTaggedValue::SetProperty(thread, JSHandle(thread, receiver), + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) JSHandle(thread, key), JSHandle(thread, value), true); } @@ -702,10 +713,15 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByValue(JSThread *thread, JSTagged auto getPropertyByValuePtr = reinterpret_cast(stubAddr); JSTaggedValue result = getPropertyByValuePtr(thread->GetGlueAddr(), receiver, key); #else - JSTaggedValue result = FastRuntimeStub::GetPropertyByValue(thread, receiver, key); + JSTaggedValue result = FastRuntimeStub::GetPropertyByValue(thread, &receiver, &key); #endif if (result.IsHole()) { + // CSA reports usage of 'receiver' and 'key' after GC in the function 'GetPropertyByValue'. + // In case GC is triggered in the function and the objects are moved the function returns + // new addreses of 'receiver' and 'key' via parameters. + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) JSHandle(thread, key)) .GetValue() .GetTaggedValue(); @@ -726,6 +742,9 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTagged JSTaggedValue result = FastRuntimeStub::GetPropertyByIndex(thread, receiver, index); #endif if (result.IsHole() && !UseHole) { + // CSA reports usage of 'receiver' after GC in the function 'CallGetter' which is called from + // GetPropertyByIndex. In case we reach CallGetter the result canot by JSTaggedValue::Hole(). + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), index) .GetValue() .GetTaggedValue(); @@ -959,10 +978,12 @@ bool FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue receiver if (holder.IsTypedArray()) { [[maybe_unused]] EcmaHandleScope handleScope(thread); - return JSTypedArray::SetProperty(thread, JSHandle(thread, holder), - JSTypedArray::ToPropKey(thread, JSHandle(thread, key)), - JSHandle(thread, value), - JSHandle(thread, receiver), mayThrow); + JSHandle holder_handle(thread, holder); + JSHandle value_handle(thread, value); + JSHandle receiver_handle(thread, receiver); + JSHandle key_handle = JSTypedArray::ToPropKey(thread, JSHandle(thread, key)); + return JSTypedArray::SetProperty(thread, holder_handle, key_handle, value_handle, receiver_handle, + mayThrow); } holder = JSObject::Cast(holder)->GetJSHClass()->GetPrototype(); @@ -1158,6 +1179,9 @@ JSTaggedValue FastRuntimeStub::FastGetProperty(JSThread *thread, JSTaggedValue r { INTERPRETER_TRACE(thread, FastGetProperty); JSTaggedValue result; + + JSHandle receiver_handle(thread, receiver); + JSHandle key_handle(thread, key); if (receiver.IsJSObject() && !receiver.IsTypedArray() && (key.IsStringOrSymbol())) { uint32_t index = 0; if (UNLIKELY(JSTaggedValue::ToElementIndex(key, &index))) { @@ -1176,15 +1200,11 @@ JSTaggedValue FastRuntimeStub::FastGetProperty(JSThread *thread, JSTaggedValue r } if (!result.IsHole()) { if (UNLIKELY(result.IsAccessor())) { - return JSObject::CallGetter(thread, AccessorData::Cast(result.GetHeapObject()), - JSHandle(thread, receiver)); + return JSObject::CallGetter(thread, AccessorData::Cast(result.GetHeapObject()), receiver_handle); } return result; } - return JSTaggedValue::GetProperty(thread, JSHandle(thread, receiver), - JSHandle(thread, key)) - .GetValue() - .GetTaggedValue(); + return JSTaggedValue::GetProperty(thread, receiver_handle, key_handle).GetValue().GetTaggedValue(); } JSTaggedValue FastRuntimeStub::FindOwnProperty(JSThread *thread, JSObject *obj, TaggedArray *properties, diff --git a/runtime/interpreter/fast_runtime_stub.h b/runtime/interpreter/fast_runtime_stub.h index 0346e7d14a25491970398f822be5e6e2cc408d86..098494b563a217b1059aacb28c447e942d80c173 100644 --- a/runtime/interpreter/fast_runtime_stub.h +++ b/runtime/interpreter/fast_runtime_stub.h @@ -72,7 +72,7 @@ public: template static inline JSTaggedValue GetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key); template - static inline JSTaggedValue GetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key); + static inline JSTaggedValue GetPropertyByValue(JSThread *thread, JSTaggedValue *receiver, JSTaggedValue *key); template static inline JSTaggedValue GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index); template diff --git a/runtime/interpreter/slow_runtime_stub.cpp b/runtime/interpreter/slow_runtime_stub.cpp index a587eda32d98bf185d8c3302f2b0724585643ebc..17baf84df65648fd299fe5d72b588801069e960d 100644 --- a/runtime/interpreter/slow_runtime_stub.cpp +++ b/runtime/interpreter/slow_runtime_stub.cpp @@ -518,10 +518,12 @@ JSTaggedValue SlowRuntimeStub::ExpDyn(JSThread *thread, JSTaggedValue base, JSTa INTERPRETER_TRACE(thread, ExpDyn); [[maybe_unused]] EcmaHandleScope handleScope(thread); - JSTaggedNumber baseNumber = JSTaggedValue::ToNumber(thread, JSHandle(thread, base)); + JSHandle base_handle(thread, base); + JSHandle exp_handle(thread, exponent); + JSTaggedNumber baseNumber = JSTaggedValue::ToNumber(thread, base_handle); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); double doubleBase = baseNumber.GetNumber(); - JSTaggedNumber exponentNumber = JSTaggedValue::ToNumber(thread, JSHandle(thread, exponent)); + JSTaggedNumber exponentNumber = JSTaggedValue::ToNumber(thread, exp_handle); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); double doubleExponent = exponentNumber.GetNumber(); @@ -1252,8 +1254,9 @@ JSTaggedValue SlowRuntimeStub::GetIterator(JSThread *thread, JSTaggedValue obj, RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod). - JSHandle syncIterator( - thread, SlowRuntimeStub::GetIterator(thread, obj, false, syncMethod.GetTaggedValue())); + JSHandle syncIterator(thread, + SlowRuntimeStub::GetIterator(thread, objHandle.GetTaggedValue(), + false, syncMethod.GetTaggedValue())); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 6. Let nextMethod be ? GetV(iterator, "next"). @@ -1446,7 +1449,7 @@ JSTaggedValue SlowRuntimeStub::TryLdGlobalByName(JSThread *thread, JSTaggedValue JSHandle propHandle(thread, prop); OperationResult res = JSTaggedValue::GetProperty(thread, obj, propHandle); if (!res.GetPropertyMetaData().IsFound()) { - return ThrowReferenceError(thread, prop, " is not defined"); + return ThrowReferenceError(thread, propHandle.GetTaggedValue(), " is not defined"); } return res.GetValue().GetTaggedValue(); } diff --git a/runtime/intrinsics-inl.h b/runtime/intrinsics-inl.h index 5f14e46686d1687b26e8563d643a215c25acdaed..c07a47fec8f97808e1ce735fabdaecbfe3eff573 100644 --- a/runtime/intrinsics-inl.h +++ b/runtime/intrinsics-inl.h @@ -768,7 +768,7 @@ INLINE_ECMA_INTRINSICS uint64_t LdObjByValue(JSThread *thread, uint64_t rec, uin // fast path if (LIKELY(receiver.IsHeapObject())) { - res = FastRuntimeStub::GetPropertyByValue(thread, receiver, prop_key); + res = FastRuntimeStub::GetPropertyByValue(thread, &receiver, &prop_key); if (!res.IsHole()) { return res.GetRawData(); } diff --git a/runtime/js_generator_object.cpp b/runtime/js_generator_object.cpp index 05ce1f44ef5a86a18d4e01491ff8ee5ed5a83739..87d087522a7ddd4045633e251823341bf33285ad 100644 --- a/runtime/js_generator_object.cpp +++ b/runtime/js_generator_object.cpp @@ -44,7 +44,7 @@ JSTaggedValue JSGeneratorObject::GeneratorValidate(JSThread *thread, const JSHan JSHandle JSGeneratorObject::GeneratorResume(JSThread *thread, const JSHandle &generator, - JSTaggedValue value) + const JSHandle &value) { // 1.Let state be ? GeneratorValidate(generator). JSHandle gen(thread, generator.GetTaggedValue()); @@ -77,7 +77,8 @@ JSHandle JSGeneratorObject::GeneratorResume(JSThread *thread, // 10.Assert: When we return here, genContext has already been removed from the execution context stack and // methodContext is the currently running execution context. // 11.Return Completion(result). - JSHandle result = GeneratorHelper::Continue(thread, genContext, GeneratorResumeMode::NEXT, value); + JSHandle result = + GeneratorHelper::Continue(thread, genContext, GeneratorResumeMode::NEXT, value.GetTaggedValue()); return result; } diff --git a/runtime/js_generator_object.h b/runtime/js_generator_object.h index 307329140b16e697b51213951b4a8eea164ef0e9..97cf93aa1f5ced86c4bf55984f32c62e2be24cdb 100644 --- a/runtime/js_generator_object.h +++ b/runtime/js_generator_object.h @@ -61,7 +61,7 @@ public: // 26.4.3.3 GeneratorResume(generator, value) static JSHandle GeneratorResume(JSThread *thread, const JSHandle &generator, - JSTaggedValue value); + const JSHandle &value); // 26.4.3.4 GeneratorResumeAbrupt(generator, abruptCompletion) static JSHandle GeneratorResumeAbrupt(JSThread *thread, const JSHandle &generator, diff --git a/runtime/js_handle.h b/runtime/js_handle.h index a899668c911fa1c82e71a47d1e667a6919496f21..796d2b967593a511fa94975cceb32bba444a14c6 100644 --- a/runtime/js_handle.h +++ b/runtime/js_handle.h @@ -72,6 +72,7 @@ public: if (GetAddress() == 0U) { return JSTaggedValue::Undefined(); } + // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return *(reinterpret_cast(GetAddress())); // NOLINT(clang-analyzer-core.NullDereference) } diff --git a/runtime/js_map.cpp b/runtime/js_map.cpp index 9251712f92bf6f1f4c6847708c7cc2b9c1fc57fe..41dc63f9a925633a02aea00cbb25978435421087 100644 --- a/runtime/js_map.cpp +++ b/runtime/js_map.cpp @@ -35,7 +35,11 @@ void JSMap::Set(JSThread *thread, const JSHandle &map, const JSHandle &map, const JSHandle &key) { JSHandle mapHandle(thread, LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())); - int entry = mapHandle->FindElement(key.GetTaggedValue()); + if (!LinkedHashMap::IsKey(key.GetTaggedValue())) { + return false; + } + int hash = LinkedHash::Hash(key.GetTaggedValue()); + int entry = mapHandle->FindElement(key.GetTaggedValue(), hash); if (entry == -1) { return false; } @@ -52,14 +56,14 @@ void JSMap::Clear(const JSThread *thread, const JSHandle &map) linkedMap->Clear(thread); } -bool JSMap::Has(JSTaggedValue key) const +bool JSMap::Has(JSTaggedValue key, int hash) const { - return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Has(key); + return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Has(key, hash); } -JSTaggedValue JSMap::Get(JSTaggedValue key) const +JSTaggedValue JSMap::Get(JSTaggedValue key, int hash) const { - return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Get(key); + return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Get(key, hash); } int JSMap::GetSize() const diff --git a/runtime/js_map.h b/runtime/js_map.h index 7ab3d022ef4aa8cfe1b641777d18880bb6f9d7df..7ac947c12a74e0e3e49b881c5a46a26f95f66d0d 100644 --- a/runtime/js_map.h +++ b/runtime/js_map.h @@ -19,6 +19,7 @@ #include #include "js_object.h" #include "js_tagged_value-inl.h" +#include "linked_hash_table.h" namespace panda::ecmascript { class JSMap : public JSObject { @@ -31,9 +32,14 @@ public: const JSHandle &value); static void Clear(const JSThread *thread, const JSHandle &map); - bool Has(JSTaggedValue key) const; + static bool IsKey(JSTaggedValue key) + { + return LinkedHashMap::IsKey(key); + } - JSTaggedValue Get(JSTaggedValue key) const; + bool Has(JSTaggedValue key, int hash) const; + + JSTaggedValue Get(JSTaggedValue ke, int hashy) const; int GetSize() const; diff --git a/runtime/js_proxy.cpp b/runtime/js_proxy.cpp index f330f909b073235ed2cb9c2a7f0bef6f07215fda..cc0a514256056d3df5608079a35c8b96f9ea47db 100644 --- a/runtime/js_proxy.cpp +++ b/runtime/js_proxy.cpp @@ -80,12 +80,12 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p // 8. Let handlerProto be Call(trap, handler, «target»). InternalCallParams *arguments = thread->GetInternalCallParams(); arguments->MakeArgv(targetHandle); - JSTaggedValue handlerProto = JSFunction::Call(thread, trap, handler, 1, arguments->GetArgv()); + JSHandle handlerProto(thread, JSFunction::Call(thread, trap, handler, 1, arguments->GetArgv())); // 9. ReturnIfAbrupt(handlerProto). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 10. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. - if (!handlerProto.IsECMAObject() && !handlerProto.IsNull()) { + if (!handlerProto->IsECMAObject() && !handlerProto->IsNull()) { THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: Type(handlerProto) is neither Object nor Null", JSTaggedValue::Exception()); } @@ -93,7 +93,7 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p // 12. ReturnIfAbrupt(extensibleTarget). // 13. If extensibleTarget is true, return handlerProto. if (targetHandle->IsExtensible(thread)) { - return handlerProto; + return handlerProto.GetTaggedValue(); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -102,12 +102,12 @@ JSTaggedValue JSProxy::GetPrototype(JSThread *thread, const JSHandle &p // 15. ReturnIfAbrupt(targetProto). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 16. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception. - if (!JSTaggedValue::SameValue(handlerProto, targetProto)) { + if (!JSTaggedValue::SameValue(handlerProto.GetTaggedValue(), targetProto)) { THROW_TYPE_ERROR_AND_RETURN(thread, "JSProxy::GetPrototype: SameValue(handlerProto, targetProto) is false", JSTaggedValue::Exception()); } // 17. Return handlerProto. - return handlerProto; + return handlerProto.GetTaggedValue(); } // ES6 9.5.2 [[SetPrototypeOf]] (V) diff --git a/runtime/js_set.cpp b/runtime/js_set.cpp index 2b4be7ce61fa8ed40e2ff625f3812a2652750d15..58a332b6de5c124d85b1f32937d77e97e77172d5 100644 --- a/runtime/js_set.cpp +++ b/runtime/js_set.cpp @@ -35,7 +35,11 @@ void JSSet::Add(JSThread *thread, const JSHandle &set, const JSHandle &set, const JSHandle &value) { JSHandle setHandle(thread, LinkedHashSet::Cast(set->GetLinkedSet().GetTaggedObject())); - int entry = setHandle->FindElement(value.GetTaggedValue()); + if (!LinkedHashSet::IsKey(value.GetTaggedValue())) { + return false; + } + int hash = LinkedHash::Hash(value.GetTaggedValue()); + int entry = setHandle->FindElement(value.GetTaggedValue(), hash); if (entry == -1) { return false; } @@ -51,9 +55,9 @@ void JSSet::Clear(const JSThread *thread, const JSHandle &set) linkedSet->Clear(thread); } -bool JSSet::Has(JSTaggedValue value) const +bool JSSet::Has(JSTaggedValue value, int hash) const { - return LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject())->Has(value); + return LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject())->Has(value, hash); } int JSSet::GetSize() const diff --git a/runtime/js_set.h b/runtime/js_set.h index 9db9af344408b3627e3bbb375ee3056ff1da329a..33704fc698fd4e43d5679d188e400441695804de 100644 --- a/runtime/js_set.h +++ b/runtime/js_set.h @@ -19,6 +19,7 @@ #include #include "js_object.h" #include "js_tagged_value-inl.h" +#include "linked_hash_table.h" namespace panda::ecmascript { class JSSet : public JSObject { @@ -31,7 +32,12 @@ public: static void Clear(const JSThread *thread, const JSHandle &set); - bool Has(JSTaggedValue value) const; + static bool IsKey(JSTaggedValue key) + { + return LinkedHashMap::IsKey(key); + } + + bool Has(JSTaggedValue value, int hash) const; int GetSize() const; diff --git a/runtime/js_typed_array.cpp b/runtime/js_typed_array.cpp index b41f0f7dc91f3d0aef5b573be40b6a6b62a9561c..88497b63a77f66c6a4c635a4af8b2c3322b33709 100644 --- a/runtime/js_typed_array.cpp +++ b/runtime/js_typed_array.cpp @@ -310,11 +310,15 @@ OperationResult JSTypedArray::IntegerIndexedElementGet(JSThread *thread, const J ASSERT(typedarray->IsTypedArray()); // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot. JSHandle typedarrayObj(typedarray); - JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); - // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { - THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", - OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); + // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } } // 5. If IsInteger(index) is false, return undefined if (!index.IsInteger()) { @@ -349,7 +353,13 @@ OperationResult JSTypedArray::IntegerIndexedElementGet(JSThread *thread, const J // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName. DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj); // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType). - JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true); + JSTaggedValue result; + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); + result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true); + } return OperationResult(thread, result, PropertyMetaData(true)); } @@ -400,11 +410,15 @@ OperationResult JSTypedArray::FastElementGet(JSThread *thread, const JSHandleIsTypedArray()); // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot. JSHandle typedarrayObj(typedarray); - JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); - // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { - THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", - OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); + // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } } // 7. Let length be the value of O’s [[ArrayLength]] internal slot. @@ -422,8 +436,13 @@ OperationResult JSTypedArray::FastElementGet(JSThread *thread, const JSHandleGetViewedArrayBuffer(); + JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true); + return OperationResult(thread, result, PropertyMetaData(true)); + } } // 9.4.5.9 IntegerIndexedElementSet ( O, index, value ) @@ -442,10 +461,14 @@ bool JSTypedArray::IntegerIndexedElementSet(JSThread *thread, const JSHandle typedarrayObj(typedarray); - JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); - // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { - THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false); + { + // We use buffer without handle and GC can move it. So we have to get buffer each time. + // To make developer get buffer each time use scope and don't populate buffer into function's scope. + JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer(); + // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false); + } } // 7. If IsInteger(index) is false, return false if (!index.IsInteger()) { @@ -481,7 +504,12 @@ bool JSTypedArray::IntegerIndexedElementSet(JSThread *thread, const JSHandleGetViewedArrayBuffer(); + BuiltinsArrayBuffer::SetValueInBuffer(buffer, byteIndex, elementType, numVal, true); + } // 17. Return true. return true; } diff --git a/runtime/js_weak_container.cpp b/runtime/js_weak_container.cpp index 5037e197e227393846a60adc1d512a21118534ad..4a194a067bec0e720d994f2e36a55102062f8e62 100644 --- a/runtime/js_weak_container.cpp +++ b/runtime/js_weak_container.cpp @@ -37,7 +37,11 @@ void JSWeakMap::Set(JSThread *thread, const JSHandle &map, const JSHa bool JSWeakMap::Delete(JSThread *thread, const JSHandle &map, const JSHandle &key) { JSHandle mapHandle(thread, LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())); - int entry = mapHandle->FindElement(key.GetTaggedValue()); + if (!LinkedHashSet::IsKey(key.GetTaggedValue())) { + return false; + } + int hash = LinkedHash::Hash(key.GetTaggedValue()); + int entry = mapHandle->FindElement(key.GetTaggedValue(), hash); if (entry == -1) { return false; } @@ -48,14 +52,14 @@ bool JSWeakMap::Delete(JSThread *thread, const JSHandle &map, const J return true; } -bool JSWeakMap::Has(JSTaggedValue key) const +bool JSWeakMap::Has(JSTaggedValue key, int hash) const { - return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Has(key); + return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Has(key, hash); } -JSTaggedValue JSWeakMap::Get(JSTaggedValue key) const +JSTaggedValue JSWeakMap::Get(JSTaggedValue key, int hash) const { - return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Get(key); + return LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject())->Get(key, hash); } int JSWeakMap::GetSize() const @@ -77,7 +81,8 @@ void JSWeakSet::Add(JSThread *thread, const JSHandle &weakSet, const bool JSWeakSet::Delete(JSThread *thread, const JSHandle &weakSet, const JSHandle &value) { JSHandle weakSetHandle(thread, LinkedHashSet::Cast(weakSet->GetLinkedSet().GetTaggedObject())); - int entry = weakSetHandle->FindElement(value.GetTaggedValue()); + int hash = LinkedHash::Hash(value.GetTaggedValue()); + int entry = weakSetHandle->FindElement(value.GetTaggedValue(), hash); if (entry == -1) { return false; } @@ -87,9 +92,9 @@ bool JSWeakSet::Delete(JSThread *thread, const JSHandle &weakSet, con return true; } -bool JSWeakSet::Has(JSTaggedValue value) const +bool JSWeakSet::Has(JSTaggedValue value, int hash) const { - return LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject())->Has(value); + return LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject())->Has(value, hash); } int JSWeakSet::GetSize() const diff --git a/runtime/js_weak_container.h b/runtime/js_weak_container.h index d8aac384c605d72dd6b58c00588dff2ac25fe775..1361b7b227978f3c0daff46578ba94c35295bfbb 100644 --- a/runtime/js_weak_container.h +++ b/runtime/js_weak_container.h @@ -34,9 +34,9 @@ public: static void Set(JSThread *thread, const JSHandle &map, const JSHandle &key, const JSHandle &value); - bool Has(JSTaggedValue key) const; + bool Has(JSTaggedValue key, int hash) const; - JSTaggedValue Get(JSTaggedValue key) const; + JSTaggedValue Get(JSTaggedValue key, int hash) const; int GetSize() const; @@ -58,7 +58,7 @@ public: static void Add(JSThread *thread, const JSHandle &set, const JSHandle &value); - bool Has(JSTaggedValue value) const; + bool Has(JSTaggedValue value, int hash) const; int GetSize() const; diff --git a/runtime/linked_hash_table-inl.h b/runtime/linked_hash_table-inl.h index 7ab230b9c49477062e02ad87b66f23f43650b37c..c432682ffda42de6eea670a458f0ffac8f2240d5 100644 --- a/runtime/linked_hash_table-inl.h +++ b/runtime/linked_hash_table-inl.h @@ -181,12 +181,9 @@ void LinkedHashTable::InsertNewEntry(const JSThread *thread } template -int LinkedHashTable::FindElement(JSTaggedValue key) const +int LinkedHashTable::FindElement(JSTaggedValue key, int hash) const { - if (!IsKey(key)) { - return -1; - } - int hash = LinkedHash::Hash(key); + ASSERT(IsKey(key)); int bucket = HashToBucket(hash); for (JSTaggedValue entry = GetElement(BucketToIndex(bucket)); !entry.IsHole(); entry = GetNextEntry(entry.GetInt())) { diff --git a/runtime/linked_hash_table.cpp b/runtime/linked_hash_table.cpp index b38d7ec1a24f3f55efe192b75f5cc8c94fcfcb4b..36237a1038898633db342c0413732421e0b1ff89 100644 --- a/runtime/linked_hash_table.cpp +++ b/runtime/linked_hash_table.cpp @@ -44,7 +44,7 @@ JSHandle LinkedHashTable::Insert(const JSThread *t { ASSERT(IsKey(key.GetTaggedValue())); int hash = LinkedHash::Hash(key.GetTaggedValue()); - int entry = table->FindElement(key.GetTaggedValue()); + int entry = table->FindElement(key.GetTaggedValue(), hash); if (entry != -1) { table->SetValue(thread, entry, value.GetTaggedValue()); return table; @@ -121,7 +121,9 @@ template JSHandle LinkedHashTable::Remove(const JSThread *thread, const JSHandle &table, const JSHandle &key) { - int entry = table->FindElement(key.GetTaggedValue()); + ASSERT(IsKey(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + int entry = table->FindElement(key.GetTaggedValue(), hash); if (entry == -1) { return table; } @@ -170,18 +172,20 @@ JSHandle LinkedHashMap::Set(const JSThread *thread, const JSHandl return LinkedHashTable::Insert(thread, obj, key, value); } -JSTaggedValue LinkedHashMap::Get(JSTaggedValue key) const +JSTaggedValue LinkedHashMap::Get(JSTaggedValue key, int hash) const { - int entry = FindElement(key); + ASSERT(IsKey(key)); + int entry = FindElement(key, hash); if (entry == -1) { return JSTaggedValue::Undefined(); } return GetValue(entry); } -bool LinkedHashMap::Has(JSTaggedValue key) const +bool LinkedHashMap::Has(JSTaggedValue key, int hash) const { - int entry = FindElement(key); + ASSERT(IsKey(key)); + int entry = FindElement(key, hash); return entry != -1; } @@ -221,9 +225,10 @@ JSHandle LinkedHashSet::Add(const JSThread *thread, const JSHandl return LinkedHashTable::Insert(thread, obj, key, key); } -bool LinkedHashSet::Has(JSTaggedValue key) const +bool LinkedHashSet::Has(JSTaggedValue key, int hash) const { - int entry = FindElement(key); + ASSERT(IsKey(key)); + int entry = FindElement(key, hash); return entry != -1; } diff --git a/runtime/linked_hash_table.h b/runtime/linked_hash_table.h index 8730c1db4ac681283d160560d597d3fd0e568a1d..96b3480bdb89a1027ff98f658bcb35fa11d8f17d 100644 --- a/runtime/linked_hash_table.h +++ b/runtime/linked_hash_table.h @@ -59,7 +59,7 @@ public: inline bool HasSufficientCapacity(int numOfAddElements) const; - inline int FindElement(JSTaggedValue key) const; + inline int FindElement(JSTaggedValue key, int hash) const; inline void RemoveEntry(const JSThread *thread, int entry); @@ -155,12 +155,12 @@ public: static JSHandle Set(const JSThread *thread, const JSHandle &obj, const JSHandle &key, const JSHandle &value); - JSTaggedValue Get(JSTaggedValue key) const; + JSTaggedValue Get(JSTaggedValue key, int hash) const; static JSHandle Shrink(const JSThread *thread, const JSHandle &table, int additionalCapacity = 0); - bool Has(JSTaggedValue key) const; + bool Has(JSTaggedValue key, int hash) const; void Clear(const JSThread *thread); DECL_DUMP() @@ -201,7 +201,7 @@ public: static JSHandle Shrink(const JSThread *thread, const JSHandle &table, int additionalCapacity = 0); - bool Has(JSTaggedValue key) const; + bool Has(JSTaggedValue key, int hash) const; void Clear(const JSThread *thread); DECL_DUMP() diff --git a/runtime/object_factory.cpp b/runtime/object_factory.cpp index 7d0a8eb3177835e66761f4db10d1c34c4e8c9e6c..9215fb9f0c2aed8c2d77ffed7e4b77885ea399d4 100644 --- a/runtime/object_factory.cpp +++ b/runtime/object_factory.cpp @@ -1630,6 +1630,7 @@ JSHandle ObjectFactory::NewTaggedArrayImpl(uint32_t length, JSTagge return weak ? EmptyWeakArray() : EmptyArray(); } + ASSERT(!initVal.IsHeapObject()); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heapHelper_.AllocateYoungGenerationOrHugeObject(weak ? weakArrayClass_ : arrayClass_, size); JSHandle array(thread_, header); @@ -2024,11 +2025,11 @@ JSHandle ObjectFactory::CreateJSPromiseExecutorFuncti } JSHandle ObjectFactory::CreateBuiltinFunction(EcmaEntrypoint steps, uint8_t length, - JSHandle name, JSTaggedValue proto, + JSHandle name, JSHandle proto, JSHandle prefix) { JSHandle function = NewJSFunction(vm_->GetGlobalEnv(), reinterpret_cast(steps)); - function->SetFunctionPrototype(thread_, proto); + function->SetFunctionPrototype(thread_, proto.GetTaggedValue()); function->GetJSHClass()->SetExtensible(true); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(length)); JSHandle baseFunction(function); diff --git a/runtime/object_factory.h b/runtime/object_factory.h index be2bd732d9f48265982b0c19c4779713c6335d91..767a130b6845bf9802f7b992dd5fa8cbeeca7185 100644 --- a/runtime/object_factory.h +++ b/runtime/object_factory.h @@ -300,7 +300,7 @@ public: JSHandle CreateJSPromiseExecutorFunction(const void *nativeFunc); JSHandle CreateBuiltinFunction(EcmaEntrypoint steps, uint8_t length, JSHandle name, - JSTaggedValue proto, JSHandle prefix); + JSHandle proto, JSHandle prefix); JSHandle NewJSPromiseAllResolveElementFunction(const void *nativeFunc); diff --git a/tests/runtime/common/js_map_test.cpp b/tests/runtime/common/js_map_test.cpp index 4e24b69646eadef544de71a54c8f486c8e8958b8..b041a951a5f0f4c2f2485ff3270d75c838628e83 100644 --- a/tests/runtime/common/js_map_test.cpp +++ b/tests/runtime/common/js_map_test.cpp @@ -83,7 +83,8 @@ TEST_F(JSMapTest, AddAndHas) JSHandle key(factory_->NewFromString("key")); JSHandle value(thread, JSTaggedValue(1)); JSMap::Set(thread, map, key, value); - EXPECT_TRUE(map->Has(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_TRUE(map->Has(key.GetTaggedValue(), hash)); } TEST_F(JSMapTest, DeleteAndGet) @@ -99,7 +100,8 @@ TEST_F(JSMapTest, DeleteAndGet) JSHandle key(factory_->NewFromString(key_array)); JSHandle value(thread, JSTaggedValue(i)); JSMap::Set(thread, map, key, value); - EXPECT_TRUE(map->Has(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_TRUE(map->Has(key.GetTaggedValue(), hash)); } EXPECT_EQ(map->GetSize(), 40); // whether js_map has delete key @@ -107,7 +109,8 @@ TEST_F(JSMapTest, DeleteAndGet) JSHandle delete_key(factory_->NewFromString(key_array)); EXPECT_EQ(map->GetValue(8), JSTaggedValue(8)); JSMap::Delete(thread, map, delete_key); - EXPECT_FALSE(map->Has(delete_key.GetTaggedValue())); + int hash = LinkedHash::Hash(delete_key.GetTaggedValue()); + EXPECT_FALSE(map->Has(delete_key.GetTaggedValue(), hash)); EXPECT_EQ(map->GetSize(), 39); } diff --git a/tests/runtime/common/js_set_test.cpp b/tests/runtime/common/js_set_test.cpp index ce41c922cdcfdae7e859e6ccedf52f32a1640ae5..b30d19153617a7df0991c415f9399a06fca23caa 100644 --- a/tests/runtime/common/js_set_test.cpp +++ b/tests/runtime/common/js_set_test.cpp @@ -84,7 +84,8 @@ TEST_F(JSSetTest, AddAndHas) // JSHandle key(factory_->NewFromString("key")); JSSet::Add(thread, set, key); - EXPECT_TRUE(set->Has(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_TRUE(set->Has(key.GetTaggedValue(), hash)); } TEST_F(JSSetTest, DeleteAndGet) @@ -99,14 +100,16 @@ TEST_F(JSSetTest, DeleteAndGet) key_array[3] = '1' + i; JSHandle key(factory_->NewFromString(key_array)); JSSet::Add(thread, set, key); - EXPECT_TRUE(set->Has(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_TRUE(set->Has(key.GetTaggedValue(), hash)); } EXPECT_EQ(set->GetSize(), 40); // whether js_set has delete key key_array[3] = '1' + 8; JSHandle delete_key(factory_->NewFromString(key_array)); JSSet::Delete(thread, set, delete_key); - EXPECT_FALSE(set->Has(delete_key.GetTaggedValue())); + int hash = LinkedHash::Hash(delete_key.GetTaggedValue()); + EXPECT_FALSE(set->Has(delete_key.GetTaggedValue(), hash)); EXPECT_EQ(set->GetSize(), 39); } diff --git a/tests/runtime/common/linked_hash_table_test.cpp b/tests/runtime/common/linked_hash_table_test.cpp index 656505368bbf164f6b9c7e929abfab26796ef112..5ca6f2dd97ef7760f11e5d8cb99522a27f5c7478 100644 --- a/tests/runtime/common/linked_hash_table_test.cpp +++ b/tests/runtime/common/linked_hash_table_test.cpp @@ -100,7 +100,8 @@ TEST_F(LinkedHashTableTest, addKeyAndValue) EXPECT_EQ(dictHandle->NumberOfElements(), 1); // test find() - int entry1 = dictHandle->FindElement(key1.GetTaggedValue()); + int hash = LinkedHash::Hash(key1.GetTaggedValue()); + int entry1 = dictHandle->FindElement(key1.GetTaggedValue(), hash); EXPECT_EQ(key1.GetTaggedValue(), dictHandle->GetKey(entry1)); EXPECT_EQ(value1.GetTaggedValue(), dictHandle->GetValue(entry1)); @@ -108,12 +109,13 @@ TEST_F(LinkedHashTableTest, addKeyAndValue) EXPECT_EQ(dictHandle->NumberOfElements(), 2); // test remove() dictHandle = LinkedHashMap::Delete(thread, dictHandle, key1); - EXPECT_EQ(-1, dictHandle->FindElement(key1.GetTaggedValue())); + EXPECT_EQ(-1, dictHandle->FindElement(key1.GetTaggedValue(), hash)); EXPECT_EQ(dictHandle->NumberOfElements(), 1); JSHandle undefinedKey(thread, JSTaggedValue::Undefined()); dictHandle = LinkedHashMap::Set(thread, dictHandle, undefinedKey, value1); - int entry2 = dictHandle->FindElement(undefinedKey.GetTaggedValue()); + int undefinedHash = LinkedHash::Hash(undefinedKey.GetTaggedValue()); + int entry2 = dictHandle->FindElement(undefinedKey.GetTaggedValue(), undefinedHash); EXPECT_EQ(value1.GetTaggedValue(), dictHandle->GetValue(entry2)); } @@ -141,18 +143,20 @@ TEST_F(LinkedHashTableTest, SetaddKeyAndValue) EXPECT_EQ(setHandle->NumberOfElements(), 1); // test has() - EXPECT_TRUE(setHandle->Has(key1.GetTaggedValue())); + int hash = LinkedHash::Hash(key1.GetTaggedValue()); + EXPECT_TRUE(setHandle->Has(key1.GetTaggedValue(), hash)); setHandle = LinkedHashSet::Add(thread, setHandle, key2); EXPECT_EQ(setHandle->NumberOfElements(), 2); // test remove() setHandle = LinkedHashSet::Delete(thread, setHandle, key1); - EXPECT_EQ(-1, setHandle->FindElement(key1.GetTaggedValue())); + EXPECT_EQ(-1, setHandle->FindElement(key1.GetTaggedValue(), hash)); EXPECT_EQ(setHandle->NumberOfElements(), 1); JSHandle undefinedKey(thread, JSTaggedValue::Undefined()); setHandle = LinkedHashSet::Add(thread, setHandle, undefinedKey); - EXPECT_TRUE(setHandle->Has(undefinedKey.GetTaggedValue())); + int undefinedHash = LinkedHash::Hash(undefinedKey.GetTaggedValue()); + EXPECT_TRUE(setHandle->Has(undefinedKey.GetTaggedValue(), undefinedHash)); } TEST_F(LinkedHashTableTest, GrowCapacity) @@ -171,7 +175,8 @@ TEST_F(LinkedHashTableTest, GrowCapacity) // test insert() dictHandle = LinkedHashMap::Set(thread, dictHandle, key, value); - EXPECT_EQ(i, dictHandle->FindElement(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_EQ(i, dictHandle->FindElement(key.GetTaggedValue(), hash)); } // test order @@ -180,7 +185,8 @@ TEST_F(LinkedHashTableTest, GrowCapacity) keyArray[6] = 0; JSHandle stringKey = factory->NewFromCanBeCompressString(keyArray); // test insert() - EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue())); + int hash = LinkedHash::Hash(stringKey.GetTaggedValue()); + EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue(), hash)); } EXPECT_EQ(dictHandle->NumberOfElements(), 33); EXPECT_EQ(dictHandle->Capacity(), 64); @@ -203,7 +209,8 @@ TEST_F(LinkedHashTableTest, SetGrowCapacity) // test insert() setHandle = LinkedHashSet::Add(thread, setHandle, key); - EXPECT_EQ(i, setHandle->FindElement(key.GetTaggedValue())); + int hash = LinkedHash::Hash(key.GetTaggedValue()); + EXPECT_EQ(i, setHandle->FindElement(key.GetTaggedValue(), hash)); } // test order @@ -212,7 +219,8 @@ TEST_F(LinkedHashTableTest, SetGrowCapacity) keyArray[6] = 0; JSHandle stringKey = factory->NewFromCanBeCompressString(keyArray); // test insert() - EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue())); + int hash = LinkedHash::Hash(stringKey.GetTaggedValue()); + EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue(), hash)); } EXPECT_EQ(setHandle->NumberOfElements(), 33); EXPECT_EQ(setHandle->Capacity(), 64); @@ -244,7 +252,8 @@ TEST_F(LinkedHashTableTest, ShrinkCapacity) keyArray[6] = 0; JSHandle stringKey = factory->NewFromCanBeCompressString(keyArray); // test insert() - EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue())); + int hash = LinkedHash::Hash(stringKey.GetTaggedValue()); + EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue(), hash)); } EXPECT_EQ(dictHandle->NumberOfElements(), 9); EXPECT_EQ(dictHandle->Capacity(), 16); @@ -276,7 +285,8 @@ TEST_F(LinkedHashTableTest, SetShrinkCapacity) keyArray[6] = 0; JSHandle stringKey = factory->NewFromCanBeCompressString(keyArray); // test insert() - EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue())); + int hash = LinkedHash::Hash(stringKey.GetTaggedValue()); + EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue(), hash)); } EXPECT_EQ(setHandle->NumberOfElements(), 9); EXPECT_EQ(setHandle->Capacity(), 16);