mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
!6776 Implement hash calculation for numbers and objects
Merge pull request !6776 from udav/hash
This commit is contained in:
commit
e4f5cab36b
@ -1178,7 +1178,7 @@ uint64_t RandomGenerator::XorShift64(uint64_t *pVal)
|
||||
return x * GET_MULTIPLY;
|
||||
}
|
||||
|
||||
void RandomGenerator::InitRandom()
|
||||
void RandomGenerator::InitRandom(JSThread *thread)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
@ -1187,6 +1187,7 @@ void RandomGenerator::InitRandom()
|
||||
if (randomState_ == 0) {
|
||||
randomState_ = 1;
|
||||
}
|
||||
thread->SetRandomStatePtr(&randomState_);
|
||||
}
|
||||
|
||||
double RandomGenerator::NextDouble()
|
||||
|
@ -171,7 +171,7 @@ private:
|
||||
// The value is used in xorshift64* random generator to generate result.
|
||||
class RandomGenerator {
|
||||
public:
|
||||
static void InitRandom();
|
||||
static void InitRandom(JSThread *thread);
|
||||
static double NextDouble();
|
||||
static int32_t GenerateIdentityHash();
|
||||
static int32_t Next(int bits);
|
||||
|
@ -1557,7 +1557,7 @@ void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JST
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread_);
|
||||
JSHandle<JSHClass> mathClass = factory_->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal);
|
||||
JSHandle<JSObject> mathObject = factory_->NewJSObjectWithInit(mathClass);
|
||||
RandomGenerator::InitRandom();
|
||||
RandomGenerator::InitRandom(thread_);
|
||||
|
||||
for (const base::BuiltinFunctionEntry &entry: Math::GetMathFunctions()) {
|
||||
SetFunction(env, mathObject, entry.GetName(), entry.GetEntrypoint(),
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "ecmascript/property_detector-inl.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
|
||||
#include "ecmascript/linked_hash_table.h"
|
||||
#include "builtins_typedarray.h"
|
||||
#include "ecmascript/jit/jit.h"
|
||||
|
||||
@ -250,6 +251,15 @@ JSTaggedValue BuiltinsArkTools::CheckCircularImport(EcmaRuntimeCallInfo *info)
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::HashCode(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(info, 0);
|
||||
return JSTaggedValue(LinkedHash::Hash(thread, key.GetTaggedValue()));
|
||||
}
|
||||
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
JSTaggedValue BuiltinsArkTools::StartCpuProfiler(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
|
@ -49,7 +49,8 @@
|
||||
V("printTypedOpProfilerAndReset", PrintTypedOpProfilerAndReset, 1, INVALID) \
|
||||
V("isOnHeap", IsOnHeap, 1, INVALID) \
|
||||
V("checkDeoptStatus", CheckDeoptStatus, 2, INVALID) \
|
||||
V("checkCircularImport", CheckCircularImport, 2, INVALID)
|
||||
V("checkCircularImport", CheckCircularImport, 2, INVALID) \
|
||||
V("hashCode", HashCode, 1, ArkToolsHashCode)
|
||||
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \
|
||||
V("prepareFunctionForOptimization", PrepareFunctionForOptimization, 1, INVALID) \
|
||||
@ -170,6 +171,8 @@ public:
|
||||
|
||||
static JSTaggedValue CheckCircularImport(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue HashCode(EcmaRuntimeCallInfo *info);
|
||||
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
static JSTaggedValue StartCpuProfiler(EcmaRuntimeCallInfo *info);
|
||||
|
||||
|
@ -126,6 +126,7 @@ libark_jsoptimizer_sources = [
|
||||
"gate_accessor.cpp",
|
||||
"graph_editor.cpp",
|
||||
"graph_linearizer.cpp",
|
||||
"hash_stub_builder.cpp",
|
||||
"hcr_circuit_builder.cpp",
|
||||
"hcr_gate_meta_data.cpp",
|
||||
"ic_stub_builder.cpp",
|
||||
|
@ -31,7 +31,8 @@ namespace panda::ecmascript::kungfu {
|
||||
BUILTINS_METHOD_STUB_LIST(D, D, D) \
|
||||
BUILTINS_WITH_CONTAINERS_STUB_BUILDER(D) \
|
||||
BUILTINS_CONSTRUCTOR_STUB_LIST(V) \
|
||||
AOT_AND_BUILTINS_STUB_LIST(V)
|
||||
AOT_AND_BUILTINS_STUB_LIST(V) \
|
||||
BUILTINS_ARKTOOLS_STUB_BUILDER(D)
|
||||
|
||||
#define BUILTINS_METHOD_STUB_LIST(V, T, D) \
|
||||
BUILTINS_WITH_STRING_STUB_BUILDER(V) \
|
||||
@ -147,6 +148,9 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ReplaceAllElements, ArrayList, ContainersCommonFuncCall, ARRAYLIST_REPLACEALLELEMENTS, JS_POINTER) \
|
||||
V(ReplaceAllElements, Vector, ContainersCommonFuncCall, VECTOR_REPLACEALLELEMENTS, JS_POINTER)
|
||||
|
||||
#define BUILTINS_ARKTOOLS_STUB_BUILDER(V) \
|
||||
V(HashCode, ArkTools, Undefined())
|
||||
|
||||
#define BUILTINS_CONSTRUCTOR_STUB_LIST(V) \
|
||||
V(BooleanConstructor) \
|
||||
V(NumberConstructor) \
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "ecmascript/compiler/new_object_stub_builder.h"
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/compiler/stub_builder.h"
|
||||
#include "ecmascript/compiler/hash_stub_builder.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
@ -217,6 +218,28 @@ BUILTINS_METHOD_STUB_LIST(DECLARE_BUILTINS_STUB_BUILDER, DECLARE_BUILTINS_STUB_B
|
||||
#undef DECLARE_BUILTINS_STUB_BUILDER1
|
||||
#undef DECLARE_BUILTINS_COLLECTION_STUB_BUILDER
|
||||
|
||||
DECLARE_BUILTINS(ArkToolsHashCode)
|
||||
{
|
||||
(void) nativeCode;
|
||||
(void) func;
|
||||
(void) newTarget;
|
||||
(void) thisValue;
|
||||
auto env = GetEnvironment();
|
||||
GateRef key = GetCallArg0(numArgs);
|
||||
|
||||
Label irHash(env);
|
||||
Label rtHash(env);
|
||||
BRANCH(IntPtrEqual(numArgs, IntPtr(1)), &irHash, &rtHash);
|
||||
Bind(&irHash);
|
||||
{
|
||||
HashStubBuilder hashBuilder(this, glue);
|
||||
GateRef hash = hashBuilder.GetHash(key);
|
||||
Return(env->GetBuilder()->Int32ToTaggedPtr(hash));
|
||||
}
|
||||
Bind(&rtHash);
|
||||
Return(CallRuntime(glue, RTSTUB_ID(GetLinkedHash), { key }));
|
||||
}
|
||||
|
||||
// aot and builtins public stub function
|
||||
#define DECLARE_AOT_AND_BUILTINS_STUB_BUILDER(stubName, method, type, initValue) \
|
||||
DECLARE_BUILTINS(stubName) \
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "ecmascript/compiler/builtins/linked_hashtable_stub_builder.h"
|
||||
|
||||
#include "ecmascript/compiler/builtins/builtins_stubs.h"
|
||||
#include "ecmascript/compiler/hash_stub_builder.h"
|
||||
#include "ecmascript/compiler/new_object_stub_builder.h"
|
||||
#include "ecmascript/linked_hash_table.h"
|
||||
#include "ecmascript/js_set.h"
|
||||
@ -72,7 +73,8 @@ void LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::Reh
|
||||
}
|
||||
Bind(¬Weak);
|
||||
|
||||
GateRef hash = GetHash(*key);
|
||||
HashStubBuilder hashBuilder(this, glue_);
|
||||
GateRef hash = hashBuilder.GetHash(*key);
|
||||
GateRef bucket = HashToBucket(newTable, hash);
|
||||
InsertNewEntry(newTable, bucket, *desEntry);
|
||||
GateRef desIndex = EntryToIndex(newTable, *desEntry);
|
||||
@ -222,45 +224,6 @@ GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename LinkedHashTableType, typename LinkedHashTableObject>
|
||||
GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::GetHash(GateRef key)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entryLabel(env);
|
||||
Label exit(env);
|
||||
env->SubCfgEntry(&entryLabel);
|
||||
DEFVARIABLE(res, VariableType::INT32(), Int32(0));
|
||||
|
||||
Label symbolKey(env);
|
||||
Label stringCheck(env);
|
||||
BRANCH(TaggedIsSymbol(key), &symbolKey, &stringCheck);
|
||||
Bind(&symbolKey);
|
||||
{
|
||||
res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&stringCheck);
|
||||
Label stringKey(env);
|
||||
Label slowGetHash(env);
|
||||
BRANCH(TaggedIsString(key), &stringKey, &slowGetHash);
|
||||
Bind(&stringKey);
|
||||
{
|
||||
res = GetHashcodeFromString(glue_, key);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&slowGetHash);
|
||||
{
|
||||
// GetHash();
|
||||
GateRef hash = CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key });
|
||||
res = GetInt32OfTInt(hash);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *res;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename LinkedHashTableType, typename LinkedHashTableObject>
|
||||
GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::HashObjectIsMatch(
|
||||
GateRef key, GateRef other)
|
||||
@ -543,7 +506,8 @@ GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::
|
||||
env->SubCfgEntry(&cfgEntry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(res, VariableType::JS_ANY(), linkedTable);
|
||||
GateRef hash = GetHash(key);
|
||||
HashStubBuilder hashBuilder(this, glue_);
|
||||
GateRef hash = hashBuilder.GetHash(key);
|
||||
GateRef entry = FindElement(linkedTable, key, hash);
|
||||
Label findEntry(env);
|
||||
Label notFind(env);
|
||||
@ -589,7 +553,8 @@ GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::
|
||||
env->SubCfgEntry(&cfgEntry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(res, VariableType::JS_ANY(), TaggedFalse());
|
||||
GateRef hash = GetHash(key);
|
||||
HashStubBuilder hashBuilder(this, glue_);
|
||||
GateRef hash = hashBuilder.GetHash(key);
|
||||
GateRef entry = FindElement(linkedTable, key, hash);
|
||||
Label findEntry(env);
|
||||
BRANCH(Int32Equal(entry, Int32(-1)), &exit, &findEntry);
|
||||
@ -624,7 +589,9 @@ GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::
|
||||
GateRef size = GetNumberOfElements(linkedTable);
|
||||
BRANCH(Int32Equal(size, Int32(0)), &exit, &nonEmpty);
|
||||
Bind(&nonEmpty);
|
||||
GateRef hash = GetHash(key);
|
||||
HashStubBuilder hashBuilder(this, glue_);
|
||||
GateRef hash = hashBuilder.GetHash(key);
|
||||
|
||||
GateRef entry = FindElement(linkedTable, key, hash);
|
||||
Label findEntry(env);
|
||||
BRANCH(Int32Equal(entry, Int32(-1)), &exit, &findEntry);
|
||||
@ -747,7 +714,8 @@ GateRef LinkedHashTableStubBuilder<LinkedHashTableType, LinkedHashTableObject>::
|
||||
env->SubCfgEntry(&cfgEntry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
|
||||
GateRef hash = GetHash(key);
|
||||
HashStubBuilder hashBuilder(this, glue_);
|
||||
GateRef hash = hashBuilder.GetHash(key);
|
||||
GateRef entry = FindElement(linkedTable, key, hash);
|
||||
Label findEntry(env);
|
||||
Branch(Int32Equal(entry, Int32(-1)), &exit, &findEntry);
|
||||
|
@ -56,7 +56,6 @@ private:
|
||||
return Int32Add(bucket, Int32(LinkedHashTableType::ELEMENTS_START_INDEX));
|
||||
}
|
||||
|
||||
GateRef GetHash(GateRef key);
|
||||
GateRef HashObjectIsMatch(GateRef key, GateRef other);
|
||||
GateRef FindElement(GateRef linkedTable, GateRef key, GateRef hash);
|
||||
GateRef GetKey(GateRef linkedTable, GateRef entry)
|
||||
|
@ -719,6 +719,8 @@ public:
|
||||
GateRef NumberToString(GateRef number);
|
||||
GateRef TaggedPointerToInt64(GateRef x);
|
||||
GateRef GetLengthFromString(GateRef value);
|
||||
GateRef Rotl(GateRef word, uint32_t shift);
|
||||
GateRef CalcHashcodeForInt(GateRef value);
|
||||
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
|
||||
GateRef TryGetHashcodeFromString(GateRef string);
|
||||
GateRef IsIntegerString(GateRef string);
|
||||
|
89
ecmascript/compiler/hash_stub_builder.cpp
Normal file
89
ecmascript/compiler/hash_stub_builder.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/hash_stub_builder.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
GateRef HashStubBuilder::GetHash(GateRef key)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entryLabel(env);
|
||||
Label exit(env);
|
||||
env->SubCfgEntry(&entryLabel);
|
||||
DEFVARIABLE(res, VariableType::INT32(), Int32(0));
|
||||
|
||||
Label slowGetHash(env);
|
||||
Label symbolKey(env);
|
||||
Label stringCheck(env);
|
||||
BRANCH(TaggedIsSymbol(key), &symbolKey, &stringCheck);
|
||||
|
||||
Bind(&symbolKey);
|
||||
res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET));
|
||||
Jump(&exit);
|
||||
|
||||
Bind(&stringCheck);
|
||||
Label stringKey(env);
|
||||
Label objectCheck(env);
|
||||
BRANCH(TaggedIsString(key), &stringKey, &objectCheck);
|
||||
Bind(&stringKey);
|
||||
res = GetHashcodeFromString(glue_, key);
|
||||
Jump(&exit);
|
||||
|
||||
Bind(&objectCheck);
|
||||
Label heapObjectKey(env);
|
||||
Label numberCheck(env);
|
||||
BRANCH(TaggedIsHeapObject(key), &heapObjectKey, &numberCheck);
|
||||
|
||||
Bind(&heapObjectKey);
|
||||
Label ecmaObjectKey(env);
|
||||
BRANCH(TaggedObjectIsEcmaObject(key), &ecmaObjectKey, &slowGetHash);
|
||||
Bind(&ecmaObjectKey);
|
||||
CalcHashcodeForObject(glue_, key, &res, &exit);
|
||||
|
||||
Bind(&numberCheck);
|
||||
Label numberKey(env);
|
||||
BRANCH(TaggedIsNumber(key), &numberKey, &slowGetHash);
|
||||
|
||||
Bind(&numberKey);
|
||||
CalcHashcodeForNumber(key, &res, &exit);
|
||||
|
||||
Bind(&slowGetHash);
|
||||
res = GetInt32OfTInt(CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key }));
|
||||
Jump(&exit);
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *res;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HashStubBuilder::CalcHashcodeForNumber(GateRef key, Variable *res, Label *exit)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label doubleKey(env);
|
||||
Label intKey(env);
|
||||
BRANCH(TaggedIsDouble(key), &doubleKey, &intKey);
|
||||
Bind(&doubleKey);
|
||||
{
|
||||
CalcHashcodeForDouble(key, res, exit);
|
||||
}
|
||||
Bind(&intKey);
|
||||
{
|
||||
*res = CalcHashcodeForInt(key);
|
||||
Jump(exit);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
41
ecmascript/compiler/hash_stub_builder.h
Normal file
41
ecmascript/compiler/hash_stub_builder.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_HASH_STUB_BUILDER_H
|
||||
#define ECMASCRIPT_COMPILER_HASH_STUB_BUILDER_H
|
||||
|
||||
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
|
||||
#include "ecmascript/compiler/profiler_operation.h"
|
||||
#include "ecmascript/compiler/stub_builder.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class HashStubBuilder : public StubBuilder {
|
||||
public:
|
||||
explicit HashStubBuilder(StubBuilder *parent, GateRef glue)
|
||||
: StubBuilder(parent), glue_(glue) {}
|
||||
~HashStubBuilder() override = default;
|
||||
NO_MOVE_SEMANTIC(HashStubBuilder);
|
||||
NO_COPY_SEMANTIC(HashStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
GateRef GetHash(GateRef key);
|
||||
|
||||
private:
|
||||
void CalcHashcodeForNumber(GateRef key, Variable *res, Label *exit);
|
||||
|
||||
GateRef glue_;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_HASH_STUB_BUILDER_H
|
@ -13,6 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "libpandabase/utils/hash.h"
|
||||
|
||||
#include "ecmascript/compiler/mcr_circuit_builder.h"
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
@ -1214,6 +1216,43 @@ GateRef CircuitBuilder::GetLengthFromString(GateRef value)
|
||||
return Int32LSR(len, Int32(EcmaString::STRING_LENGTH_SHIFT_COUNT));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Rotl(GateRef word, uint32_t shift)
|
||||
{
|
||||
static constexpr uint32_t MAX_BITS = 32;
|
||||
return Int32Or(Int32LSL(word, Int32(shift)), Int32LSR(word, Int32(MAX_BITS - shift)));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CalcHashcodeForInt(GateRef value)
|
||||
{
|
||||
GateRef rawVal = ChangeTaggedPointerToInt64(value);
|
||||
GateRef low = TruncInt64ToInt32(rawVal);
|
||||
GateRef k1 = Int32Mul(low, Int32(MurmurHash32Const::C1));
|
||||
GateRef k2 = Rotl(k1, MurmurHash32Const::MAIN_FIRST_SHIFT);
|
||||
GateRef k3 = Int32Mul(k2, Int32(MurmurHash32Const::C2));
|
||||
GateRef hash1 = Int32Xor(Int32(DEFAULT_SEED), k3);
|
||||
GateRef hash2 = Rotl(hash1, MurmurHash32Const::MAIN_SECOND_SHIFT);
|
||||
GateRef hash3 = Int32Add(Int32Mul(hash2, Int32(MurmurHash32Const::MAIN_MULTIPLICATOR)),
|
||||
Int32(MurmurHash32Const::MAIN_CONSTANT));
|
||||
|
||||
GateRef high = TruncInt64ToInt32(Int64LSR(rawVal, Int64(32U)));
|
||||
GateRef k4 = Int32Mul(high, Int32(MurmurHash32Const::C1));
|
||||
GateRef k5 = Rotl(k4, MurmurHash32Const::MAIN_FIRST_SHIFT);
|
||||
GateRef k6 = Int32Mul(k5, Int32(MurmurHash32Const::C2));
|
||||
GateRef hash4 = Int32Xor(hash3, k6);
|
||||
GateRef hash5 = Rotl(hash4, MurmurHash32Const::MAIN_SECOND_SHIFT);
|
||||
GateRef hash6 = Int32Add(Int32Mul(hash5, Int32(MurmurHash32Const::MAIN_MULTIPLICATOR)),
|
||||
Int32(MurmurHash32Const::MAIN_CONSTANT));
|
||||
|
||||
GateRef hash7 = Int32Xor(hash6, Int32(8U));
|
||||
// Finalize
|
||||
GateRef hash8 = Int32Xor(hash7, Int32LSR(hash7, Int32(MurmurHash32Const::FINALIZE_FIRST_SHIFT)));
|
||||
GateRef hash9 = Int32Mul(hash8, Int32(MurmurHash32Const::FINALIZE_FIRST_MULTIPLICATOR));
|
||||
GateRef hash10 = Int32Xor(hash9, Int32LSR(hash9, Int32(MurmurHash32Const::FINALIZE_SECOND_SHIFT)));
|
||||
GateRef hash11 = Int32Mul(hash10, Int32(MurmurHash32Const::FINALIZE_SECOND_MULTIPLICATOR));
|
||||
GateRef hash12 = Int32Xor(hash11, Int32LSR(hash11, Int32(MurmurHash32Const::FINALIZE_THIRD_SHIFT)));
|
||||
return hash12;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
|
||||
{
|
||||
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
|
||||
|
@ -1069,6 +1069,12 @@ inline void StubBuilder::SetPropertiesArray(VariableType type, GateRef glue, Gat
|
||||
Store(type, glue, object, propertiesOffset, propsArray);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetHash(GateRef object)
|
||||
{
|
||||
GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), object, hashOffset);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash)
|
||||
{
|
||||
GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
|
||||
|
@ -6737,6 +6737,107 @@ void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
|
||||
return;
|
||||
}
|
||||
|
||||
GateRef StubBuilder::CalcHashcodeForInt(GateRef value)
|
||||
{
|
||||
return env_->GetBuilder()->CalcHashcodeForInt(value);
|
||||
}
|
||||
|
||||
GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits)
|
||||
{
|
||||
GateRef isNanOrInf = Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK));
|
||||
GateRef isSubnormal = BoolAnd(
|
||||
Int64Equal(expBits, Int64(0)),
|
||||
Int64NotEqual(fractionBits, Int64(0)));
|
||||
GateRef hasFraction = Int64NotEqual(
|
||||
Int64And(
|
||||
Int64LSL(fractionBits, exp),
|
||||
Int64(base::DOUBLE_SIGNIFICAND_MASK)),
|
||||
Int64(0));
|
||||
GateRef badExp = BoolOr(
|
||||
Int64LessThan(exp, Int64(0)),
|
||||
Int64GreaterThanOrEqual(exp, Int64(31U)));
|
||||
return BoolOr(BoolOr(BoolOr(isNanOrInf, isSubnormal), badExp), hasFraction);
|
||||
}
|
||||
|
||||
void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
GateRef xInt64 = Int64Sub(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
|
||||
GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK));
|
||||
GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
|
||||
GateRef signBit = Int64And(xInt64, Int64(base::DOUBLE_SIGN_MASK));
|
||||
GateRef isZero = BoolAnd(
|
||||
Int64Equal(expBits, Int64(0)),
|
||||
Int64Equal(fractionBits, Int64(0)));
|
||||
Label zero(env);
|
||||
Label nonZero(env);
|
||||
|
||||
BRANCH(isZero, &zero, &nonZero);
|
||||
Bind(&nonZero);
|
||||
{
|
||||
DEFVARIABLE(value, VariableType::JS_ANY(), x);
|
||||
// exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
|
||||
GateRef exp = Int64Sub(
|
||||
Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)),
|
||||
Int64(base::DOUBLE_EXPONENT_BIAS));
|
||||
Label convertToInt(env);
|
||||
Label calcHash(env);
|
||||
BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt);
|
||||
Bind(&convertToInt);
|
||||
{
|
||||
GateRef shift = Int64Sub(Int64(base::DOUBLE_SIGNIFICAND_SIZE), exp);
|
||||
GateRef intVal = Int64Add(
|
||||
Int64LSL(Int64(1), exp),
|
||||
Int64LSR(fractionBits, shift));
|
||||
DEFVARIABLE(intVariable, VariableType::INT64(), intVal);
|
||||
Label negate(env);
|
||||
Label pass(env);
|
||||
BRANCH(Int64NotEqual(signBit, Int64(0)), &negate, &pass);
|
||||
Bind(&negate);
|
||||
{
|
||||
intVariable = Int64Sub(Int64(0), intVal);
|
||||
Jump(&pass);
|
||||
}
|
||||
Bind(&pass);
|
||||
value = IntToTaggedPtr(TruncInt64ToInt32(*intVariable));
|
||||
Jump(&calcHash);
|
||||
}
|
||||
Bind(&calcHash);
|
||||
{
|
||||
*res = env_->GetBuilder()->CalcHashcodeForInt(*value);
|
||||
Jump(exit);
|
||||
}
|
||||
}
|
||||
|
||||
Bind(&zero);
|
||||
*res = env_->GetBuilder()->CalcHashcodeForInt(IntToTaggedPtr(Int32(0)));
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef hash = GetHash(value);
|
||||
*res = TruncInt64ToInt32(TaggedCastToIntPtr(hash));
|
||||
Label calcHash(env);
|
||||
BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit);
|
||||
Bind(&calcHash);
|
||||
GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit()));
|
||||
GateRef randomStatePtr = Load(VariableType::NATIVE_POINTER(), glue, offset);
|
||||
GateRef randomState = Load(VariableType::INT64(), randomStatePtr, IntPtr(0));
|
||||
GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12)));
|
||||
GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25)));
|
||||
GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27)));
|
||||
Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3);
|
||||
GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY));
|
||||
GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS));
|
||||
GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX));
|
||||
SetHash(glue, value, IntToTaggedPtr(k6));
|
||||
*res = k6;
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
|
||||
{
|
||||
return env_->GetBuilder()->GetHashcodeFromString(glue, value);
|
||||
|
@ -322,6 +322,7 @@ public:
|
||||
GateRef GetPropertiesArray(GateRef object);
|
||||
// SetProperties in js_object.h
|
||||
void SetPropertiesArray(VariableType type, GateRef glue, GateRef object, GateRef propsArray);
|
||||
GateRef GetHash(GateRef object);
|
||||
void SetHash(GateRef glue, GateRef object, GateRef hash);
|
||||
GateRef GetLengthOfTaggedArray(GateRef array);
|
||||
GateRef GetLengthOfJSTypedArray(GateRef array);
|
||||
@ -452,6 +453,9 @@ public:
|
||||
GateRef GetLayoutFromHClass(GateRef hClass);
|
||||
GateRef GetBitFieldFromHClass(GateRef hClass);
|
||||
GateRef GetLengthFromString(GateRef value);
|
||||
GateRef CalcHashcodeForInt(GateRef value);
|
||||
void CalcHashcodeForDouble(GateRef value, Variable *res, Label *exit);
|
||||
void CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit);
|
||||
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
|
||||
inline GateRef IsIntegerString(GateRef string);
|
||||
inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode, GateRef isInteger);
|
||||
@ -863,6 +867,7 @@ private:
|
||||
void InitializeArguments();
|
||||
void CheckDetectorName(GateRef glue, GateRef key, Label *fallthrough, Label *slow);
|
||||
bool IsCallModeSupportPGO(JSCallMode mode);
|
||||
GateRef CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits);
|
||||
|
||||
CallSignature *callSignature_ {nullptr};
|
||||
Environment *env_;
|
||||
|
@ -149,7 +149,7 @@ void EcmaVM::PreFork()
|
||||
|
||||
void EcmaVM::PostFork()
|
||||
{
|
||||
RandomGenerator::InitRandom();
|
||||
RandomGenerator::InitRandom(GetAssociatedJSThread());
|
||||
heap_->SetHeapMode(HeapMode::SHARE);
|
||||
GetAssociatedJSThread()->PostFork();
|
||||
Taskpool::GetCurrentTaskpool()->Initialize();
|
||||
|
@ -836,6 +836,11 @@ public:
|
||||
return glueData_.propertiesGrowStep_;
|
||||
}
|
||||
|
||||
void SetRandomStatePtr(uint64_t *ptr)
|
||||
{
|
||||
glueData_.randomStatePtr_ = reinterpret_cast<uintptr_t>(ptr);
|
||||
}
|
||||
|
||||
struct GlueData : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
|
||||
BCStubEntries,
|
||||
JSTaggedValue,
|
||||
@ -868,6 +873,7 @@ public:
|
||||
BuiltinEntries,
|
||||
base::AlignedBool,
|
||||
base::AlignedPointer,
|
||||
base::AlignedPointer,
|
||||
base::AlignedUint32> {
|
||||
enum class Index : size_t {
|
||||
BCStubEntriesIndex = 0,
|
||||
@ -901,6 +907,7 @@ public:
|
||||
BuiltinEntriesIndex,
|
||||
IsTracingIndex,
|
||||
unsharedConstpoolsIndex,
|
||||
RandomStatePtrIndex,
|
||||
stateAndFlagsIndex,
|
||||
NumOfMembers
|
||||
};
|
||||
@ -1087,6 +1094,11 @@ public:
|
||||
return GetOffset<static_cast<size_t>(Index::stateAndFlagsIndex)>(isArch32);
|
||||
}
|
||||
|
||||
static size_t GetRandomStatePtrOffset(bool isArch32)
|
||||
{
|
||||
return GetOffset<static_cast<size_t>(Index::RandomStatePtrIndex)>(isArch32);
|
||||
}
|
||||
|
||||
alignas(EAS) BCStubEntries bcStubEntries_;
|
||||
alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
|
||||
alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
|
||||
@ -1118,6 +1130,7 @@ public:
|
||||
alignas(EAS) BuiltinEntries builtinEntries_;
|
||||
alignas(EAS) bool isTracing_ {false};
|
||||
alignas(EAS) uintptr_t unsharedConstpools_ {0};
|
||||
alignas(EAS) uintptr_t randomStatePtr_ {0};
|
||||
alignas(EAS) ThreadStateAndFlags stateAndFlags_ {};
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64);
|
||||
|
@ -16,3 +16,4 @@ value
|
||||
-1
|
||||
-2
|
||||
undefined
|
||||
success
|
||||
|
@ -32,3 +32,40 @@ for (let i = 0; i < 4; ++i) {
|
||||
let value = map.get(i);
|
||||
print(value);
|
||||
}
|
||||
|
||||
map = new Map();
|
||||
let key = Number.parseFloat("1392210229");
|
||||
map.set(key, "success");
|
||||
let value = map.get(key);
|
||||
print(value);
|
||||
|
||||
|
||||
function check(key) {
|
||||
let irHash = ArkTools.hashCode(key);
|
||||
let rtHash = ArkTools.hashCode(key, true);
|
||||
if (irHash != rtHash) {
|
||||
throw new Error("Mismatch hash for " + key + ": expected " + rtHash + ", but got " + irHash);
|
||||
}
|
||||
}
|
||||
|
||||
check(0);
|
||||
check(1);
|
||||
check(-1);
|
||||
check(1.5);
|
||||
check(-1.5);
|
||||
check(Number.EPSILON);
|
||||
check(Number.NaN);
|
||||
check(Number.MIN_VALUE);
|
||||
check(Number.MAX_VALUE);
|
||||
check(Number.MIN_SAFE_INTEGER);
|
||||
check(Number.MIN_SAFE_INTEGER - 1);
|
||||
check(Number.MAX_SAFE_INTEGER);
|
||||
check(Number.MAX_SAFE_INTEGER + 1);
|
||||
check(Number.NaN);
|
||||
check(Number.POSITIVE_INFINITY);
|
||||
check(Number.NEGATIVE_INFINITY);
|
||||
check(Number.parseFloat("+0.0"));
|
||||
check(Number.parseFloat("-0.0"));
|
||||
|
||||
// regression test
|
||||
check(Number.parseFloat("1392210229"));
|
||||
|
Loading…
Reference in New Issue
Block a user