Serenity Operating System
1/*
2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <LibJS/Interpreter.h>
28#include <LibJS/Runtime/Shape.h>
29
30namespace JS {
31
32Shape* Shape::create_put_transition(const FlyString& property_name, u8 property_attributes)
33{
34 auto* new_shape = m_forward_transitions.get(property_name).value_or(nullptr);
35 if (new_shape && new_shape->m_property_attributes == property_attributes)
36 return new_shape;
37 new_shape = heap().allocate<Shape>(this, property_name, property_attributes);
38 m_forward_transitions.set(property_name, new_shape);
39 return new_shape;
40}
41
42Shape* Shape::create_prototype_transition(Object* new_prototype)
43{
44 return heap().allocate<Shape>(this, new_prototype);
45}
46
47Shape::Shape()
48{
49}
50
51Shape::Shape(Shape* previous_shape, const FlyString& property_name, u8 property_attributes)
52 : m_previous(previous_shape)
53 , m_property_name(property_name)
54 , m_property_attributes(property_attributes)
55 , m_prototype(previous_shape->m_prototype)
56{
57}
58
59Shape::Shape(Shape* previous_shape, Object* new_prototype)
60 : m_previous(previous_shape)
61 , m_prototype(new_prototype)
62{
63}
64
65Shape::~Shape()
66{
67}
68
69void Shape::visit_children(Cell::Visitor& visitor)
70{
71 Cell::visit_children(visitor);
72 if (m_prototype)
73 visitor.visit(m_prototype);
74 if (m_previous)
75 visitor.visit(m_previous);
76 for (auto& it : m_forward_transitions)
77 visitor.visit(it.value);
78}
79
80Optional<PropertyMetadata> Shape::lookup(const FlyString& property_name) const
81{
82 return property_table().get(property_name);
83}
84
85const HashMap<FlyString, PropertyMetadata>& Shape::property_table() const
86{
87 ensure_property_table();
88 return *m_property_table;
89}
90
91size_t Shape::property_count() const
92{
93 return property_table().size();
94}
95
96void Shape::ensure_property_table() const
97{
98 if (m_property_table)
99 return;
100 m_property_table = make<HashMap<FlyString, PropertyMetadata>>();
101
102 // FIXME: We need to make sure the GC doesn't collect the transition chain as we're building it.
103 // Maybe some kind of RAII "prevent GC for a moment" helper thingy?
104
105 Vector<const Shape*> transition_chain;
106 for (auto* shape = this; shape->m_previous; shape = shape->m_previous) {
107 transition_chain.append(shape);
108 }
109
110 u32 next_offset = 0;
111 for (ssize_t i = transition_chain.size() - 1; i >= 0; --i) {
112 auto* shape = transition_chain[i];
113 if (shape->m_property_name.is_null()) {
114 // Ignore prototype transitions as they don't affect the key map.
115 continue;
116 }
117 m_property_table->set(shape->m_property_name, { next_offset++, shape->m_property_attributes });
118 }
119}
120
121}