diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index fd4b50b2c7..170156ee54 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -22,6 +22,7 @@ #include "ecmascript/class_linker/program_object-inl.h" #include "ecmascript/ecma_module.h" #include "ecmascript/ecma_string_table.h" +#include "ecmascript/global_dictionary.h" #include "ecmascript/global_env.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/global_env_constants.h" @@ -153,7 +154,7 @@ bool EcmaVM::Initialize() globalEnv->SetEmptyArray(thread_, factory_->NewEmptyArray()); globalEnv->SetEmptyLayoutInfo(thread_, factory_->CreateLayoutInfo(0)); globalEnv->SetRegisterSymbols(thread_, JSTaggedValue(SymbolTable::Create(thread_))); - globalEnv->SetGlobalRecord(thread_, JSTaggedValue(NameDictionary::Create(thread_))); + globalEnv->SetGlobalRecord(thread_, JSTaggedValue(GlobalDictionary::Create(thread_))); JSTaggedValue emptyStr = thread_->GlobalConstants()->GetEmptyString(); stringTable_->InternEmptyString(EcmaString::Cast(emptyStr.GetTaggedObject())); globalEnv->SetEmptyTaggedQueue(thread_, factory_->NewTaggedQueue(0)); diff --git a/ecmascript/ic/ic_runtime.cpp b/ecmascript/ic/ic_runtime.cpp index 33b3161800..bac8baee38 100644 --- a/ecmascript/ic/ic_runtime.cpp +++ b/ecmascript/ic/ic_runtime.cpp @@ -136,15 +136,18 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle if (receiver->IsTypedArray() || !receiver->IsJSObject()) { return JSTaggedValue::GetProperty(thread_, receiver, key).GetValue().GetTaggedValue(); } - // 1. find from global record + + // global variable find from global record firstly if (GetICKind() == ICKind::NamedGlobalLoadIC) { bool found = false; - JSTaggedValue res = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); + JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); if (found) { - return res; + ASSERT(box.IsPropertyBox()); + icAccessor_.AddGlobalRecordHandler(JSHandle(thread_, box)); + return PropertyBox::Cast(box.GetTaggedObject())->GetValue(); } } - // 2. find from global object + ObjectOperator op(GetThread(), receiver, key); auto result = JSHandle(thread_, JSObject::GetProperty(GetThread(), &op)); if (!op.IsFound() && GetICKind() == ICKind::NamedGlobalLoadIC) { @@ -176,18 +179,21 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle receiver, JSHand bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true); return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception(); } - // 1. find from global record + + // global variable find from global record firstly if (GetICKind() == ICKind::NamedGlobalStoreIC) { bool found = false; - SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); + JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue(), &found); if (found) { + ASSERT(box.IsPropertyBox()); SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); + icAccessor_.AddGlobalRecordHandler(JSHandle(thread_, box)); return JSTaggedValue::Undefined(); } } UpdateReceiverHClass(JSHandle(GetThread(), JSHandle::Cast(receiver)->GetClass())); - // 2. find from global object + ObjectOperator op(GetThread(), receiver, key); bool success = JSObject::SetProperty(&op, value, true); if (!success && GetICKind() == ICKind::NamedGlobalStoreIC) { diff --git a/ecmascript/ic/profile_type_info.cpp b/ecmascript/ic/profile_type_info.cpp index 9091b89700..6725d364e8 100644 --- a/ecmascript/ic/profile_type_info.cpp +++ b/ecmascript/ic/profile_type_info.cpp @@ -181,6 +181,12 @@ void ProfileTypeAccessor::AddGlobalHandlerKey(JSHandle key, JSHan profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue()); } +void ProfileTypeAccessor::AddGlobalRecordHandler(JSHandle handler) const +{ + uint32_t index = slotId_; + profileTypeInfo_->Set(thread_, index, handler.GetTaggedValue()); +} + void ProfileTypeAccessor::SetAsMega() const { profileTypeInfo_->Set(thread_, slotId_, JSTaggedValue::Hole()); diff --git a/ecmascript/ic/profile_type_info.h b/ecmascript/ic/profile_type_info.h index 3546a856b9..f7fecfef55 100644 --- a/ecmascript/ic/profile_type_info.h +++ b/ecmascript/ic/profile_type_info.h @@ -116,6 +116,7 @@ public: void AddHandlerWithKey(JSHandle key, JSHandle dynclass, JSHandle handler) const; void AddGlobalHandlerKey(JSHandle key, JSHandle handler) const; + void AddGlobalRecordHandler(JSHandle handler) const; JSTaggedValue GetWeakRef(JSTaggedValue value) const { diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index a9232e5d88..462d9528d6 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2640,7 +2640,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool // order: 1. global record 2. global object JSTaggedValue result = SlowRuntimeStub::LdGlobalRecord(thread, prop, &found); if (found) { - SET_ACC(result); + SET_ACC(PropertyBox::Cast(result.GetTaggedObject())->GetValue()); } else { JSTaggedValue globalResult = FastRuntimeStub::GetGlobalOwnProperty(globalObj, prop, &found); if (found) { diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 43f35cdbf2..bf9106cd8b 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -1380,16 +1380,21 @@ JSTaggedValue SlowRuntimeStub::TryUpdateGlobalRecord(JSThread *thread, JSTaggedV EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); int entry = dict->FindEntry(prop); + ASSERT(entry != -1); + if (dict->GetAttributes(entry).IsConstProps()) { - return ThrowSyntaxError(thread, " const can not be modified"); + return ThrowSyntaxError(thread, "const variable can not be modified"); } - dict->UpdateValue(thread, entry, value); + + PropertyBox *box = dict->GetBox(entry); + box->SetValue(thread, value); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::True(); } +// return box JSTaggedValue SlowRuntimeStub::LdGlobalRecord(JSThread *thread, JSTaggedValue key, bool *found) { INTERPRETER_TRACE(thread, LdGlobalRecord); @@ -1397,11 +1402,11 @@ JSTaggedValue SlowRuntimeStub::LdGlobalRecord(JSThread *thread, JSTaggedValue ke EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); int entry = dict->FindEntry(key); if (entry != -1) { *found = true; - return dict->GetValue(entry); + return JSTaggedValue(dict->GetBox(entry)); } return JSTaggedValue::Undefined(); } @@ -1413,18 +1418,28 @@ JSTaggedValue SlowRuntimeStub::StGlobalRecord(JSThread *thread, JSTaggedValue pr EcmaVM *vm = thread->GetEcmaVM(); JSHandle env = vm->GetGlobalEnv(); - NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + // cross files global record name binding judgment int entry = dict->FindEntry(prop); if (entry != -1) { - return ThrowReferenceError(thread, prop, " is not defined"); + return ThrowSyntaxError(thread, "Duplicate identifier"); } + PropertyAttributes attributes; - attributes.SetIsConstProps(isConst); + if (isConst) { + attributes.SetIsConstProps(true); + } JSHandle propHandle(thread, prop); JSHandle valueHandle(thread, value); - JSHandle dictHandle(thread, dict); - dict->PutIfAbsent(thread, dictHandle, propHandle, valueHandle, attributes); + JSHandle dictHandle(thread, dict); + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle box = factory->NewPropertyBox(valueHandle); + PropertyBoxType boxType = valueHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT; + attributes.SetBoxType(boxType); + + dict->PutIfAbsent(thread, dictHandle, propHandle, JSHandle(box), attributes); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::True(); }