1// Copyright 2017 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/objects/template-objects.h" 6 7#include "src/base/functional.h" 8#include "src/execution/isolate.h" 9#include "src/heap/factory.h" 10#include "src/objects/objects-inl.h" 11#include "src/objects/property-descriptor.h" 12#include "src/objects/template-objects-inl.h" 13 14namespace v8 { 15namespace internal { 16 17// static 18Handle<JSArray> TemplateObjectDescription::GetTemplateObject( 19 Isolate* isolate, Handle<NativeContext> native_context, 20 Handle<TemplateObjectDescription> description, 21 Handle<SharedFunctionInfo> shared_info, int slot_id) { 22 uint32_t hash = shared_info->Hash(); 23 24 // Check the template weakmap to see if the template object already exists. 25 Handle<EphemeronHashTable> template_weakmap; 26 27 if (native_context->template_weakmap().IsUndefined(isolate)) { 28 template_weakmap = EphemeronHashTable::New(isolate, 1); 29 } else { 30 DisallowGarbageCollection no_gc; 31 ReadOnlyRoots roots(isolate); 32 template_weakmap = handle( 33 EphemeronHashTable::cast(native_context->template_weakmap()), isolate); 34 Object maybe_cached_template = template_weakmap->Lookup(shared_info, hash); 35 while (!maybe_cached_template.IsTheHole(roots)) { 36 CachedTemplateObject cached_template = 37 CachedTemplateObject::cast(maybe_cached_template); 38 if (cached_template.slot_id() == slot_id) { 39 return handle(cached_template.template_object(), isolate); 40 } 41 maybe_cached_template = cached_template.next(); 42 } 43 } 44 45 // Create the raw object from the {raw_strings}. 46 Handle<FixedArray> raw_strings(description->raw_strings(), isolate); 47 Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements( 48 raw_strings, PACKED_ELEMENTS, raw_strings->length(), 49 AllocationType::kOld); 50 51 // Create the template object from the {cooked_strings}. 52 Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate); 53 Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements( 54 cooked_strings, PACKED_ELEMENTS, cooked_strings->length(), 55 AllocationType::kOld); 56 57 // Freeze the {raw_object}. 58 JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked(); 59 60 // Install a "raw" data property for {raw_object} on {template_object}. 61 PropertyDescriptor raw_desc; 62 raw_desc.set_value(raw_object); 63 raw_desc.set_configurable(false); 64 raw_desc.set_enumerable(false); 65 raw_desc.set_writable(false); 66 JSArray::DefineOwnProperty(isolate, template_object, 67 isolate->factory()->raw_string(), &raw_desc, 68 Just(kThrowOnError)) 69 .ToChecked(); 70 71 // Freeze the {template_object} as well. 72 JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError) 73 .ToChecked(); 74 75 // Insert the template object into the template weakmap. 76 Handle<HeapObject> previous_cached_templates = handle( 77 HeapObject::cast(template_weakmap->Lookup(shared_info, hash)), isolate); 78 Handle<CachedTemplateObject> cached_template = CachedTemplateObject::New( 79 isolate, slot_id, template_object, previous_cached_templates); 80 template_weakmap = EphemeronHashTable::Put( 81 isolate, template_weakmap, shared_info, cached_template, hash); 82 native_context->set_template_weakmap(*template_weakmap); 83 84 return template_object; 85} 86 87Handle<CachedTemplateObject> CachedTemplateObject::New( 88 Isolate* isolate, int slot_id, Handle<JSArray> template_object, 89 Handle<HeapObject> next) { 90 DCHECK(next->IsCachedTemplateObject() || next->IsTheHole()); 91 Handle<CachedTemplateObject> result_handle = 92 Handle<CachedTemplateObject>::cast(isolate->factory()->NewStruct( 93 CACHED_TEMPLATE_OBJECT_TYPE, AllocationType::kOld)); 94 { 95 DisallowGarbageCollection no_gc; 96 auto result = *result_handle; 97 result.set_slot_id(slot_id); 98 result.set_template_object(*template_object); 99 result.set_next(*next); 100 } 101 return result_handle; 102} 103 104} // namespace internal 105} // namespace v8 106