66#include < fstream>
77#include < string>
88#include < string_view>
9+ #include < unordered_map>
910
1011namespace next2d ::v8util {
1112
@@ -18,6 +19,32 @@ inline v8::Local<v8::String> Str(v8::Isolate* isolate, std::string_view s)
1819 ).ToLocalChecked ();
1920}
2021
22+ // プロパティ名 v8::String のキャッシュ。
23+ // バインディングのディスクリプタ解析 (webgpu::Prop/HasProp/U32 等) は毎フレーム
24+ // 数千回呼ばれ、その度に NewFromUtf8 が JS ヒープ確保 + ハッシュ計算をしていた。
25+ // internalized string (isolate 内で重複排除され、プロパティ検索がポインタ比較で済む)
26+ // を v8::Eternal で保持し、2 回目以降はハッシュマップ参照のみにする。
27+ // jitless では JS↔C++ 境界のコストが相対的に重いため、ここの削減が全体に効く。
28+ // キーは内容比較 (std::string) なので呼び出し元がリテラル以外を渡しても安全。
29+ // ホストは単一 Isolate 運用 (worker も同一 Isolate の別 Context) だが、
30+ // 念のため isolate が変わったらキャッシュを破棄する (Eternal は isolate 寿命に紐づく)。
31+ inline v8::Local<v8::String> PropName (v8::Isolate* isolate, const char * key)
32+ {
33+ static v8::Isolate* cached_isolate = nullptr ;
34+ static std::unordered_map<std::string, v8::Eternal<v8::String>> cache;
35+ if (cached_isolate != isolate) {
36+ cache.clear ();
37+ cached_isolate = isolate;
38+ }
39+ auto it = cache.find (key);
40+ if (it == cache.end ()) {
41+ v8::Local<v8::String> s = v8::String::NewFromUtf8 (
42+ isolate, key, v8::NewStringType::kInternalized ).ToLocalChecked ();
43+ it = cache.emplace (key, v8::Eternal<v8::String>(isolate, s)).first ;
44+ }
45+ return it->second .Get (isolate);
46+ }
47+
2148// v8::Value -> std::string (UTF-8)
2249inline std::string ToStdString (v8::Isolate* isolate, v8::Local<v8::Value> value)
2350{
0 commit comments