From 127cc661c0605189e939ff9122cc92b051c9e316 Mon Sep 17 00:00:00 2001 From: lifansheng Date: Fri, 10 Sep 2021 11:25:35 +0800 Subject: [PATCH] add globalrecord Signed-off-by: lifansheng --- ecmascript/ecma_isa.yaml | 15 +++++ ecmascript/ecma_vm.cpp | 2 + ecmascript/global_env.h | 3 +- ecmascript/ic/ic_runtime.cpp | 13 +++- ecmascript/interpreter/interpreter-inl.h | 50 ++++++++++++++- ecmascript/interpreter/interpreter.h | 3 + ecmascript/interpreter/slow_runtime_stub.cpp | 62 ++++++++++++++++++- ecmascript/interpreter/slow_runtime_stub.h | 3 + .../debugger_instruction_dispatch.inl | 6 +- .../debugger_instruction_handler.inl | 15 +++++ .../templates/instruction_dispatch.inl | 6 +- ecmascript/property_attributes.h | 12 +++- 12 files changed, 175 insertions(+), 15 deletions(-) diff --git a/ecmascript/ecma_isa.yaml b/ecmascript/ecma_isa.yaml index 56ca07bf86..3a59436ab3 100644 --- a/ecmascript/ecma_isa.yaml +++ b/ecmascript/ecma_isa.yaml @@ -562,3 +562,18 @@ groups: acc: inout:top prefix: ecma format: [pref_op_none] + - sig: ecma.stconsttoglobalrecord string_id + acc: in:top + prefix: ecma + format: [pref_op_id_32] + properties: [string_id] + - sig: ecma.stlettoglobalrecord string_id + acc: in:top + prefix: ecma + format: [pref_op_id_32] + properties: [string_id] + - sig: ecma.stclasstoglobalrecord string_id + acc: in:top + prefix: ecma + format: [pref_op_id_32] + properties: [string_id] diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 2fde7aa0d3..31bb8274e6 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -33,6 +33,7 @@ #include "ecmascript/js_invoker.h" #include "ecmascript/js_thread.h" #include "ecmascript/mem/heap.h" +#include "ecmascript/tagged_dictionary.h" #include "ecmascript/object_factory.h" #include "ecmascript/regexp/regexp_parser_cache.h" #include "ecmascript/runtime_call_id.h" @@ -152,6 +153,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_))); JSTaggedValue emptyStr = thread_->GlobalConstants()->GetEmptyString(); stringTable_->InternEmptyString(EcmaString::Cast(emptyStr.GetTaggedObject())); globalEnv->SetEmptyTaggedQueue(thread_, factory_->NewTaggedQueue(0)); diff --git a/ecmascript/global_env.h b/ecmascript/global_env.h index 3d9c225b67..a2d4ce9fc7 100644 --- a/ecmascript/global_env.h +++ b/ecmascript/global_env.h @@ -137,7 +137,8 @@ class JSThread; V(JSTaggedValue, JSIntlBoundFunctionClass, JS_INTL_BOUND_FUNCTION_CLASS) \ V(JSTaggedValue, NumberFormatLocales, NUMBER_FORMAT_LOCALES_INDEX) \ V(JSTaggedValue, DateTimeFormatLocales, DATE_TIMEFORMAT_LOCALES_INDEX) \ - V(JSTaggedValue, JSNativeObjectClass, JS_NATIVE_OBJECT_CLASS) + V(JSTaggedValue, JSNativeObjectClass, JS_NATIVE_OBJECT_CLASS) \ + V(JSTaggedValue, GlobalRecord, GLOBAL_RECORD) class GlobalEnv : public TaggedObject { public: diff --git a/ecmascript/ic/ic_runtime.cpp b/ecmascript/ic/ic_runtime.cpp index 2c3b96859a..fa273a964a 100644 --- a/ecmascript/ic/ic_runtime.cpp +++ b/ecmascript/ic/ic_runtime.cpp @@ -25,7 +25,7 @@ #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_typed_array.h" #include "ecmascript/object_factory-inl.h" - +#include "ecmascript/tagged_dictionary.h" namespace panda::ecmascript { #define TRACE_IC 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -134,12 +134,19 @@ void ICRuntime::TraceIC([[maybe_unused]] JSHandle receiver, JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle key) { if (receiver->IsTypedArray() || !receiver->IsJSObject()) { - return JSTaggedValue::GetProperty(GetThread(), receiver, key).GetValue().GetTaggedValue(); + return JSTaggedValue::GetProperty(thread_, receiver, key).GetValue().GetTaggedValue(); } ObjectOperator op(GetThread(), receiver, key); auto result = JSHandle(thread_, JSObject::GetProperty(GetThread(), &op)); if (!op.IsFound() && GetICKind() == ICKind::NamedGlobalLoadIC) { - return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined"); + EcmaVM *vm = thread_->GetEcmaVM(); + JSHandle env = vm->GetGlobalEnv(); + NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + int entry = dict->FindEntry(key.GetTaggedValue()); + if (entry == -1) { + return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined"); + } + return dict->GetValue(entry); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread()); // ic-switch diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index e0200af998..54abf537ee 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -2668,9 +2668,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool bool found = false; FastRuntimeStub::GetGlobalOwnProperty(globalObj, propKey, &found); if (!found) { - // slow path will throw exception - JSTaggedValue res = SlowRuntimeStub::TryStGlobalByName(thread, propKey); + // find globalreord + JSTaggedValue value = GET_ACC(); + SAVE_ACC(); + JSTaggedValue res = SlowRuntimeStub::UpdateGlobalRecord(thread, propKey, value); INTERPRETER_RETURN_IF_ABRUPT(res); + RESTORE_ACC(); } else { JSTaggedValue value = GET_ACC(); SAVE_ACC(); @@ -2680,6 +2683,49 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool } DISPATCH(BytecodeInstruction::Format::PREF_ID32); } + + HANDLE_OPCODE(HANDLE_STCONSTTOGLOBALRECORD_PREF_ID32) { + uint32_t stringId = READ_INST_32_1(); + JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); + LOG_INST() << "intrinsics::stconsttoglobalrecord" + << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())); + + JSTaggedValue value = GET_ACC(); + SAVE_ACC(); + JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, true); + INTERPRETER_RETURN_IF_ABRUPT(res); + RESTORE_ACC(); + DISPATCH(BytecodeInstruction::Format::PREF_ID32); + } + + HANDLE_OPCODE(HANDLE_STLETTOGLOBALRECORD_PREF_ID32) { + uint32_t stringId = READ_INST_32_1(); + JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); + LOG_INST() << "intrinsics::stlettoglobalrecord" + << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())); + + JSTaggedValue value = GET_ACC(); + SAVE_ACC(); + JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, false); + INTERPRETER_RETURN_IF_ABRUPT(res); + RESTORE_ACC(); + DISPATCH(BytecodeInstruction::Format::PREF_ID32); + } + + HANDLE_OPCODE(HANDLE_STCLASSTOGLOBALRECORD_PREF_ID32) { + uint32_t stringId = READ_INST_32_1(); + JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); + LOG_INST() << "intrinsics::stclasstoglobalrecord" + << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())); + + JSTaggedValue value = GET_ACC(); + SAVE_ACC(); + JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, false); + INTERPRETER_RETURN_IF_ABRUPT(res); + RESTORE_ACC(); + DISPATCH(BytecodeInstruction::Format::PREF_ID32); + } + HANDLE_OPCODE(HANDLE_LDGLOBALVAR_PREF_ID32) { uint32_t stringId = READ_INST_32_1(); JSTaggedValue propKey = constpool->GetObjectFromCache(stringId); diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index ab6ecb8f6d..62964b5a7d 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -211,6 +211,9 @@ enum EcmaOpcode { CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8, ISTRUE_PREF, ISFALSE_PREF, + STCONSTTOGLOBALRECORD_PREF_ID32, + STLETTOGLOBALRECORD_PREF_ID32, + STCLASSTOGLOBALRECORD_PREF_ID32, MOV_DYN_V8_V8, MOV_DYN_V16_V16, LDA_STR_ID32, diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 405dd0c092..fe35ee66ea 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -37,6 +37,7 @@ #include "ecmascript/js_proxy.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" +#include "ecmascript/tagged_dictionary.h" #include "ecmascript/runtime_call_id.h" #include "ecmascript/template_string.h" #include "ecmascript/vmstat/runtime_stat.h" @@ -1283,10 +1284,18 @@ JSTaggedValue SlowRuntimeStub::TryLdGlobalByName(JSThread *thread, JSTaggedValue JSHandle obj(thread, global.GetTaggedObject()->GetClass()->GetPrototype()); JSHandle propHandle(thread, prop); OperationResult res = JSTaggedValue::GetProperty(thread, obj, propHandle); - if (!res.GetPropertyMetaData().IsFound()) { + if (res.GetPropertyMetaData().IsFound()) { + return res.GetValue().GetTaggedValue(); + } + + EcmaVM *vm = thread->GetEcmaVM(); + JSHandle env = vm->GetGlobalEnv(); + NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + int entry = dict->FindEntry(propHandle.GetTaggedValue()); + if (entry == -1) { return ThrowReferenceError(thread, prop, " is not defined"); } - return res.GetValue().GetTaggedValue(); + return dict->GetValue(entry); } JSTaggedValue SlowRuntimeStub::TryStGlobalByName(JSThread *thread, JSTaggedValue prop) @@ -1319,6 +1328,48 @@ JSTaggedValue SlowRuntimeStub::StGlobalVar(JSThread *thread, JSTaggedValue prop, return JSTaggedValue::True(); } +JSTaggedValue SlowRuntimeStub::UpdateGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value) +{ + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + EcmaVM *vm = thread->GetEcmaVM(); + JSHandle env = vm->GetGlobalEnv(); + NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + + int entry = dict->FindEntry(prop); + if (entry == -1) { + return ThrowReferenceError(thread, prop, " is not defined"); + } + if (dict->GetAttributes(entry).IsConstProps()) { + return ThrowSyntaxError(thread, " const can not be modified"); + } + dict->UpdateValue(thread, entry, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return JSTaggedValue::True(); +} + +JSTaggedValue SlowRuntimeStub::StGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value, bool isConst) +{ + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + EcmaVM *vm = thread->GetEcmaVM(); + JSHandle env = vm->GetGlobalEnv(); + NameDictionary *dict = NameDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject()); + + int entry = dict->FindEntry(prop); + if (entry != -1) { + return ThrowReferenceError(thread, prop, " is not defined"); + } + PropertyAttributes attributes; + attributes.SetIsConstProps(isConst); + JSHandle propHandle(thread, prop); + JSHandle valueHandle(thread, value); + JSHandle dictHandle(thread, dict); + dict->PutIfAbsent(thread, dictHandle, propHandle, valueHandle, attributes); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return JSTaggedValue::True(); +} + JSTaggedValue SlowRuntimeStub::ThrowReferenceError(JSThread *thread, JSTaggedValue prop, const char *desc) { [[maybe_unused]] EcmaHandleScope handleScope(thread); @@ -1339,6 +1390,13 @@ JSTaggedValue SlowRuntimeStub::ThrowTypeError(JSThread *thread, const char *mess THROW_TYPE_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception()); } +JSTaggedValue SlowRuntimeStub::ThrowSyntaxError(JSThread *thread, const char *message) +{ + [[maybe_unused]] EcmaHandleScope handleScope(thread); + ASSERT_NO_ABRUPT_COMPLETION(thread); + THROW_SYNTAX_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception()); +} + JSTaggedValue SlowRuntimeStub::StArraySpread(JSThread *thread, JSTaggedValue dst, JSTaggedValue index, JSTaggedValue src) { diff --git a/ecmascript/interpreter/slow_runtime_stub.h b/ecmascript/interpreter/slow_runtime_stub.h index 32b5704db3..e584705532 100644 --- a/ecmascript/interpreter/slow_runtime_stub.h +++ b/ecmascript/interpreter/slow_runtime_stub.h @@ -121,6 +121,8 @@ public: static JSTaggedValue TryStGlobalByName(JSThread *thread, JSTaggedValue prop); static JSTaggedValue LdGlobalVar(JSThread *thread, JSTaggedValue global, JSTaggedValue prop); static JSTaggedValue StGlobalVar(JSThread *thread, JSTaggedValue prop, JSTaggedValue value); + static JSTaggedValue StGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value, bool isConst); + static JSTaggedValue UpdateGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value); static JSTaggedValue StArraySpread(JSThread *thread, JSTaggedValue dst, JSTaggedValue index, JSTaggedValue src); static JSTaggedValue DefineGeneratorFunc(JSThread *thread, JSFunction *func); @@ -145,6 +147,7 @@ public: private: static JSTaggedValue ThrowTypeError(JSThread *thread, const char *message); + static JSTaggedValue ThrowSyntaxError(JSThread *thread, const char *message); static JSTaggedValue GetCallSpreadArgs(JSThread *thread, JSTaggedValue array); }; } // namespace panda::ecmascript diff --git a/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl b/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl index c9111ef78f..bb5386e842 100644 --- a/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl +++ b/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl @@ -141,6 +141,9 @@ &&DEBUG_HANDLE_CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8, &&DEBUG_HANDLE_ISTRUE_PREF, &&DEBUG_HANDLE_ISFALSE_PREF, + &&DEBUG_HANDLE_STCONSTTOGLOBALRECORD_PREF_ID32, + &&DEBUG_HANDLE_STLETTOGLOBALRECORD_PREF_ID32, + &&DEBUG_HANDLE_STCLASSTOGLOBALRECORD_PREF_ID32, &&DEBUG_HANDLE_MOV_DYN_V8_V8, &&DEBUG_HANDLE_MOV_DYN_V16_V16, &&DEBUG_HANDLE_LDA_STR_ID32, @@ -266,6 +269,3 @@ &&DEBUG_HANDLE_OVERFLOW, &&DEBUG_HANDLE_OVERFLOW, &&DEBUG_HANDLE_OVERFLOW, - &&DEBUG_HANDLE_OVERFLOW, - &&DEBUG_HANDLE_OVERFLOW, - &&DEBUG_HANDLE_OVERFLOW, diff --git a/ecmascript/interpreter/templates/debugger_instruction_handler.inl b/ecmascript/interpreter/templates/debugger_instruction_handler.inl index 1c03309f21..60d3cac4a8 100644 --- a/ecmascript/interpreter/templates/debugger_instruction_handler.inl +++ b/ecmascript/interpreter/templates/debugger_instruction_handler.inl @@ -653,6 +653,21 @@ NOTIFY_DEBUGGER_EVENT(); REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::ISFALSE_PREF); } + HANDLE_OPCODE(DEBUG_HANDLE_STCONSTTOGLOBALRECORD_PREF_ID32) + { + NOTIFY_DEBUGGER_EVENT(); + REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::STCONSTTOGLOBALRECORD_PREF_ID32); + } + HANDLE_OPCODE(DEBUG_HANDLE_STLETTOGLOBALRECORD_PREF_ID32) + { + NOTIFY_DEBUGGER_EVENT(); + REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::STLETTOGLOBALRECORD_PREF_ID32); + } + HANDLE_OPCODE(DEBUG_HANDLE_STCLASSTOGLOBALRECORD_PREF_ID32) + { + NOTIFY_DEBUGGER_EVENT(); + REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::STCLASSTOGLOBALRECORD_PREF_ID32); + } HANDLE_OPCODE(DEBUG_HANDLE_MOV_DYN_V8_V8) { NOTIFY_DEBUGGER_EVENT(); diff --git a/ecmascript/interpreter/templates/instruction_dispatch.inl b/ecmascript/interpreter/templates/instruction_dispatch.inl index dfdfb40bae..a9599b0c7a 100644 --- a/ecmascript/interpreter/templates/instruction_dispatch.inl +++ b/ecmascript/interpreter/templates/instruction_dispatch.inl @@ -141,6 +141,9 @@ &&HANDLE_CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8, &&HANDLE_ISTRUE_PREF, &&HANDLE_ISFALSE_PREF, + &&HANDLE_STCONSTTOGLOBALRECORD_PREF_ID32, + &&HANDLE_STLETTOGLOBALRECORD_PREF_ID32, + &&HANDLE_STCLASSTOGLOBALRECORD_PREF_ID32, &&HANDLE_MOV_DYN_V8_V8, &&HANDLE_MOV_DYN_V16_V16, &&HANDLE_LDA_STR_ID32, @@ -266,6 +269,3 @@ &&HANDLE_OVERFLOW, &&HANDLE_OVERFLOW, &&HANDLE_OVERFLOW, - &&HANDLE_OVERFLOW, - &&HANDLE_OVERFLOW, - &&HANDLE_OVERFLOW, diff --git a/ecmascript/property_attributes.h b/ecmascript/property_attributes.h index b7d07eb1b2..ef272fb6cb 100644 --- a/ecmascript/property_attributes.h +++ b/ecmascript/property_attributes.h @@ -76,7 +76,7 @@ public: static constexpr uint32_t NORMAL_ATTR_BITS = 18; using NormalAttrField = BitField; using SortedIndexField = OffsetField::NextField; // 28 - + using IsConstPropsField = SortedIndexField::NextFlag; // 29 // dictionary mode, include global using PropertyBoxTypeField = PropertyMetaDataField::NextField; // 2: 2 bits, 5-6 using DictionaryOrderField = PropertyBoxTypeField::NextField; // 26 @@ -217,6 +217,16 @@ public: return IsInlinedPropsField::Get(value_); } + inline void SetIsConstProps(bool flag) + { + IsConstPropsField::Set(flag, &value_); + } + + inline bool IsConstProps() const + { + return IsConstPropsField::Get(value_); + } + inline void SetRepresentation(Representation representation) { RepresentationField::Set(representation, &value_); -- Gitee