OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/allocation-site-scopes.h" | 7 #include "src/allocation-site-scopes.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/compile-time-value.h" | 10 #include "src/ast/compile-time-value.h" |
11 #include "src/isolate-inl.h" | 11 #include "src/isolate-inl.h" |
12 #include "src/runtime/runtime.h" | 12 #include "src/runtime/runtime.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 static Handle<Map> ComputeObjectLiteralMap( | |
18 Handle<Context> context, | |
19 Handle<BoilerplateDescription> boilerplate_description, | |
20 bool* is_result_from_cache) { | |
21 int number_of_properties = boilerplate_description->backing_store_size(); | |
22 Isolate* isolate = context->GetIsolate(); | |
23 return isolate->factory()->ObjectLiteralMapFromCache( | |
24 context, number_of_properties, is_result_from_cache); | |
25 } | |
26 | |
27 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 17 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( |
28 Isolate* isolate, Handle<FeedbackVector> vector, | 18 Isolate* isolate, Handle<FeedbackVector> vector, |
29 Handle<BoilerplateDescription> boilerplate_description); | 19 Handle<FixedArray> compile_time_value); |
30 | 20 |
31 MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate( | 21 MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate( |
32 Isolate* isolate, Handle<FeedbackVector> vector, | 22 Isolate* isolate, Handle<FeedbackVector> vector, |
33 Handle<BoilerplateDescription> boilerplate_description, | 23 Handle<BoilerplateDescription> boilerplate_description, |
34 bool should_have_fast_elements) { | 24 bool use_fast_elements, bool has_null_prototype) { |
35 Handle<Context> context = isolate->native_context(); | 25 Handle<Context> native_context = isolate->native_context(); |
36 | 26 |
37 // In case we have function literals, we want the object to be in | 27 // In case we have function literals, we want the object to be in |
38 // slow properties mode for now. We don't go in the map cache because | 28 // slow properties mode for now. We don't go in the map cache because |
39 // maps with constant functions can't be shared if the functions are | 29 // maps with constant functions can't be shared if the functions are |
40 // not the same (which is the common case). | 30 // not the same (which is the common case). |
41 bool is_result_from_cache = false; | 31 int number_of_properties = boilerplate_description->backing_store_size(); |
42 Handle<Map> map = ComputeObjectLiteralMap(context, boilerplate_description, | 32 |
43 &is_result_from_cache); | 33 // Ignoring number_of_properties for force dictionary map with __proto__:null. |
| 34 Handle<Map> map = |
| 35 has_null_prototype |
| 36 ? handle(native_context->slow_object_with_null_prototype_map(), |
| 37 isolate) |
| 38 : isolate->factory()->ObjectLiteralMapFromCache(native_context, |
| 39 number_of_properties); |
44 | 40 |
45 PretenureFlag pretenure_flag = | 41 PretenureFlag pretenure_flag = |
46 isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED; | 42 isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED; |
47 | 43 |
48 Handle<JSObject> boilerplate = | 44 Handle<JSObject> boilerplate = |
49 isolate->factory()->NewJSObjectFromMap(map, pretenure_flag); | 45 map->is_dictionary_map() |
| 46 ? isolate->factory()->NewSlowJSObjectFromMap( |
| 47 map, number_of_properties, pretenure_flag) |
| 48 : isolate->factory()->NewJSObjectFromMap(map, pretenure_flag); |
50 | 49 |
51 // Normalize the elements of the boilerplate to save space if needed. | 50 // Normalize the elements of the boilerplate to save space if needed. |
52 if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate); | 51 if (!use_fast_elements) JSObject::NormalizeElements(boilerplate); |
53 | 52 |
54 // Add the constant properties to the boilerplate. | 53 // Add the constant properties to the boilerplate. |
55 int length = boilerplate_description->size(); | 54 int length = boilerplate_description->size(); |
56 bool should_transform = | |
57 !is_result_from_cache && boilerplate->HasFastProperties(); | |
58 bool should_normalize = should_transform; | |
59 if (should_normalize) { | |
60 // TODO(verwaest): We might not want to ever normalize here. | |
61 JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length, | |
62 "Boilerplate"); | |
63 } | |
64 // TODO(verwaest): Support tracking representations in the boilerplate. | 55 // TODO(verwaest): Support tracking representations in the boilerplate. |
65 for (int index = 0; index < length; index++) { | 56 for (int index = 0; index < length; index++) { |
66 Handle<Object> key(boilerplate_description->name(index), isolate); | 57 Handle<Object> key(boilerplate_description->name(index), isolate); |
67 Handle<Object> value(boilerplate_description->value(index), isolate); | 58 Handle<Object> value(boilerplate_description->value(index), isolate); |
68 if (value->IsBoilerplateDescription()) { | 59 if (value->IsFixedArray()) { |
69 // The value contains the boilerplate properties of a | 60 // The value contains the CompileTimeValue with the boilerplate properties |
70 // simple object or array literal. | 61 // of a simple object or array literal. |
71 Handle<BoilerplateDescription> boilerplate = | 62 Handle<FixedArray> compile_time_value = Handle<FixedArray>::cast(value); |
72 Handle<BoilerplateDescription>::cast(value); | |
73 ASSIGN_RETURN_ON_EXCEPTION( | 63 ASSIGN_RETURN_ON_EXCEPTION( |
74 isolate, value, | 64 isolate, value, |
75 CreateLiteralBoilerplate(isolate, vector, boilerplate), Object); | 65 CreateLiteralBoilerplate(isolate, vector, compile_time_value), |
| 66 Object); |
76 } | 67 } |
77 MaybeHandle<Object> maybe_result; | 68 MaybeHandle<Object> maybe_result; |
78 uint32_t element_index = 0; | 69 uint32_t element_index = 0; |
79 if (key->ToArrayIndex(&element_index)) { | 70 if (key->ToArrayIndex(&element_index)) { |
80 // Array index (uint32). | 71 // Array index (uint32). |
81 if (value->IsUninitialized(isolate)) { | 72 if (value->IsUninitialized(isolate)) { |
82 value = handle(Smi::kZero, isolate); | 73 value = handle(Smi::kZero, isolate); |
83 } | 74 } |
84 maybe_result = JSObject::SetOwnElementIgnoreAttributes( | 75 maybe_result = JSObject::SetOwnElementIgnoreAttributes( |
85 boilerplate, element_index, value, NONE); | 76 boilerplate, element_index, value, NONE); |
86 } else { | 77 } else { |
87 Handle<String> name = Handle<String>::cast(key); | 78 Handle<String> name = Handle<String>::cast(key); |
88 DCHECK(!name->AsArrayIndex(&element_index)); | 79 DCHECK(!name->AsArrayIndex(&element_index)); |
89 maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, | 80 maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, |
90 value, NONE); | 81 value, NONE); |
91 } | 82 } |
92 RETURN_ON_EXCEPTION(isolate, maybe_result, Object); | 83 RETURN_ON_EXCEPTION(isolate, maybe_result, Object); |
93 } | 84 } |
94 | 85 |
95 // Transform to fast properties if necessary. For object literals with | 86 if (map->is_dictionary_map() && !has_null_prototype) { |
96 // containing function literals we defer this operation until after all | 87 // TODO(cbruni): avoid making the boilerplate fast again, the clone stub |
97 // computed properties have been assigned so that we can generate | 88 // supports dict-mode objects directly. |
98 // constant function properties. | |
99 if (should_transform) { | |
100 JSObject::MigrateSlowToFast(boilerplate, | 89 JSObject::MigrateSlowToFast(boilerplate, |
101 boilerplate->map()->unused_property_fields(), | 90 boilerplate->map()->unused_property_fields(), |
102 "FastLiteral"); | 91 "FastLiteral"); |
103 } | 92 } |
104 return boilerplate; | 93 return boilerplate; |
105 } | 94 } |
106 | 95 |
107 static MaybeHandle<Object> CreateArrayLiteralBoilerplate( | 96 static MaybeHandle<Object> CreateArrayLiteralBoilerplate( |
108 Isolate* isolate, Handle<FeedbackVector> vector, | 97 Isolate* isolate, Handle<FeedbackVector> vector, |
109 Handle<ConstantElementsPair> elements) { | 98 Handle<ConstantElementsPair> elements) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 } | 136 } |
148 #endif | 137 #endif |
149 } else { | 138 } else { |
150 Handle<FixedArray> fixed_array_values = | 139 Handle<FixedArray> fixed_array_values = |
151 Handle<FixedArray>::cast(constant_elements_values); | 140 Handle<FixedArray>::cast(constant_elements_values); |
152 Handle<FixedArray> fixed_array_values_copy = | 141 Handle<FixedArray> fixed_array_values_copy = |
153 isolate->factory()->CopyFixedArray(fixed_array_values); | 142 isolate->factory()->CopyFixedArray(fixed_array_values); |
154 copied_elements_values = fixed_array_values_copy; | 143 copied_elements_values = fixed_array_values_copy; |
155 FOR_WITH_HANDLE_SCOPE( | 144 FOR_WITH_HANDLE_SCOPE( |
156 isolate, int, i = 0, i, i < fixed_array_values->length(), i++, { | 145 isolate, int, i = 0, i, i < fixed_array_values->length(), i++, { |
157 if (fixed_array_values->get(i)->IsBoilerplateDescription()) { | 146 if (fixed_array_values->get(i)->IsFixedArray()) { |
158 // The value contains the boilerplate properties of a | 147 // The value contains the CompileTimeValue with the |
159 // simple object or array literal. | 148 // boilerplate description of a simple object or |
160 Handle<BoilerplateDescription> boilerplate( | 149 // array literal. |
161 BoilerplateDescription::cast(fixed_array_values->get(i))); | 150 Handle<FixedArray> compile_time_value( |
| 151 FixedArray::cast(fixed_array_values->get(i))); |
162 Handle<Object> result; | 152 Handle<Object> result; |
163 ASSIGN_RETURN_ON_EXCEPTION( | 153 ASSIGN_RETURN_ON_EXCEPTION( |
164 isolate, result, | 154 isolate, result, |
165 CreateLiteralBoilerplate(isolate, vector, boilerplate), | 155 CreateLiteralBoilerplate(isolate, vector, compile_time_value), |
166 Object); | 156 Object); |
167 fixed_array_values_copy->set(i, *result); | 157 fixed_array_values_copy->set(i, *result); |
168 } | 158 } |
169 }); | 159 }); |
170 } | 160 } |
171 } | 161 } |
172 object->set_elements(*copied_elements_values); | 162 object->set_elements(*copied_elements_values); |
173 object->set_length(Smi::FromInt(copied_elements_values->length())); | 163 object->set_length(Smi::FromInt(copied_elements_values->length())); |
174 | 164 |
175 JSObject::ValidateElements(object); | 165 JSObject::ValidateElements(object); |
176 return object; | 166 return object; |
177 } | 167 } |
178 | 168 |
179 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 169 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( |
180 Isolate* isolate, Handle<FeedbackVector> vector, | 170 Isolate* isolate, Handle<FeedbackVector> vector, |
181 Handle<BoilerplateDescription> array) { | 171 Handle<FixedArray> compile_time_value) { |
182 Handle<HeapObject> elements = CompileTimeValue::GetElements(array); | 172 Handle<HeapObject> elements = |
183 switch (CompileTimeValue::GetLiteralType(array)) { | 173 CompileTimeValue::GetElements(compile_time_value); |
184 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: { | 174 int flags = CompileTimeValue::GetLiteralTypeFlags(compile_time_value); |
185 Handle<BoilerplateDescription> props = | 175 if (flags == CompileTimeValue::kArrayLiteralFlag) { |
186 Handle<BoilerplateDescription>::cast(elements); | 176 Handle<ConstantElementsPair> elems = |
187 return CreateObjectLiteralBoilerplate(isolate, vector, props, true); | 177 Handle<ConstantElementsPair>::cast(elements); |
188 } | 178 return CreateArrayLiteralBoilerplate(isolate, vector, elems); |
189 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: { | |
190 Handle<BoilerplateDescription> props = | |
191 Handle<BoilerplateDescription>::cast(elements); | |
192 return CreateObjectLiteralBoilerplate(isolate, vector, props, false); | |
193 } | |
194 case CompileTimeValue::ARRAY_LITERAL: { | |
195 Handle<ConstantElementsPair> elems = | |
196 Handle<ConstantElementsPair>::cast(elements); | |
197 return CreateArrayLiteralBoilerplate(isolate, vector, elems); | |
198 } | |
199 default: | |
200 UNREACHABLE(); | |
201 return MaybeHandle<Object>(); | |
202 } | 179 } |
| 180 Handle<BoilerplateDescription> props = |
| 181 Handle<BoilerplateDescription>::cast(elements); |
| 182 bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; |
| 183 bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0; |
| 184 return CreateObjectLiteralBoilerplate(isolate, vector, props, |
| 185 use_fast_elements, has_null_prototype); |
203 } | 186 } |
204 | 187 |
205 | 188 |
206 RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) { | 189 RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) { |
207 HandleScope scope(isolate); | 190 HandleScope scope(isolate); |
208 DCHECK_EQ(4, args.length()); | 191 DCHECK_EQ(4, args.length()); |
209 CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0); | 192 CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0); |
210 CONVERT_SMI_ARG_CHECKED(index, 1); | 193 CONVERT_SMI_ARG_CHECKED(index, 1); |
211 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2); | 194 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2); |
212 CONVERT_SMI_ARG_CHECKED(flags, 3); | 195 CONVERT_SMI_ARG_CHECKED(flags, 3); |
(...skipping 13 matching lines...) Expand all Loading... |
226 | 209 |
227 RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) { | 210 RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) { |
228 HandleScope scope(isolate); | 211 HandleScope scope(isolate); |
229 DCHECK_EQ(4, args.length()); | 212 DCHECK_EQ(4, args.length()); |
230 CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0); | 213 CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0); |
231 CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 214 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
232 CONVERT_ARG_HANDLE_CHECKED(BoilerplateDescription, boilerplate_description, | 215 CONVERT_ARG_HANDLE_CHECKED(BoilerplateDescription, boilerplate_description, |
233 2); | 216 2); |
234 CONVERT_SMI_ARG_CHECKED(flags, 3); | 217 CONVERT_SMI_ARG_CHECKED(flags, 3); |
235 Handle<FeedbackVector> vector(closure->feedback_vector(), isolate); | 218 Handle<FeedbackVector> vector(closure->feedback_vector(), isolate); |
236 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; | 219 bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; |
237 bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0; | 220 bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0; |
| 221 bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0; |
238 | 222 |
239 FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index)); | 223 FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index)); |
240 CHECK(literals_slot.ToInt() < vector->slot_count()); | 224 CHECK(literals_slot.ToInt() < vector->slot_count()); |
241 | 225 |
242 // Check if boilerplate exists. If not, create it first. | 226 // Check if boilerplate exists. If not, create it first. |
243 Handle<Object> literal_site(vector->Get(literals_slot), isolate); | 227 Handle<Object> literal_site(vector->Get(literals_slot), isolate); |
244 Handle<AllocationSite> site; | 228 Handle<AllocationSite> site; |
245 Handle<JSObject> boilerplate; | 229 Handle<JSObject> boilerplate; |
246 if (literal_site->IsUndefined(isolate)) { | 230 if (literal_site->IsUndefined(isolate)) { |
247 Handle<Object> raw_boilerplate; | 231 Handle<Object> raw_boilerplate; |
248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 232 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
249 isolate, raw_boilerplate, | 233 isolate, raw_boilerplate, |
250 CreateObjectLiteralBoilerplate(isolate, vector, boilerplate_description, | 234 CreateObjectLiteralBoilerplate(isolate, vector, boilerplate_description, |
251 should_have_fast_elements)); | 235 use_fast_elements, has_null_prototype)); |
252 boilerplate = Handle<JSObject>::cast(raw_boilerplate); | 236 boilerplate = Handle<JSObject>::cast(raw_boilerplate); |
253 | 237 |
254 AllocationSiteCreationContext creation_context(isolate); | 238 AllocationSiteCreationContext creation_context(isolate); |
255 site = creation_context.EnterNewScope(); | 239 site = creation_context.EnterNewScope(); |
256 RETURN_FAILURE_ON_EXCEPTION( | 240 RETURN_FAILURE_ON_EXCEPTION( |
257 isolate, JSObject::DeepWalk(boilerplate, &creation_context)); | 241 isolate, JSObject::DeepWalk(boilerplate, &creation_context)); |
258 creation_context.ExitScope(site, boilerplate); | 242 creation_context.ExitScope(site, boilerplate); |
259 | 243 |
260 // Update the functions literal and return the boilerplate. | 244 // Update the functions literal and return the boilerplate. |
261 vector->Set(literals_slot, *site); | 245 vector->Set(literals_slot, *site); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 | 335 |
352 Handle<FeedbackVector> vector(closure->feedback_vector(), isolate); | 336 Handle<FeedbackVector> vector(closure->feedback_vector(), isolate); |
353 FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index)); | 337 FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index)); |
354 RETURN_RESULT_OR_FAILURE( | 338 RETURN_RESULT_OR_FAILURE( |
355 isolate, CreateArrayLiteralImpl(isolate, vector, literals_slot, elements, | 339 isolate, CreateArrayLiteralImpl(isolate, vector, literals_slot, elements, |
356 ArrayLiteral::kShallowElements)); | 340 ArrayLiteral::kShallowElements)); |
357 } | 341 } |
358 | 342 |
359 } // namespace internal | 343 } // namespace internal |
360 } // namespace v8 | 344 } // namespace v8 |
OLD | NEW |